Subversion Repositories Kolibri OS

Rev

Rev 2415 | 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. #include <libavutil/imgutils.h>
  7. #include "system.h"
  8. #include <winlib.h>
  9. #include "sound.h"
  10. #include "fplay.h"
  11.  
  12. #define CAPTION_HEIGHT      24
  13.  
  14. typedef struct
  15. {
  16.     AVPicture      picture;
  17.     double         pts;
  18.     volatile int   ready;
  19. }vframe_t;
  20.  
  21. vframe_t           frames[4];
  22.  
  23. struct SwsContext *cvt_ctx = NULL;
  24.  
  25. int vfx    = 0;
  26. int dfx    = 0;
  27.  
  28. render_t   *main_render;
  29.  
  30. int width;
  31. int height;
  32.  
  33. AVRational video_time_base;
  34. AVFrame  *Frame;
  35.  
  36. volatile uint32_t driver_lock;
  37.  
  38. void get_client_rect(rect_t *rc);
  39.  
  40.  
  41. int init_video(AVCodecContext *ctx)
  42. {
  43.     int        i;
  44.  
  45.     width = ctx->width;
  46.     height = ctx->height;
  47.  
  48.  
  49.     printf("w = %d  h = %d\n\r", width, height);
  50.  
  51. //    __asm__ __volatile__("int3");
  52.  
  53.     main_render = create_render(ctx->width, ctx->height,
  54.                            ctx->pix_fmt, HW_BIT_BLIT|HW_TEX_BLIT);
  55. //    render = create_render(ctx->width, ctx->height,
  56. //                           ctx->pix_fmt, 0);
  57. //
  58.     if( main_render == NULL)
  59.     {
  60.         printf("Cannot create render\n\r");
  61.         return 0;
  62.     };
  63.  
  64.     Frame = avcodec_alloc_frame();
  65.     if ( Frame == NULL )
  66.     {
  67.         printf("Cannot alloc video frame\n\r");
  68.         return 0;
  69.     };
  70.  
  71.     for( i=0; i < 4; i++)
  72.     {
  73.         int ret;
  74.  
  75. //        printf("alloc picture %d %d %x\n",
  76. //                   ctx->width, ctx->height, ctx->pix_fmt );
  77.  
  78.         ret = avpicture_alloc(&frames[i].picture, ctx->pix_fmt,
  79.                                ctx->width, ctx->height);
  80.         if ( ret != 0 )
  81.         {
  82.             printf("Cannot alloc video buffer\n\r");
  83.             return 0;
  84.         };
  85.  
  86.         frames[i].pts    = 0;
  87.         frames[i].ready  = 0;
  88.     };
  89.  
  90.     create_thread(video_thread, ctx, 1024*1024);
  91.  
  92.     delay(50);
  93.     return 1;
  94. };
  95.  
  96. int decode_video(AVCodecContext  *ctx, queue_t *qv)
  97. {
  98.     AVPacket   pkt;
  99.     double     pts;
  100.     int frameFinished;
  101.  
  102.     if(frames[dfx].ready != 0 )
  103.         return 1;
  104.  
  105.     if( get_packet(qv, &pkt) == 0 )
  106.         return 0;
  107.  
  108.     frameFinished = 0;
  109.  
  110.     ctx->reordered_opaque = pkt.pts;
  111.  
  112.     if(avcodec_decode_video2(ctx, Frame, &frameFinished, &pkt) <= 0)
  113.         printf("video decoder error\n");
  114.  
  115.     if(frameFinished)
  116.     {
  117.         AVPicture *dst_pic;
  118.  
  119.  
  120.         if( pkt.dts == AV_NOPTS_VALUE &&
  121.             Frame->reordered_opaque != AV_NOPTS_VALUE)
  122.         pts = Frame->reordered_opaque;
  123.         else if(pkt.dts != AV_NOPTS_VALUE)
  124.             pts= pkt.dts;
  125.         else
  126.             pts= 0;
  127.  
  128. //        pts = *(int64_t*)av_opt_ptr(avcodec_get_frame_class(),
  129. //                                Frame, "best_effort_timestamp");
  130.  
  131. //        if (pts == AV_NOPTS_VALUE)
  132. //            pts = 0;
  133.  
  134.         pts *= av_q2d(video_time_base);
  135.  
  136.         dst_pic = &frames[dfx].picture;
  137.  
  138.         av_image_copy(dst_pic->data, dst_pic->linesize,
  139.                       (const uint8_t**)Frame->data,
  140.                       Frame->linesize, ctx->pix_fmt, ctx->width, ctx->height);
  141.  
  142.         frames[dfx].pts = pts*1000.0;
  143.         frames[dfx].ready = 1;
  144.  
  145.         dfx++;
  146.         dfx&= 3;
  147.     };
  148.     av_free_packet(&pkt);
  149.  
  150.     return 1;
  151. }
  152.  
  153. extern volatile uint32_t status;
  154. rect_t     win_rect;
  155.  
  156.  
  157. int MainWindowProc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
  158. {
  159.     window_t  *win;
  160.  
  161.     win = (window_t*)ctrl;
  162.  
  163.     switch(msg)
  164.     {
  165.         case MSG_SIZE:
  166.             //printf("MSG_SIZE\n");
  167.             render_adjust_size(main_render, win);
  168.             break;
  169.  
  170.         case MSG_DRAW_CLIENT:
  171.             render_draw_client(main_render);
  172.             break;
  173.  
  174.         case MSG_COMMAND:
  175.             switch((short)arg1)
  176.             {
  177.                 case ID_CLOSE:
  178.                     exit(0);
  179.             };
  180.             break;
  181.  
  182.         default:
  183.             def_window_proc(ctrl,msg,arg1,arg2);
  184.     };
  185.     return 0;
  186. };
  187.  
  188. void render_time(render_t *render)
  189. {
  190.     double ctime;
  191.     double fdelay;
  192.  
  193.     if(status == 0)
  194.     {
  195.         render->win->win_command = WIN_CLOSED;
  196.         return;
  197.     };
  198.  
  199.     if(frames[vfx].ready == 1 )
  200.     {
  201.         ctime = get_master_clock();
  202.         fdelay = (frames[vfx].pts - ctime);
  203.  
  204. //            printf("pts %f time %f delay %f\n",
  205. //                    frames[vfx].pts, ctime, fdelay);
  206.  
  207.         if(fdelay < 0.0 )
  208.         {
  209.             int  next_vfx;
  210.             fdelay = 0;
  211.             next_vfx = (vfx+1) & 3;
  212.             if( frames[next_vfx].ready == 1 )
  213.             {
  214.                 if(frames[next_vfx].pts <= ctime)
  215.                 {
  216.                     frames[vfx].ready = 0;                  // skip this frame
  217.                     vfx++;
  218.                     vfx&= 3;
  219.                 }
  220.                 else
  221.                 {
  222.                     if( (frames[next_vfx].pts - ctime) <
  223.                         ( ctime - frames[vfx].pts) )
  224.                     {
  225.                         frames[vfx].ready = 0;                  // skip this frame
  226.                         vfx++;
  227.                         vfx&= 3;
  228.                         fdelay = (frames[next_vfx].pts - ctime);
  229.                     }
  230.                 }
  231.             };
  232.         };
  233.  
  234.         if(fdelay > 10.0)
  235.         {
  236.            // delay( (uint32_t)(fdelay/10.0));
  237.             yield();
  238.             return;
  239.         };
  240.  
  241.         main_render->draw(main_render, &frames[vfx].picture);
  242.         frames[vfx].ready = 0;
  243.         vfx++;
  244.         vfx&= 3;
  245.     };
  246. }
  247.  
  248. extern char *movie_file;
  249.  
  250. int video_thread(void *param)
  251. {
  252.     window_t    *MainWindow;
  253.  
  254.     init_winlib();
  255.  
  256.     MainWindow = create_window(movie_file,0,
  257.                                10,10,width+14,height+29,MainWindowProc);
  258.  
  259. //    printf("MainWindow %x\n", MainWindow);
  260.  
  261.     main_render->win = MainWindow;
  262.  
  263.     show_window(MainWindow, NORMAL);
  264.     run_render(MainWindow, main_render);
  265.  
  266. //    printf("exit thread\n");
  267.     status = 0;
  268.     return 0;
  269. };
  270.  
  271.  
  272. void draw_hw_picture(render_t *render, AVPicture *picture);
  273. void draw_sw_picture(render_t *render, AVPicture *picture);
  274.  
  275. render_t *create_render(uint32_t width, uint32_t height,
  276.                         uint32_t ctx_format, uint32_t flags)
  277. {
  278.     render_t *render;
  279.  
  280. //    __asm__ __volatile__("int3");
  281.  
  282.     render = (render_t*)malloc(sizeof(render_t));
  283.     memset(render, 0, sizeof(render_t));
  284.  
  285.     render->ctx_width  = width;
  286.     render->ctx_height = height;
  287.     render->ctx_format = ctx_format;
  288.  
  289.     mutex_lock(&driver_lock);
  290.     render->caps = InitPixlib(flags);
  291.     mutex_unlock(&driver_lock);
  292.  
  293.     if(render->caps==0)
  294.     {
  295.         printf("FPlay render engine: Hardware acceleration disabled\n");
  296.         render->draw = draw_sw_picture;
  297.     }
  298.     else
  299.     {
  300.         render->target = 0;
  301.         render->draw   = draw_hw_picture;
  302.     };
  303.  
  304.     render->state = EMPTY;
  305.     return render;
  306. };
  307.  
  308. int render_set_size(render_t *render, int width, int height)
  309. {
  310.     int i;
  311.  
  312.     render->layout = 0;
  313.     render->rcvideo.l = 0;
  314.     render->rcvideo.t = 0;
  315.     render->rcvideo.r = width;
  316.     render->rcvideo.b = height;
  317.  
  318.     if( render->win_height > height )
  319.     {
  320.         int yoffs;
  321.         yoffs = (render->win_height-height)/2;
  322.         if(yoffs)
  323.         {
  324.             render->rctop.t = 0;
  325.             render->rctop.b = yoffs;
  326.             render->rcvideo.t  = yoffs;
  327.             render->layout |= HAS_TOP;
  328.         }
  329.  
  330.         yoffs = render->win_height-(render->rcvideo.t+render->rcvideo.b);
  331.         if(yoffs)
  332.         {
  333.             render->rcbottom.t = render->rcvideo.t+render->rcvideo.b;
  334.             render->rcbottom.b = yoffs;
  335.             render->layout |= HAS_BOTTOM;
  336.         }
  337.     }
  338.  
  339.     if( render->win_width > width )
  340.     {
  341.         int xoffs;
  342.         xoffs = (render->win_width-width)/2;
  343.         if(xoffs)
  344.         {
  345.             render->rcleft.r  = xoffs;
  346.             render->rcvideo.l = xoffs;
  347.             render->layout |= HAS_LEFT;
  348.         }
  349.         xoffs = render->win_width-(render->rcvideo.l+render->rcvideo.r);
  350.         if(xoffs)
  351.         {
  352.             render->rcright.l = render->rcvideo.l+render->rcvideo.r;
  353.             render->rcright.r = xoffs;
  354.             render->layout |= HAS_RIGHT;
  355.         }
  356.     };
  357.  
  358.     if(render->state == EMPTY)
  359.     {
  360.         if(render->caps & HW_TEX_BLIT)
  361.         {
  362.             for( i=0; i < 4; i++)
  363.             {
  364.                 render->bitmap[i].width  = render->ctx_width;
  365.                 render->bitmap[i].height = render->ctx_height;
  366.  
  367.                 if( create_bitmap(&render->bitmap[i]) != 0 )
  368.                 {
  369.                     status = 0;
  370. /*
  371.  *  Epic fail. Need  exit_thread() here
  372.  *
  373. */
  374.                     return 0;
  375.                 };
  376.             }
  377.         }
  378.         else
  379.         {
  380.             render->bitmap[0].width  = width;
  381.             render->bitmap[0].height = height;
  382.  
  383.             if( create_bitmap(&render->bitmap[0]) != 0 )
  384.                 return 0;
  385.         };
  386.         render->state = INIT;
  387.         return 0;
  388.     };
  389.  
  390.     if(render->caps & HW_TEX_BLIT)          /*  hw scaler  */
  391.         return 0;
  392.  
  393.     render->bitmap[0].width  = width;
  394.     render->bitmap[0].height = height;
  395.     resize_bitmap(&render->bitmap[0]);
  396.  
  397.     return 0;
  398. };
  399.  
  400. void render_adjust_size(render_t *render, window_t *win)
  401. {
  402.     uint32_t right, bottom, new_w, new_h;
  403.     uint32_t s, sw, sh;
  404.     uint8_t  state;
  405.  
  406.  
  407.     right  = win->w;
  408.     bottom = win->h-CAPTION_HEIGHT;
  409.     render->win_state  = win->win_state;
  410.  
  411.     if(render->win_state == MINIMIZED)
  412.         return;
  413.  
  414.     if(render->win_state == ROLLED)
  415.         return;
  416.  
  417.     if( right  == render->win_width &&
  418.         bottom == render->win_height)
  419.         return;
  420.  
  421.     new_w = bottom*render->ctx_width/render->ctx_height;
  422.     new_h = right*render->ctx_height/render->ctx_width;
  423.  
  424. //    printf("new_w %d new_h %d\n", new_w, new_h);
  425.  
  426.     s  = right * bottom;
  427.     sw = right * new_h;
  428.     sh = bottom * new_w;
  429.  
  430.     if( abs(s-sw) > abs(s-sh))
  431.         new_h = bottom;
  432.     else
  433.         new_w = right;
  434.  
  435.     if(new_w < 64)
  436.     {
  437.         new_w = 64;
  438.         new_h = 64*render->ctx_height/render->ctx_width;
  439.     };
  440.  
  441.     render->win_width  = win->w;
  442.     render->win_height = win->h-CAPTION_HEIGHT;
  443.     render_set_size(render, new_w, new_h);
  444. };
  445.  
  446. void draw_hw_picture(render_t *render, AVPicture *picture)
  447. {
  448.     int      dst_width, dst_height;
  449.     bitmap_t   *bitmap;
  450.     uint8_t    *data[4];
  451.     int      linesize[4];
  452.     int ret;
  453.  
  454.     if(render->win_state == ROLLED)
  455.         return;
  456.  
  457.     if(render->caps & HW_TEX_BLIT)
  458.     {
  459.         dst_width  = render->ctx_width;
  460.         dst_height = render->ctx_height;
  461.     }
  462.     else
  463.     {
  464.         dst_width  = render->win_width;
  465.         dst_height = render->win_height;
  466.     };
  467.  
  468.     cvt_ctx = sws_getCachedContext(cvt_ctx,
  469.               render->ctx_width, render->ctx_height, render->ctx_format,
  470.               dst_width, dst_height, PIX_FMT_BGRA,
  471.               SWS_FAST_BILINEAR, NULL, NULL, NULL);
  472.     if(cvt_ctx == NULL)
  473.     {
  474.         printf("Cannot initialize the conversion context!\n");
  475.         return ;
  476.     };
  477.  
  478.     bitmap = &render->bitmap[render->target];
  479.  
  480.     ret = lock_bitmap(bitmap);
  481.     if( ret != 0)
  482.     {
  483.         printf("Cannot lock the bitmap!\n");
  484.         return ;
  485.     }
  486.  
  487. //    printf("sws_getCachedContext\n");
  488.     data[0] = bitmap->data;
  489.     data[1] = bitmap->data+1;
  490.     data[2] = bitmap->data+2;
  491.     data[3] = bitmap->data+3;
  492.  
  493.     linesize[0] = bitmap->pitch;
  494.     linesize[1] = bitmap->pitch;
  495.     linesize[2] = bitmap->pitch;
  496.     linesize[3] = bitmap->pitch;
  497.  
  498.     sws_scale(cvt_ctx, (const uint8_t* const *)picture->data,
  499.               picture->linesize, 0, render->ctx_height, data, linesize);
  500. //    printf("sws_scale\n");
  501.  
  502.     blit_bitmap(bitmap, render->rcvideo.l,
  503.                  CAPTION_HEIGHT+render->rcvideo.t,
  504.                  render->rcvideo.r, render->rcvideo.b);
  505. //    printf("blit_bitmap\n");
  506.  
  507.  
  508.     render->target++;
  509.     render->target&= 3;
  510. }
  511.  
  512. void draw_sw_picture(render_t *render, AVPicture *picture)
  513. {
  514.     uint8_t     *data[4];
  515.     int      linesize[4];
  516.  
  517.     if(render->win_state == MINIMIZED ||
  518.        render->win_state == ROLLED)
  519.         return;
  520.  
  521.     cvt_ctx = sws_getCachedContext(cvt_ctx,
  522.               render->ctx_width, render->ctx_height,
  523.               render->ctx_format,
  524.               render->rcvideo.r, render->rcvideo.b,
  525.               PIX_FMT_BGRA, SWS_FAST_BILINEAR, NULL, NULL, NULL);
  526.     if(cvt_ctx == NULL)
  527.     {
  528.         printf("Cannot initialize the conversion context!\n");
  529.         return ;
  530.     }
  531.  
  532.     data[0] = render->bitmap[0].data;
  533.     data[1] = render->bitmap[0].data+1;
  534.     data[2] = render->bitmap[0].data+2;
  535.     data[3] = render->bitmap[0].data+3;
  536.  
  537.  
  538.     linesize[0] = render->bitmap[0].pitch;
  539.     linesize[1] = render->bitmap[0].pitch;
  540.     linesize[2] = render->bitmap[0].pitch;
  541.     linesize[3] = render->bitmap[0].pitch;
  542.  
  543.     sws_scale(cvt_ctx, (const uint8_t* const *)picture->data,
  544.               picture->linesize, 0, render->ctx_height, data, linesize);
  545.  
  546.     blit_bitmap(&render->bitmap[0], render->rcvideo.l,
  547.                 render->rcvideo.t+CAPTION_HEIGHT,
  548.                 render->rcvideo.r, render->rcvideo.b);
  549. }
  550.  
  551. void render_draw_client(render_t *render)
  552. {
  553.     if(render->win_state == MINIMIZED ||
  554.        render->win_state == ROLLED)
  555.         return;
  556.  
  557.     if(render->layout & HAS_TOP)
  558.         draw_bar(0, CAPTION_HEIGHT, render->win_width,
  559.                  render->rctop.b, 0);
  560.     if(render->layout & HAS_LEFT)
  561.         draw_bar(0, render->rcvideo.t+CAPTION_HEIGHT, render->rcleft.r,
  562.                  render->rcvideo.b, 0);
  563.     if(render->layout & HAS_RIGHT)
  564.         draw_bar(render->rcright.l, render->rcvideo.t+CAPTION_HEIGHT,
  565.                  render->rcright.r, render->rcvideo.b, 0);
  566.     if(render->layout & HAS_BOTTOM)
  567.         draw_bar(0, render->rcbottom.t+CAPTION_HEIGHT,
  568.                  render->win_width, render->rcbottom.b, 0);
  569. }
  570.  
  571.  
  572.