Subversion Repositories Kolibri OS

Rev

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

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