Subversion Repositories Kolibri OS

Rev

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