Subversion Repositories Kolibri OS

Rev

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