Subversion Repositories Kolibri OS

Rev

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