Subversion Repositories Kolibri OS

Rev

Rev 5021 | Rev 5603 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

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