Subversion Repositories Kolibri OS

Rev

Rev 4438 | Rev 5372 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | 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 <kos32sys.h>
  8. #include "winlib/winlib.h"
  9. #include <sound.h>
  10. #include "fplay.h"
  11. #include <math.h>
  12.  
  13. int fplay_blit_bitmap(bitmap_t *bitmap, int dst_x, int dst_y,int w, int h);
  14.  
  15. extern int res_pause_btn[];
  16. extern int res_pause_btn_pressed[];
  17.  
  18. extern int res_play_btn[];
  19. extern int res_play_btn_pressed[];
  20.  
  21. extern int64_t stream_duration;
  22. extern volatile int sound_level_0;
  23. extern volatile int sound_level_1;
  24.  
  25. typedef struct
  26. {
  27.     AVPicture      picture;
  28.     double         pts;
  29.     volatile int   ready;
  30. }vframe_t;
  31.  
  32. vframe_t           frames[4];
  33. volatile int      frames_count = 0;
  34.  
  35. struct SwsContext *cvt_ctx = NULL;
  36.  
  37. int vfx    = 0;
  38. int dfx    = 0;
  39.  
  40. render_t   *main_render;
  41.  
  42. int width;
  43. int height;
  44.  
  45. AVRational video_time_base;
  46. AVFrame  *Frame;
  47.  
  48. volatile uint32_t driver_lock;
  49.  
  50. void get_client_rect(rect_t *rc);
  51.  
  52. void flush_video()
  53. {
  54.     int i;
  55.  
  56.     for(i = 0; i < 4; i++)
  57.     {
  58.         frames[i].pts    = 0;
  59.         frames[i].ready  = 0;
  60.     };
  61.     frames_count = 0;
  62.     vfx    = 0;
  63.     dfx    = 0;
  64. };
  65.  
  66. int init_video(AVCodecContext *ctx)
  67. {
  68.     int        i;
  69.  
  70.     width = ctx->width;
  71.     height = ctx->height;
  72.  
  73.  
  74.     Frame = avcodec_alloc_frame();
  75.     if ( Frame == NULL )
  76.     {
  77.         printf("Cannot alloc video frame\n\r");
  78.         return 0;
  79.     };
  80.  
  81.     for( i=0; i < 4; i++)
  82.     {
  83.         int ret;
  84.  
  85. //        printf("alloc picture %d %d %x\n",
  86. //                   ctx->width, ctx->height, ctx->pix_fmt );
  87.  
  88.         ret = avpicture_alloc(&frames[i].picture, ctx->pix_fmt,
  89.                                ctx->width, ctx->height);
  90.         if ( ret != 0 )
  91.         {
  92.             printf("Cannot alloc video buffer\n\r");
  93.             return 0;
  94.         };
  95.  
  96.         frames[i].pts    = 0;
  97.         frames[i].ready  = 0;
  98.     };
  99.  
  100.     create_thread(video_thread, ctx, 1024*1024);
  101.  
  102.     delay(50);
  103.     return 1;
  104. };
  105.  
  106. int decode_video(AVCodecContext  *ctx, queue_t *qv)
  107. {
  108.     AVPacket   pkt;
  109.     double     pts;
  110.     int frameFinished;
  111.     double current_clock;
  112.  
  113.     if(frames[dfx].ready != 0 )
  114.         return -1;
  115.  
  116.     if( get_packet(qv, &pkt) == 0 )
  117.         return 0;
  118.  
  119. /*
  120.     current_clock = -90.0 + get_master_clock();
  121.  
  122.     if( pkt.dts == AV_NOPTS_VALUE &&
  123.         Frame->reordered_opaque != AV_NOPTS_VALUE)
  124.         pts = Frame->reordered_opaque;
  125.     else if(pkt.dts != AV_NOPTS_VALUE)
  126.         pts= pkt.dts;
  127.     else
  128.         pts= 0;
  129.  
  130.  
  131.     pts *= av_q2d(video_time_base)*1000.0;
  132. */
  133.     if( 1 /*pts > current_clock*/)
  134.     {
  135.         frameFinished = 0;
  136.  
  137.         ctx->reordered_opaque = pkt.pts;
  138.  
  139.         if(avcodec_decode_video2(ctx, Frame, &frameFinished, &pkt) <= 0)
  140.             printf("video decoder error\n");
  141.  
  142.         if(frameFinished)
  143.         {
  144.             AVPicture *dst_pic;
  145.  
  146.             if( pkt.dts == AV_NOPTS_VALUE &&
  147.                 Frame->reordered_opaque != AV_NOPTS_VALUE)
  148.                 pts = Frame->reordered_opaque;
  149.             else if(pkt.dts != AV_NOPTS_VALUE)
  150.                 pts= pkt.dts;
  151.             else
  152.                 pts= 0;
  153.  
  154. //        pts = *(int64_t*)av_opt_ptr(avcodec_get_frame_class(),
  155. //                                Frame, "best_effort_timestamp");
  156.  
  157. //        if (pts == AV_NOPTS_VALUE)
  158. //            pts = 0;
  159.  
  160.             pts *= av_q2d(video_time_base);
  161.  
  162.             dst_pic = &frames[dfx].picture;
  163.  
  164.             av_image_copy(dst_pic->data, dst_pic->linesize,
  165.                       (const uint8_t**)Frame->data,
  166.                       Frame->linesize, ctx->pix_fmt, ctx->width, ctx->height);
  167.  
  168.             frames[dfx].pts = pts*1000.0;
  169. //            printf("pts %f\n", frames[dfx].pts);
  170.  
  171.             frames[dfx].ready = 1;
  172.  
  173.             dfx++;
  174.             dfx&= 3;
  175.             frames_count++;
  176.         };
  177.     };
  178.     av_free_packet(&pkt);
  179.  
  180.     return 1;
  181. }
  182.  
  183. extern volatile enum player_state player_state;
  184. extern volatile enum player_state decoder_state;
  185. extern volatile enum player_state sound_state;
  186.  
  187. //rect_t     win_rect;
  188.  
  189. extern int64_t rewind_pos;
  190.  
  191. static void player_stop()
  192. {
  193.     window_t  *win;
  194.  
  195.     win = main_render->win;
  196.  
  197.     rewind_pos = 0;
  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.     win->panel.prg->current             = rewind_pos;
  203.  
  204.     send_message(&win->panel.ctrl, MSG_PAINT, 0, 0);
  205.     player_state = STOP;
  206.     decoder_state = PLAY_2_STOP;
  207.     sound_state = PLAY_2_STOP;
  208.     render_draw_client(main_render);
  209. //    printf("stop player\n");
  210.  
  211. };
  212.  
  213. int MainWindowProc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
  214. {
  215.     window_t  *win = (window_t*)ctrl;
  216.     static int spc_down = 0;
  217.     static int ent_down = 0;
  218.  
  219.     switch(msg)
  220.     {
  221.         case MSG_SIZE:
  222.             //printf("MSG_SIZE\n");
  223.             if(main_render)
  224.             {
  225.                 render_adjust_size(main_render, win);
  226.                 render_draw_client(main_render);
  227.             };
  228.             break;
  229.  
  230.         case MSG_KEY:
  231.             switch((short)arg2)
  232.             {
  233.                 case 0x39:
  234.                     if(spc_down == 0)
  235.                     {
  236.                         spc_down = 1;
  237.                         send_message(win, MSG_LBTNDOWN, 0, 0);
  238.                     }
  239.                     break;
  240.  
  241.                 case 0xB9:
  242.                     spc_down = 0;
  243.                     break;
  244.  
  245.                 case 0x1C:
  246.                     if(ent_down == 0)
  247.                     {
  248.                         int screensize;
  249.                         if(win->win_state == NORMAL)
  250.                         {
  251.                             win->saved = win->rc;
  252.                             win->saved_state = win->win_state;
  253.  
  254.                             screensize = GetScreenSize();
  255.                             __asm__ __volatile__(
  256.                             "int $0x40"
  257.                             ::"a"(67), "b"(0), "c"(0),
  258.                             "d"((screensize >> 16)-1),"S"((screensize & 0xFFFF)-1) );
  259.                             win->win_state = FULLSCREEN;
  260.                             window_update_layout(win);
  261.                         }
  262.                         else if(win->win_state == FULLSCREEN)
  263.                         {
  264.                             __asm__ __volatile__(
  265.                             "int $0x40"
  266.                             ::"a"(67), "b"(win->saved.l), "c"(win->saved.t),
  267.                             "d"(win->saved.r-win->saved.l-1),"S"(win->saved.b-win->saved.t-1));
  268.                             win->win_state = win->saved_state;
  269.                             window_update_layout(win);
  270. //                            if(win->saved_state == MAXIMIZED)
  271.                             {
  272.                                 blit_caption(&win->caption);
  273.                                 blit_panel(&win->panel);
  274.                             }
  275.                         }
  276.                         ent_down = 1;
  277.                     };
  278.                     break;
  279.  
  280.                 case 0x9C:
  281.                     ent_down = 0;
  282.                     break;
  283.             };
  284.  
  285.         case MSG_DRAW_CLIENT:
  286.             if(main_render)
  287.             {
  288.                 render_draw_client(main_render);
  289.             };
  290.             break;
  291.  
  292.         case MSG_LBTNDOWN:
  293.  
  294.             if(player_state == PAUSE)
  295.             {
  296.                 win->panel.play_btn->img_default = res_pause_btn;
  297.                 win->panel.play_btn->img_hilite  = res_pause_btn;
  298.                 win->panel.play_btn->img_pressed = res_pause_btn_pressed;
  299.                 send_message(&win->panel.play_btn->ctrl, MSG_PAINT, 0, 0);
  300.                 player_state = PLAY;
  301.                 sound_state  = PAUSE_2_PLAY;
  302.  
  303.             }
  304.             else if(player_state == PLAY)
  305.             {
  306.                 win->panel.play_btn->img_default = res_play_btn;
  307.                 win->panel.play_btn->img_hilite  = res_play_btn;
  308.                 win->panel.play_btn->img_pressed = res_play_btn_pressed;
  309.                 send_message(&win->panel.play_btn->ctrl, MSG_PAINT, 0, 0);
  310.                 player_state = PAUSE;
  311.                 sound_state  = PLAY_2_PAUSE;
  312.             }
  313.             break;
  314.  
  315.         case MSG_COMMAND:
  316.             switch((short)arg1)
  317.             {
  318.                 case ID_PLAY:
  319.                     if(player_state == PAUSE)
  320.                     {
  321.                         win->panel.play_btn->img_default  = res_pause_btn;
  322.                         win->panel.play_btn->img_hilite   = res_pause_btn;
  323.                         win->panel.play_btn->img_pressed = res_pause_btn_pressed;
  324.                         player_state = PLAY;
  325.                         sound_state = PAUSE_2_PLAY;
  326.                     }
  327.                     else if(player_state == PLAY)
  328.                     {
  329.                         win->panel.play_btn->img_default = res_play_btn;
  330.                         win->panel.play_btn->img_hilite  = res_play_btn;
  331.                         win->panel.play_btn->img_pressed  = res_play_btn_pressed;
  332.                         player_state = PAUSE;
  333.                         sound_state  = PLAY_2_PAUSE;
  334.                     }
  335.                     else if(player_state == STOP)
  336.                     {
  337.                         win->panel.play_btn->img_default  = res_pause_btn;
  338.                         win->panel.play_btn->img_hilite   = res_pause_btn;
  339.                         win->panel.play_btn->img_pressed = res_pause_btn_pressed;
  340.                         rewind_pos = 0;
  341.                         send_message(&win->panel.ctrl, MSG_PAINT, 0, 0);
  342.                         player_state = PLAY;
  343.                         decoder_state = PREPARE;
  344.                     }
  345.                     break;
  346.  
  347.                 case ID_STOP:
  348.                     player_stop();
  349.                     break;
  350.  
  351.                 case ID_PROGRESS:
  352.                     if(player_state != REWIND)
  353.                     {
  354.                         progress_t *prg = (progress_t*)arg2;
  355.  
  356.                         rewind_pos = (prg->max - prg->min)*prg->pos/prg->ctrl.w;
  357.  
  358. //                        printf("progress action pos: %d time: %f\n", prg->pos, (double)rewind_pos);
  359.                         player_state  = REWIND;
  360.                         decoder_state = REWIND;
  361.                         sound_state   = PLAY_2_STOP;
  362.                         if(rewind_pos < prg->current)
  363.                         {
  364.                             prg->current  = rewind_pos;
  365.                             rewind_pos = -rewind_pos;
  366.                         }
  367.                         else
  368.                             prg->current  = rewind_pos;
  369.  
  370.                         win->panel.play_btn->img_default  = res_pause_btn;
  371.                         win->panel.play_btn->img_hilite   = res_pause_btn;
  372.                         win->panel.play_btn->img_pressed  = res_pause_btn_pressed;
  373.                         send_message(&prg->ctrl, MSG_PAINT, 0, 0);
  374.                     };
  375.                     break;
  376.  
  377.                 case ID_VOL_CTRL:
  378.                 {
  379.                     slider_t *sld = (slider_t*)arg2;
  380.                     int      peak;
  381.                     int      level;
  382.  
  383.                     peak = sld->min + sld->pos * (sld->max - sld->min)/(96);
  384. //                    level = (log2(peak+16384)*10000.0)/15 - 10000;
  385.                     level =  peak;
  386.  
  387. //                    printf("level %d\n", level);
  388.                     set_audio_volume(level, level);
  389.                     send_message(&sld->ctrl, MSG_PAINT, 0, 0);
  390.                     win->panel.lvl->vol = level;
  391.                 }
  392.  
  393.                 default:
  394.                     break;
  395.             }
  396.             break;
  397.  
  398.         default:
  399.             def_window_proc(ctrl,msg,arg1,arg2);
  400.     };
  401.     return 0;
  402. };
  403.  
  404. #define VERSION_A     1
  405.  
  406. extern queue_t  q_video;
  407. extern queue_t  q_audio;
  408.  
  409. void render_time(render_t *render)
  410. {
  411.     progress_t  *prg = main_render->win->panel.prg;
  412.     level_t     *lvl = main_render->win->panel.lvl;
  413.  
  414.     double      ctime;            /*    milliseconds    */
  415.     double      fdelay;           /*    milliseconds    */
  416.  
  417. //again:
  418.  
  419.     if(player_state == CLOSED)
  420.     {
  421.         render->win->win_command = WIN_CLOSED;
  422.         return;
  423.     }
  424.     else if((player_state == PAUSE) || (player_state == REWIND))
  425.     {
  426.         delay(1);
  427.         return;
  428.     }
  429.     else if (decoder_state == STOP && frames_count  == 0 &&
  430.               player_state  != STOP)
  431.     {
  432.         player_stop();
  433.     }
  434.     else if(player_state != PLAY)
  435.     {
  436.         delay(1);
  437.         return;
  438.     };
  439.  
  440.  
  441. #ifdef VERSION_A
  442.     if(frames[vfx].ready == 1 )
  443.     {
  444.         int sys_time;
  445.  
  446.         ctime = get_master_clock();
  447.         fdelay = (frames[vfx].pts - ctime);
  448.  
  449. //        printf("pts %f time %f delay %f\n",
  450. //                frames[vfx].pts, ctime, fdelay);
  451.  
  452.         if(fdelay > 15.0)
  453.         {
  454.             delay((int)fdelay/10);
  455.         //    return;
  456.         };
  457. #if 0
  458.         ctime = get_master_clock();
  459.         fdelay = (frames[vfx].pts - ctime);
  460.  
  461. //        while(fdelay > 0)
  462. //        {
  463. //            yield();
  464. //            ctime = get_master_clock();
  465. //            fdelay = (frames[vfx].pts - ctime);
  466. //        }
  467.  
  468. //        sys_time = get_tick_count();
  469.  
  470. //        if(fdelay < 0)
  471. //            printf("systime %d pts %f time %f delay %f\n",
  472. //                    sys_time*10, frames[vfx].pts, ctime, fdelay);
  473.  
  474.         printf("pts %f time %f delay %f\n",
  475.                 frames[vfx].pts, ctime, fdelay);
  476.         printf("video cache %d audio cache %d\n", q_video.size/1024, q_audio.size/1024);
  477. #endif
  478.  
  479.         main_render->draw(main_render, &frames[vfx].picture);
  480.         if(main_render->win->win_state != FULLSCREEN)
  481.         {
  482.             prg->current = frames[vfx].pts*1000;
  483. //        printf("current %f\n", prg->current);
  484.             lvl->current = vfx & 1 ? sound_level_1 : sound_level_0;
  485.  
  486.             send_message(&prg->ctrl, PRG_PROGRESS, 0, 0);
  487.  
  488.             if(main_render->win->panel.layout)
  489.                 send_message(&lvl->ctrl, MSG_PAINT, 0, 0);
  490.         }
  491.  
  492.         frames_count--;
  493.         frames[vfx].ready = 0;
  494.         vfx++;
  495.         vfx&= 3;
  496.     }
  497.     else delay(1);
  498.  
  499. #else
  500.  
  501.     if(frames[vfx].ready == 1 )
  502.     {
  503.         ctime = get_master_clock();
  504.         fdelay = (frames[vfx].pts - ctime);
  505.  
  506. //            printf("pts %f time %f delay %f\n",
  507. //                    frames[vfx].pts, ctime, fdelay);
  508.  
  509.         if(fdelay < 0.0 )
  510.         {
  511.             int  next_vfx;
  512.             fdelay = 0;
  513.             next_vfx = (vfx+1) & 3;
  514.             if( frames[next_vfx].ready == 1 )
  515.             {
  516.                 if(frames[next_vfx].pts <= ctime)
  517.                 {
  518.                     frames[vfx].ready = 0;                  // skip this frame
  519.                     vfx++;
  520.                     vfx&= 3;
  521.                 }
  522.                 else
  523.                 {
  524.                     if( (frames[next_vfx].pts - ctime) <
  525.                         ( ctime - frames[vfx].pts) )
  526.                     {
  527.                         frames[vfx].ready = 0;                  // skip this frame
  528.                         vfx++;
  529.                         vfx&= 3;
  530.                         fdelay = (frames[next_vfx].pts - ctime);
  531.                     }
  532.                 }
  533.             };
  534.         };
  535.  
  536.         if(fdelay > 10.0)
  537.         {
  538.            int val = fdelay;
  539.            printf("pts %f time %f delay %d\n",
  540.                    frames[vfx].pts, ctime, val);
  541.            delay(val/10);
  542.         };
  543.  
  544.         ctime = get_master_clock();
  545.         fdelay = (frames[vfx].pts - ctime);
  546.  
  547.         printf("pts %f time %f delay %f\n",
  548.                 frames[vfx].pts, ctime, fdelay);
  549.  
  550.         main_render->draw(main_render, &frames[vfx].picture);
  551.         main_render->win->panel.prg->current = frames[vfx].pts;
  552. //        send_message(&render->win->panel.prg->ctrl, MSG_PAINT, 0, 0);
  553.         frames[vfx].ready = 0;
  554.         vfx++;
  555.         vfx&= 3;
  556.     }
  557.     else yield();
  558. #endif
  559.  
  560. }
  561.  
  562.  
  563. extern char *movie_file;
  564.  
  565. int video_thread(void *param)
  566. {
  567.     AVCodecContext *ctx = param;
  568.     window_t  *MainWindow;
  569.  
  570.     init_winlib();
  571.  
  572.     MainWindow = create_window(movie_file,0,
  573.                                10,10,width,height+CAPTION_HEIGHT+PANEL_HEIGHT,MainWindowProc);
  574.  
  575.     MainWindow->panel.prg->max = stream_duration;
  576. //    printf("MainWindow %x\n", MainWindow);
  577.  
  578.     show_window(MainWindow, NORMAL);
  579.  
  580. //    __asm__ __volatile__("int3");
  581.  
  582.     main_render = create_render(MainWindow, ctx, HW_TEX_BLIT|HW_BIT_BLIT);
  583.     if( main_render == NULL)
  584.     {
  585.         printf("Cannot create render\n\r");
  586.         return 0;
  587.     };
  588.  
  589.     render_draw_client(main_render);
  590.     player_state = PLAY;
  591.  
  592.     run_render(MainWindow, main_render);
  593.  
  594.     destroy_render(main_render);
  595.     fini_winlib();
  596.  
  597.     player_state = CLOSED;
  598.     return 0;
  599. };
  600.  
  601.  
  602. void draw_hw_picture(render_t *render, AVPicture *picture);
  603. void draw_sw_picture(render_t *render, AVPicture *picture);
  604.  
  605. render_t *create_render(window_t *win, AVCodecContext *ctx, uint32_t flags)
  606. {
  607.     render_t *render;
  608.  
  609.     uint32_t right, bottom, draw_w, draw_h;
  610.     uint32_t s, sw, sh;
  611.     uint8_t  state;
  612.  
  613. //    __asm__ __volatile__("int3");
  614.  
  615.     render = (render_t*)malloc(sizeof(render_t));
  616.     memset(render, 0, sizeof(render_t));
  617.  
  618.     render->win = win;
  619.  
  620.     render->ctx_width  = ctx->width;
  621.     render->ctx_height = ctx->height;
  622.     render->ctx_format = ctx->pix_fmt;
  623.  
  624.     mutex_lock(&driver_lock);
  625.     render->caps = init_pixlib(flags);
  626.     mutex_unlock(&driver_lock);
  627.  
  628.     right  = win->w;
  629.     bottom = win->h-CAPTION_HEIGHT-PANEL_HEIGHT;
  630.  
  631.  //   printf("window width %d height %d\n",
  632.  //                   right, bottom);
  633.  
  634.     render->win_state  = win->win_state;
  635.  
  636.     draw_w = bottom*render->ctx_width/render->ctx_height;
  637.     draw_h = right*render->ctx_height/render->ctx_width;
  638.  
  639.     if(draw_w > right)
  640.     {
  641.         draw_w = right;
  642.         draw_h = right*render->ctx_height/render->ctx_width;
  643.     };
  644.  
  645.     if(draw_h > bottom)
  646.     {
  647.         draw_h = bottom;
  648.         draw_w = bottom*render->ctx_width/render->ctx_height;
  649.     };
  650.  
  651.     render->win_width  = win->w;
  652.     render->win_height = win->h-CAPTION_HEIGHT-PANEL_HEIGHT;
  653.  
  654.     render_set_size(render, draw_w, draw_h);
  655.  
  656.  
  657.     if(render->caps==0)
  658.     {
  659.         render->bitmap[0].width  = draw_w;
  660.         render->bitmap[0].height = draw_h;
  661.  
  662.         if( create_bitmap(&render->bitmap[0]) != 0 )
  663.         {
  664.             free(render);
  665.             return NULL;
  666.         }
  667.         render->draw = draw_sw_picture;
  668.     }
  669.     else
  670.     {
  671.         int width, height, flags;
  672.         int i;
  673.  
  674.         if(render->caps & HW_TEX_BLIT)
  675.         {
  676.             sna_create_mask();
  677.  
  678.             width  = render->ctx_width;
  679.             height = render->ctx_height;
  680.             flags  = HW_TEX_BLIT;
  681.         }
  682.         else
  683.         {
  684.             width  = draw_w;
  685.             height = draw_h;;
  686.             flags  = HW_BIT_BLIT;
  687.         }
  688.  
  689.         for( i=0; i < 2; i++)
  690.         {
  691.             render->bitmap[i].width  = width;
  692.             render->bitmap[i].height = height;
  693.             render->bitmap[i].flags  = flags;
  694.  
  695.             if( create_bitmap(&render->bitmap[i]) != 0 )
  696.             {
  697.                 player_state = CLOSED;
  698.                 free(render);
  699.                 return NULL;
  700.             };
  701.         }
  702.  
  703.         render->state = INIT;
  704.         render->target = 0;
  705.         render->draw   = draw_hw_picture;
  706.     };
  707.  
  708.  
  709.     printf("FPlay %s render engine: context %dx%d picture %dx%d\n",
  710.            render->caps & HW_TEX_BLIT ? "hw_tex_blit":
  711.            render->caps & HW_BIT_BLIT ? "hw_bit_blit":"software",
  712.            render->ctx_width, render->ctx_height,
  713.            draw_w, draw_h);
  714.  
  715. //    if(init_hw_context(ctx) == 0)
  716. //        printf("create hardware decoder context\n");
  717.  
  718.     return render;
  719. };
  720.  
  721. void destroy_render(render_t *render)
  722. {
  723.  
  724.     destroy_bitmap(&render->bitmap[0]);
  725.  
  726.     if(render->caps & (HW_BIT_BLIT|HW_TEX_BLIT))          /* hw blitter */
  727.         destroy_bitmap(&render->bitmap[1]);
  728.  
  729.     done_pixlib();
  730. };
  731.  
  732. void render_set_size(render_t *render, int width, int height)
  733. {
  734.     int i;
  735.  
  736.     render->layout = 0;
  737.     render->rcvideo.l = 0;
  738.     render->rcvideo.t = 0;
  739.     render->rcvideo.r = width;
  740.     render->rcvideo.b = height;
  741.  
  742. //    printf("render width %d height %d\n",width, height);
  743.  
  744.     if( render->win_height > height )
  745.     {
  746.         int yoffs;
  747.         yoffs = (render->win_height-height)/2;
  748.         if(yoffs)
  749.         {
  750.             render->rctop.t = 0;
  751.             render->rctop.b = yoffs;
  752.             render->rcvideo.t  = yoffs;
  753.             render->layout |= HAS_TOP;
  754.         }
  755.  
  756.         yoffs = render->win_height-(render->rcvideo.t+render->rcvideo.b);
  757.         if(yoffs)
  758.         {
  759.             render->rcbottom.t = render->rcvideo.t+render->rcvideo.b;
  760.             render->rcbottom.b = yoffs;
  761.             render->layout |= HAS_BOTTOM;
  762.         }
  763.     }
  764.  
  765.     if( render->win_width > width )
  766.     {
  767.         int xoffs;
  768.         xoffs = (render->win_width-width)/2;
  769.         if(xoffs)
  770.         {
  771.             render->rcleft.r  = xoffs;
  772.             render->rcvideo.l = xoffs;
  773.             render->layout |= HAS_LEFT;
  774.         }
  775.         xoffs = render->win_width-(render->rcvideo.l+render->rcvideo.r);
  776.         if(xoffs)
  777.         {
  778.             render->rcright.l = render->rcvideo.l+render->rcvideo.r;
  779.             render->rcright.r = xoffs;
  780.             render->layout |= HAS_RIGHT;
  781.         }
  782.     };
  783. };
  784.  
  785. void render_adjust_size(render_t *render, window_t *win)
  786. {
  787.     uint32_t right, bottom, new_w, new_h;
  788.     uint32_t s, sw, sh;
  789.     uint8_t  state;
  790.  
  791.     right  = win->w;
  792.     bottom = win->h;
  793.  
  794.     if(win->win_state != FULLSCREEN)
  795.         bottom-= CAPTION_HEIGHT+PANEL_HEIGHT;
  796.  
  797.  //   printf("window width %d height %d\n",
  798.  //                   right, bottom);
  799.  
  800.     render->win_state  = win->win_state;
  801.  
  802.     if(render->win_state == MINIMIZED)
  803.         return;
  804.  
  805.     if(render->win_state == ROLLED)
  806.         return;
  807.  
  808.     if( right  == render->win_width &&
  809.         bottom == render->win_height)
  810.         return;
  811.  
  812. //    printf("%s r: %d b: %d\n", __FUNCTION__, right, bottom);
  813.  
  814.     new_w = bottom*render->ctx_width/render->ctx_height;
  815.     new_h = right*render->ctx_height/render->ctx_width;
  816.  
  817.     if(new_w > right)
  818.     {
  819.         new_w = right;
  820.         new_h = right*render->ctx_height/render->ctx_width;
  821.     };
  822.     if(new_h > bottom)
  823.     {
  824.         new_h = bottom;
  825.         new_w = bottom*render->ctx_width/render->ctx_height;
  826.     };
  827.  
  828.     render->win_width  = right;
  829.     render->win_height = bottom;
  830.     render_set_size(render, new_w, new_h);
  831.  
  832.     if(render->caps & HW_TEX_BLIT)          /*  hw scaler  */
  833.         return;
  834.  
  835.     render->bitmap[0].width  = new_w;
  836.     render->bitmap[0].height = new_h;
  837.     resize_bitmap(&render->bitmap[0]);
  838.  
  839.     if(render->caps & HW_BIT_BLIT)          /* hw blitter */
  840.     {
  841.         render->bitmap[1].width  = new_w;
  842.         render->bitmap[1].height = new_h;
  843.         resize_bitmap(&render->bitmap[1]);
  844.     };
  845.     return;
  846. };
  847.  
  848. void draw_hw_picture(render_t *render, AVPicture *picture)
  849. {
  850.     int      dst_width, dst_height;
  851.     bitmap_t   *bitmap;
  852.     uint8_t    *data[4];
  853.     int      linesize[4];
  854.     int ret;
  855.  
  856.     if(render->win->win_state == MINIMIZED ||
  857.        render->win->win_state == ROLLED)
  858.         return;
  859.  
  860.     if(render->caps & HW_TEX_BLIT)
  861.     {
  862.         dst_width  = render->ctx_width;
  863.         dst_height = render->ctx_height;
  864.     }
  865.     else
  866.     {
  867.         dst_width  = render->rcvideo.r;
  868.         dst_height = render->rcvideo.b;
  869.     };
  870.  
  871.     cvt_ctx = sws_getCachedContext(cvt_ctx,
  872.               render->ctx_width, render->ctx_height, render->ctx_format,
  873.               dst_width, dst_height, PIX_FMT_BGRA,
  874.               SWS_FAST_BILINEAR, NULL, NULL, NULL);
  875.     if(cvt_ctx == NULL)
  876.     {
  877.         printf("Cannot initialize the conversion context!\n");
  878.         return ;
  879.     };
  880.  
  881.     bitmap = &render->bitmap[render->target];
  882.  
  883.     ret = lock_bitmap(bitmap);
  884.     if( ret != 0)
  885.     {
  886.         printf("Cannot lock bitmap!\n");
  887.         return ;
  888.     }
  889.  
  890. //    printf("sws_getCachedContext\n");
  891.     data[0] = bitmap->data;
  892.     data[1] = bitmap->data+1;
  893.     data[2] = bitmap->data+2;
  894.     data[3] = bitmap->data+3;
  895.  
  896.     linesize[0] = bitmap->pitch;
  897.     linesize[1] = bitmap->pitch;
  898.     linesize[2] = bitmap->pitch;
  899.     linesize[3] = bitmap->pitch;
  900.  
  901.     sws_scale(cvt_ctx, (const uint8_t* const *)picture->data,
  902.               picture->linesize, 0, render->ctx_height, data, linesize);
  903. //    printf("sws_scale\n");
  904.  
  905.  
  906.     if(render->caps & HW_TEX_BLIT)
  907.     {
  908.  
  909.         if(render->win->win_state == FULLSCREEN)
  910.             fplay_blit_bitmap(bitmap,render->rcvideo.l,render->rcvideo.t,
  911.                  render->rcvideo.r, render->rcvideo.b);
  912.         else
  913.             fplay_blit_bitmap(bitmap, render->rcvideo.l,
  914.                     CAPTION_HEIGHT+render->rcvideo.t,
  915.                     render->rcvideo.r, render->rcvideo.b);
  916.     }
  917.     else
  918.     {
  919.         if(render->win->win_state == FULLSCREEN)
  920.             blit_bitmap(bitmap,render->rcvideo.l,render->rcvideo.t,
  921.                     render->rcvideo.r, render->rcvideo.b, 0,0);
  922.         else
  923.             blit_bitmap(bitmap, render->rcvideo.l,
  924.                     CAPTION_HEIGHT+render->rcvideo.t,
  925.                     render->rcvideo.r, render->rcvideo.b, 0, 0);
  926.     };
  927.  
  928.     render->last_bitmap = bitmap;
  929.     render->target++;
  930.     render->target&= 1;
  931. }
  932.  
  933. void draw_sw_picture(render_t *render, AVPicture *picture)
  934. {
  935.     uint8_t     *data[4];
  936.     int      linesize[4];
  937.  
  938.     if(render->win->win_state == MINIMIZED ||
  939.        render->win->win_state == ROLLED)
  940.         return;
  941.  
  942.     cvt_ctx = sws_getCachedContext(cvt_ctx,
  943.               render->ctx_width, render->ctx_height,
  944.               render->ctx_format,
  945.               render->rcvideo.r, render->rcvideo.b,
  946.               PIX_FMT_BGRA, SWS_FAST_BILINEAR, NULL, NULL, NULL);
  947.     if(cvt_ctx == NULL)
  948.     {
  949.         printf("Cannot initialize the conversion context!\n");
  950.         return ;
  951.     }
  952.  
  953.     lock_bitmap(&render->bitmap[0]);
  954.  
  955.     data[0] = render->bitmap[0].data;
  956.     data[1] = render->bitmap[0].data+1;
  957.     data[2] = render->bitmap[0].data+2;
  958.     data[3] = render->bitmap[0].data+3;
  959.  
  960.     linesize[0] = render->bitmap[0].pitch;
  961.     linesize[1] = render->bitmap[0].pitch;
  962.     linesize[2] = render->bitmap[0].pitch;
  963.     linesize[3] = render->bitmap[0].pitch;
  964.  
  965.      sws_scale(cvt_ctx, (const uint8_t* const *)picture->data,
  966.               picture->linesize, 0, render->ctx_height, data, linesize);
  967.  
  968.     if(render->win->win_state == FULLSCREEN)
  969.         fplay_blit_bitmap(&render->bitmap[0],render->rcvideo.l,render->rcvideo.t,
  970.                  render->rcvideo.r, render->rcvideo.b);
  971.     else
  972.         fplay_blit_bitmap(&render->bitmap[0], render->rcvideo.l,
  973.                  CAPTION_HEIGHT+render->rcvideo.t,
  974.                  render->rcvideo.r, render->rcvideo.b);
  975.  
  976.     render->last_bitmap = &render->bitmap[0];
  977. }
  978.  
  979. void render_draw_client(render_t *render)
  980. {
  981.     int y;
  982.  
  983.     if(render->win_state == MINIMIZED ||
  984.        render->win_state == ROLLED )
  985.         return;
  986.     if(render->win_state == FULLSCREEN)
  987.         y = 0;
  988.     else
  989.         y = CAPTION_HEIGHT;
  990.  
  991.     if(player_state == PAUSE)
  992.     {
  993.          if(frames[vfx].ready == 1 )
  994.             main_render->draw(main_render, &frames[vfx].picture);
  995.          else
  996.             draw_bar(0, y, render->win_width,
  997.                  render->rcvideo.b, 0);
  998.     }
  999.     else if( player_state == STOP )
  1000.     {
  1001.         draw_bar(0,y, render->win_width,
  1002.                  render->rcvideo.b, 0);
  1003.     };
  1004.  
  1005.     if(render->layout & HAS_TOP)
  1006.         draw_bar(0, y, render->win_width,
  1007.                  render->rctop.b, 0);
  1008.     if(render->layout & HAS_LEFT)
  1009.         draw_bar(0, render->rcvideo.t+y, render->rcleft.r,
  1010.                  render->rcvideo.b, 0);
  1011.     if(render->layout & HAS_RIGHT)
  1012.         draw_bar(render->rcright.l, render->rcvideo.t+y,
  1013.                  render->rcright.r, render->rcvideo.b, 0);
  1014.     if(render->layout & HAS_BOTTOM)
  1015.         draw_bar(0, render->rcbottom.t+y,
  1016.                  render->win_width, render->rcbottom.b, 0);
  1017. }
  1018.  
  1019.  
  1020.