Subversion Repositories Kolibri OS

Rev

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