Subversion Repositories Kolibri OS

Rev

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