Subversion Repositories Kolibri OS

Rev

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