Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1.  
  2. #include <stdint.h>
  3. #include <libavcodec/avcodec.h>
  4. #include <libavformat/avformat.h>
  5. #include <libswscale/swscale.h>
  6.  
  7. #include "fplay.h"
  8.  
  9. void video_thread(void *param);
  10.  
  11. void draw_bitmap(void *bitmap, int x, int y, int w, int h)
  12. {
  13.     __asm__ __volatile__(
  14.     "int $0x40"
  15.     ::"a"(7), "b"(bitmap),
  16.       "c"((w << 16) | h),
  17.       "d"((x << 16) | y));
  18. }
  19.  
  20. typedef struct
  21. {
  22.     AVFrame       *frame;
  23.     uint8_t       *buffer;
  24.     double         pts;
  25.     volatile int   ready;
  26. }vframe_t;
  27.  
  28. vframe_t           frames[8];
  29.  
  30. struct SwsContext *cvt_ctx;
  31.  
  32. int vfx    = 0;
  33. int dfx    = 0;
  34.  
  35. int width;
  36. int height;
  37.  
  38. AVRational video_time_base;
  39. AVFrame  *Frame;
  40.  
  41. int init_video(AVCodecContext *ctx)
  42. {
  43.     uint32_t   size;
  44.     int        i;
  45.  
  46.     width = ctx->width;
  47.     height = ctx->height;
  48.  
  49.     printf("w = %d  h = %d\n\r", width, height);
  50.  
  51.     Frame = avcodec_alloc_frame();
  52.     if ( Frame == NULL )
  53.     {
  54.         printf("Cannot alloc video buffer\n\r");
  55.         return 0;
  56.     };
  57.  
  58.     cvt_ctx = sws_getContext(
  59.                             ctx->width,
  60.                             ctx->height,
  61.                             ctx->pix_fmt,
  62.                             ctx->width,
  63.                             ctx->height,
  64.                             PIX_FMT_BGR24,
  65.                             SWS_BILINEAR,
  66.                             NULL, NULL, NULL);
  67.     if(cvt_ctx == NULL)
  68.     {
  69.             printf("Cannot initialize the conversion context!\n");
  70.             return 0;
  71.     }
  72.  
  73.     size = avpicture_get_size(PIX_FMT_RGB24, ctx->width, ctx->height);
  74.  
  75.     for( i=0; i < 8; i++)
  76.     {
  77.         AVFrame   *frame;
  78.  
  79.         frame = avcodec_alloc_frame();
  80.  
  81.         if( frame )
  82.         {
  83.             uint8_t *buffer = (uint8_t*)av_malloc(size);
  84.  
  85.             if( buffer )
  86.             {
  87.                 avpicture_fill((AVPicture *)frame, buffer, PIX_FMT_BGR24,
  88.                                ctx->width, ctx->height);
  89.  
  90.                 frames[i].frame  = frame;
  91.                 frames[i].buffer = buffer;
  92.                 frames[i].pts = 0;
  93.                 frames[i].ready  = 0;
  94.                 continue;
  95.             };
  96.         };
  97.         printf("Cannot alloc frame buffer\n\r");
  98.         return 0;
  99.     };
  100.  
  101.     create_thread(video_thread, 0, 163840);
  102.  
  103.     return 1;
  104. };
  105.  
  106. int frameFinished=0;
  107.  
  108. int decode_video(AVCodecContext  *ctx, AVPacket *pkt)
  109. {
  110.     double     pts;
  111.      AVPicture pict;
  112.      const uint8_t  *data[4];
  113.     double av_time;
  114.  
  115.    // __asm__("int3");
  116.  
  117.     if(avcodec_decode_video(ctx, Frame, &frameFinished,
  118.                                      pkt->data, pkt->size) <= 0)
  119.         printf("decode error\n");
  120.  
  121.     if( pkt->dts == AV_NOPTS_VALUE &&
  122.         Frame->reordered_opaque != AV_NOPTS_VALUE)
  123.         pts= Frame->reordered_opaque;
  124.     else if(pkt->dts != AV_NOPTS_VALUE)
  125.         pts= pkt->dts;
  126.     else
  127.         pts= 0;
  128.  
  129.     pts *= av_q2d(video_time_base);
  130.  
  131.     if(frameFinished)
  132.     {
  133.         while( frames[dfx].ready != 0 )
  134.             yield();
  135.  
  136.         pict.data[0] = frames[dfx].frame->data[0];
  137.         pict.data[1] = frames[dfx].frame->data[1];
  138.         pict.data[2] = frames[dfx].frame->data[2];
  139.         pict.data[3] = NULL;
  140.  
  141.         pict.linesize[0] = frames[dfx].frame->linesize[0];
  142.         pict.linesize[1] = frames[dfx].frame->linesize[1];
  143.         pict.linesize[2] = frames[dfx].frame->linesize[2];
  144.         pict.linesize[3] = 0;
  145.  
  146.         data[0] = Frame->data[0];
  147.         data[1] = Frame->data[1];
  148.         data[2] = Frame->data[2];
  149.         data[3] = NULL;
  150.  
  151.         sws_scale(cvt_ctx, data, Frame->linesize, 0, ctx->height,
  152.                   pict.data, pict.linesize);
  153.  
  154.         frames[dfx].pts = pts*1000.0;
  155.         frames[dfx].ready = 1;
  156.  
  157.         dfx++;
  158.         dfx&= 7;
  159.     };
  160.  
  161.     return 0;
  162. }
  163.  
  164. extern volatile uint32_t status;
  165.  
  166. typedef unsigned int color_t;
  167. typedef unsigned int count_t;
  168. typedef unsigned int u32_t;
  169.  
  170. static void DrawWindow(int x, int y, int w, int h, char *name,
  171.                        color_t workcolor, u32_t style)
  172. {
  173.  
  174.     __asm__ __volatile__(
  175.     "int $0x40"
  176.     ::"a"(0),
  177.       "b"((x << 16) | (w & 0xFFFF)),
  178.       "c"((y << 16) | (h & 0xFFFF)),
  179.       "d"((style << 24) | (workcolor & 0xFFFFFF)),
  180.       "D"(name));
  181. };
  182.  
  183.  
  184. static int check_events()
  185. {
  186.     int ev;
  187.  
  188.     ev = check_os_event();
  189.  
  190.     switch(ev)
  191.     {
  192.         case 1:
  193.             DrawWindow(10, 10, width+9, height+26, NULL, 0x000000,0x74);
  194.             break;
  195.  
  196.         case 3:
  197.             if(get_os_button()==1)
  198.                 status = 0;
  199.             break;
  200.     };
  201.     return 1;
  202. }
  203.  
  204.  
  205. extern char __cmdline[];
  206.  
  207. void video_thread(void *param)
  208. {
  209.     char *path;
  210.  
  211.     path = strrchr(__cmdline,'/')+1;
  212.  
  213.     DrawWindow(10, 10, width+9, height+26, path, 0x000000,0x74);
  214.  
  215.     while( status != 0)
  216.     {
  217.         double ctime;
  218.         double fdelay;
  219.  
  220.         check_events();
  221.  
  222.         if(frames[vfx].ready == 1 )
  223.         {
  224.             ctime = get_master_clock();
  225.             fdelay = (frames[vfx].pts - ctime);
  226. //            printf("ctime %f pts %f delay %f\n",
  227. //                    ctime, frames[vfx].pts, fdelay);
  228.  
  229.             if(fdelay < 0.0 )
  230.             {
  231.                 int  next_vfx;
  232.                 fdelay = 0;
  233.                 next_vfx = (vfx+1) & 7;
  234.                 if( frames[next_vfx].ready == 1 )
  235.                 {
  236.                     if(frames[next_vfx].pts <= ctime)
  237.                     {
  238.                         frames[vfx].ready = 0;                  // skip this frame
  239.                         vfx++;
  240.                         vfx&= 7;
  241.                      }
  242.                     else
  243.                     {
  244.                         if( (frames[next_vfx].pts - ctime) <
  245.                             ( ctime - frames[vfx].pts) )
  246.                         {
  247.                             frames[vfx].ready = 0;                  // skip this frame
  248.                             vfx++;
  249.                             vfx&= 7;
  250.                             fdelay = (frames[next_vfx].pts - ctime);
  251.                         }
  252.                     }
  253.                 };
  254.             };
  255.  
  256.             if(fdelay > 10.0)
  257.             {
  258.                 delay( (uint32_t)(fdelay/10.0));
  259.             };
  260.  
  261.             draw_bitmap(frames[vfx].buffer, 0, 0, width, height);
  262.             frames[vfx].ready = 0;
  263.             vfx++;
  264.             vfx&= 7;
  265.         }
  266.         else
  267.         {
  268.             yield();
  269.         };
  270.     };
  271. };
  272.  
  273.