Subversion Repositories Kolibri OS

Rev

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