video_sdl.cpp
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:19k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is MPEG4IP.
  13.  * 
  14.  * The Initial Developer of the Original Code is Cisco Systems Inc.
  15.  * Portions created by Cisco Systems Inc. are
  16.  * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  *              Bill May        wmay@cisco.com
  20.  */
  21. /*
  22.  * video.cpp - provides codec to video hardware class
  23.  */
  24. #include <string.h>
  25. #include "player_session.h"
  26. #include "video_sdl.h"
  27. #include "player_util.h"
  28. #include <SDL_error.h>
  29. #include <SDL_syswm.h>
  30. //#define VIDEO_SYNC_PLAY 2
  31. //#define VIDEO_SYNC_FILL 1
  32. //#define SHORT_VIDEO 1
  33. //#define SWAP_UV 1
  34. #ifdef _WIN32
  35. // new hwsurface method doesn't work on windows.
  36. // If you have pre-directX 8.1 - you'll want to define OLD_SURFACE
  37. //#define OLD_SURFACE 1
  38. #endif
  39. #ifdef _WIN32
  40. DEFINE_MESSAGE_MACRO(video_message, "videosync")
  41. #else
  42. #define video_message(loglevel, fmt...) message(loglevel, "videosync", fmt)
  43. #endif
  44. CSDLVideoSync::CSDLVideoSync (CPlayerSession *psptr) : CVideoSync(psptr)
  45. {
  46.   char buf[32];
  47.   if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0 || !SDL_VideoDriverName(buf, 1)) {
  48.     video_message(LOG_CRIT, "Could not init SDL video: %s", SDL_GetError());
  49.   }
  50.   m_screen = NULL;
  51.   m_image = NULL;
  52.   m_video_initialized = 0;
  53.   m_config_set = 0;
  54.   m_have_data = 0;
  55.   for (int ix = 0; ix < MAX_VIDEO_BUFFERS; ix++) {
  56.     m_y_buffer[ix] = NULL;
  57.     m_u_buffer[ix] = NULL;
  58.     m_v_buffer[ix] = NULL;
  59.     m_buffer_filled[ix] = 0;
  60.   }
  61.   m_play_index = m_fill_index = 0;
  62.   m_decode_waiting = 0;
  63.   m_dont_fill = 0;
  64.   m_paused = 1;
  65.   m_behind_frames = 0;
  66.   m_total_frames = 0;
  67.   m_behind_time = 0;
  68.   m_behind_time_max = 0;
  69.   m_skipped_render = 0;
  70.   m_video_scale = 2;
  71.   m_msec_per_frame = 0;
  72.   m_consec_skipped = 0;
  73.   m_fullscreen = 0;
  74.   m_filled_frames = 0;
  75. }
  76. CSDLVideoSync::~CSDLVideoSync (void)
  77. {
  78.   if (m_fullscreen != 0) {
  79.     m_fullscreen = 0;
  80.     do_video_resize();
  81.   }
  82.   if (m_image) {
  83.     SDL_FreeYUVOverlay(m_image);
  84.     m_image = NULL;
  85.   }
  86.   if (m_screen) {
  87.     SDL_FreeSurface(m_screen);
  88.     m_screen = NULL;
  89.   }
  90.   for (int ix = 0; ix < MAX_VIDEO_BUFFERS; ix++) {
  91.     if (m_y_buffer[ix] != NULL) {
  92.       free(m_y_buffer[ix]);
  93.       m_y_buffer[ix] = NULL;
  94.     }
  95.     if (m_u_buffer[ix] != NULL) {
  96.       free(m_u_buffer[ix]);
  97.       m_u_buffer[ix] = NULL;
  98.     }
  99.     if (m_v_buffer[ix] != NULL) {
  100.       free(m_v_buffer[ix]);
  101.       m_v_buffer[ix] = NULL;
  102.     }
  103.   }
  104. }
  105. /*
  106.  * CSDLVideoSync::config - routine for the codec to call to set up the
  107.  * width, height and frame_rate of the video
  108.  */
  109. void CSDLVideoSync::config (int w, int h)
  110. {
  111.   m_width = w;
  112.   m_height = h;
  113.   for (int ix = 0; ix < MAX_VIDEO_BUFFERS; ix++) {
  114.     m_y_buffer[ix] = (uint8_t *)malloc(w * h * sizeof(uint8_t));
  115.     m_u_buffer[ix] = (uint8_t *)malloc(w/2 * h/2 * sizeof(uint8_t));
  116.     m_v_buffer[ix] = (uint8_t *)malloc(w/2 * h/2 * sizeof(uint8_t));
  117.     m_buffer_filled[ix] = 0;
  118.   }
  119.   m_config_set = 1;
  120. }
  121. /*
  122.  * CSDLVideoSync::initialize_video - Called from sync task to initialize
  123.  * the video window
  124.  */  
  125. int CSDLVideoSync::initialize_video (const char *name, int x, int y)
  126. {
  127.   if (m_video_initialized == 0) {
  128.     if (m_config_set) {
  129.       const SDL_VideoInfo *video_info;
  130.       video_info = SDL_GetVideoInfo();
  131.       switch (video_info->vfmt->BitsPerPixel) {
  132.       case 16:
  133.       case 32:
  134. m_video_bpp = video_info->vfmt->BitsPerPixel;
  135. break;
  136.       default:
  137. m_video_bpp = 16;
  138. break;
  139.       }
  140.       SDL_ShowCursor(SDL_DISABLE);
  141.       SDL_SysWMinfo info;
  142.       SDL_VERSION(&info.version);
  143.       int ret;
  144.       ret = SDL_GetWMInfo(&info);
  145.       // Oooh... fun... To scale the video, just pass the width and height
  146.       // to this routine. (ie: m_width *2, m_height * 2).
  147. #ifdef OLD_SURFACE
  148.       int mask = SDL_SWSURFACE | SDL_ASYNCBLIT | SDL_RESIZABLE;
  149. #else
  150.       int mask = SDL_HWSURFACE | SDL_RESIZABLE;
  151. #endif
  152.   int video_scale = m_video_scale;
  153.       if (m_fullscreen != 0) {
  154. mask |= SDL_FULLSCREEN;
  155. #ifdef _WIN32
  156. video_scale = 2;
  157. #endif
  158.       }
  159.       int w = m_width * video_scale / 2;
  160.       int h = m_height * video_scale / 2;
  161.       m_screen = SDL_SetVideoMode(w,
  162.   h,
  163.   m_video_bpp,
  164.   mask);
  165.       if (ret > 0) {
  166. #ifdef unix
  167. // player_debug_message("Trying");
  168. if (info.subsystem == SDL_SYSWM_X11) {
  169.   info.info.x11.lock_func();
  170.   XMoveWindow(info.info.x11.display, info.info.x11.wmwindow, x, y);
  171.   info.info.x11.unlock_func();
  172. }
  173. #endif
  174.       }
  175.       SDL_WM_SetCaption(name, NULL);
  176.       m_dstrect.x = 0;
  177.       m_dstrect.y = 0;
  178.       m_dstrect.w = m_screen->w;
  179.       m_dstrect.h = m_screen->h;
  180. #if 1
  181.       video_message(LOG_DEBUG, "Created mscreen %p hxw %d %d", m_screen, m_height,
  182.    m_width);
  183. #endif
  184. #ifdef OLD_SURFACE
  185. if (video_scale == 4) {
  186.       m_image = SDL_CreateYUVOverlay(m_width << 1, 
  187.      m_height << 1,
  188.      SDL_YV12_OVERLAY, 
  189.      m_screen);
  190. } else {
  191. #else
  192.   {
  193. #endif
  194.       m_image = SDL_CreateYUVOverlay(m_width, 
  195.      m_height,
  196.      SDL_YV12_OVERLAY, 
  197.      m_screen);
  198. }
  199.       m_video_initialized = 1;
  200.       return (1);
  201.     } else {
  202.       return (0);
  203.     }
  204.   }
  205.   return (1);
  206. }
  207. /*
  208.  * CSDLVideoSync::is_video_ready - called from sync task to determine if
  209.  * we have sufficient number of buffers stored up to start displaying
  210.  */
  211. int CSDLVideoSync::is_video_ready (uint64_t &disptime)
  212. {
  213.   disptime = m_play_this_at[m_play_index];
  214.   if (m_dont_fill) {
  215.     return 0;
  216.   }
  217. #ifdef SHORT_VIDEO
  218.   return (m_buffer_filled[m_play_index] == 1);
  219. #else
  220.   return (m_buffer_filled[(m_play_index + 2*MAX_VIDEO_BUFFERS/3) % MAX_VIDEO_BUFFERS] == 1);
  221. #endif
  222. }
  223. void CSDLVideoSync::play_video (void) 
  224. {
  225. }
  226. /*
  227.  * CSDLVideoSync::play_video_at - called from sync task to show the next
  228.  * video frame (if the timing is right
  229.  */
  230. int64_t CSDLVideoSync::play_video_at (uint64_t current_time, 
  231.    int &have_eof)
  232. {
  233.   uint64_t play_this_at;
  234.   unsigned int ix;
  235.   uint8_t *to, *from;
  236.   /*
  237.    * If the next buffer is not filled, indicate that, as well
  238.    */
  239.   if (m_buffer_filled[m_play_index] == 0) {
  240.     /*
  241.      * If we have end of file, indicate it
  242.      */
  243.     if (m_eof_found != 0) {
  244.       have_eof = 1;
  245.       return (-1);
  246.     }
  247.     return 10;
  248.   }
  249.   
  250.   /*
  251.    * we have a buffer.  If it is in the future, don't play it now
  252.    */
  253.   play_this_at = m_play_this_at[m_play_index];
  254.   if (play_this_at > current_time) {
  255.     return (play_this_at - current_time);
  256.   }
  257. #if VIDEO_SYNC_PLAY
  258.   video_message(LOG_DEBUG, "play "LLU" at "LLU " %d", play_this_at, current_time,
  259.        m_play_index);
  260. #endif
  261.   /*
  262.    * If we're behind - see if we should just skip it
  263.    */
  264.   if (play_this_at < current_time) {
  265.     m_behind_frames++;
  266.     uint64_t behind = current_time - play_this_at;
  267.     m_behind_time += behind;
  268.     if (behind > m_behind_time_max) m_behind_time_max = behind;
  269. #if 0
  270.     if ((m_behind_frames % 64) == 0) {
  271.       video_message(LOG_DEBUG, "behind "LLU" avg "LLU" max "LLU,
  272.    behind, m_behind_time / m_behind_frames,
  273.    m_behind_time_max);
  274.     }
  275. #endif
  276.   }
  277.   m_paused = 0;
  278.   /*
  279.    * If we're within 1/2 of the frame time, go ahead and display
  280.    * this frame
  281.    */
  282. #define CHECK_SYNC_TIME 1
  283. #ifdef CHECK_SYNC_TIME
  284.   int showed = 0;
  285.   if ((m_msec_per_frame == 0) || 
  286.       ((play_this_at + m_msec_per_frame) > current_time) ||
  287.       (m_consec_skipped > 10)) {
  288. #else
  289.     {
  290. #endif
  291.       showed = 1;
  292.       m_consec_skipped = 0;
  293.     if (SDL_LockYUVOverlay(m_image)) {
  294.       video_message(LOG_ERR, "Failed to lock image");
  295.     } else {
  296.     // Must always copy the buffer to memory.  This creates 2 copies of this
  297.     // data (probably a total of 6 - libsock -> rtp -> decoder -> our ring ->
  298.     // sdl -> hardware)
  299. #ifdef OLD_SURFACE
  300.     if (m_fullscreen == 0 && m_video_scale == 4) {
  301.       // when scaling to 200%, don't use SDL stretch blit
  302.       // use a smoothing (averaging) blit instead
  303. #ifdef USE_MMX
  304.       FrameDoublerMmx(m_y_buffer[m_play_index], m_image->pixels[0], 
  305.       m_width, m_height);
  306.       FrameDoublerMmx(m_v_buffer[m_play_index], m_image->pixels[1], 
  307.       m_width >> 1, m_height >> 1);
  308.       FrameDoublerMmx(m_u_buffer[m_play_index], m_image->pixels[2], 
  309.       m_width >> 1, m_height >> 1);
  310. #else
  311.       FrameDoubler(m_y_buffer[m_play_index], m_image->pixels[0], 
  312.    m_width, m_height, m_image->pitches[0]);
  313.       FrameDoubler(m_v_buffer[m_play_index], m_image->pixels[1], 
  314.    m_width >> 1, m_height >> 1, m_image->pitches[1]);
  315.       FrameDoubler(m_u_buffer[m_play_index], m_image->pixels[2], 
  316.    m_width >> 1, m_height >> 1, m_image->pitches[2]);
  317. #endif
  318.     } else 
  319. #endif
  320.       {
  321. // let SDL blit, either 1:1 for 100% or decimating by 2:1 for 50%
  322. uint32_t bufsize = m_width * m_height * sizeof(uint8_t);
  323. unsigned int width = m_width, height = m_height;
  324. if (width != m_image->pitches[0]) {
  325.   to = (uint8_t *)m_image->pixels[0];
  326.   from = m_y_buffer[m_play_index];
  327.   for (ix = 0; ix < height; ix++) {
  328.     memcpy(to, from, width);
  329.     to += m_image->pitches[0];
  330.     from += width;
  331.   }
  332. } else {
  333.   memcpy(m_image->pixels[0], 
  334.  m_y_buffer[m_play_index], 
  335.  bufsize);
  336. }
  337. bufsize /= 4;
  338. width /= 2;
  339. height /= 2;
  340. #ifdef SWAP_UV
  341. #define V 2
  342. #define U 1
  343. #else
  344. #define V 1
  345. #define U 2
  346. #endif
  347. if (width != m_image->pitches[V]) {
  348.     to = (uint8_t *)m_image->pixels[V];
  349.     from = m_v_buffer[m_play_index];
  350.   for (ix = 0; ix < height; ix++) {
  351.     memcpy(to, from, width);
  352.     to += m_image->pitches[V];
  353.     from += width;
  354.   }
  355. } else {
  356.   memcpy(m_image->pixels[V], 
  357.  m_v_buffer[m_play_index], 
  358.  bufsize);
  359. }
  360. if (width != m_image->pitches[U]) {
  361.     to = (uint8_t *)m_image->pixels[U];
  362.     from = m_u_buffer[m_play_index];
  363.   for (ix = 0; ix < height; ix++) {
  364.     memcpy(to, from, width);
  365.     to += m_image->pitches[U];
  366.     from += width;
  367.   }
  368. } else {
  369.   memcpy(m_image->pixels[U], 
  370.  m_u_buffer[m_play_index], 
  371.  bufsize);
  372. }
  373.       }
  374.     int rval = SDL_DisplayYUVOverlay(m_image, &m_dstrect);
  375.     if (rval != 0) {
  376.       video_message(LOG_ERR, "Return from display is %d", rval);
  377.     }
  378.     SDL_UnlockYUVOverlay(m_image);
  379. }
  380.   } 
  381. #ifdef CHECK_SYNC_TIME
  382. else {
  383. #if 0
  384.     video_message(LOG_DEBUG, "Video lagging current time "LLU" "LLU" "LLU, 
  385.  play_this_at, current_time, m_msec_per_frame);
  386. #endif
  387.     /*
  388.      * Else - we're lagging - just skip and hope we catch up...
  389.      */
  390.     m_skipped_render++;
  391.     m_consec_skipped++;
  392.   }
  393. #endif
  394.   /*
  395.    * Advance the buffer
  396.    */
  397.   m_buffer_filled[m_play_index] = 0;
  398. #ifdef VIDEO_SYNC_FILL
  399.   uint32_t temp;
  400.   temp = m_play_index;
  401. #endif
  402.   m_play_index++;
  403.   m_play_index %= MAX_VIDEO_BUFFERS;
  404.   m_total_frames++;
  405.   // 
  406.   // okay - we need to signal the decode task to continue...
  407.   if (m_decode_waiting) {
  408.     m_decode_waiting = 0;
  409.     SDL_SemPost(m_decode_sem);
  410. #ifdef VIDEO_SYNC_FILL
  411.     video_message(LOG_DEBUG, "wait posting %d", temp);
  412. #endif
  413.   }
  414.   if (m_buffer_filled[m_play_index] == 1) {
  415.     if (m_play_this_at[m_play_index] < current_time) 
  416.       return (0);
  417.     else {
  418.       m_msec_per_frame = m_play_this_at[m_play_index] - current_time;
  419.       return (m_msec_per_frame);
  420.     }
  421.   }
  422.   /*
  423.    * we don't have next frame decoded yet.  Wait a minimal time - this
  424.    * means the decode task will signal
  425.    */
  426.   m_msec_per_frame = 0;
  427.   return (10);
  428. }
  429. int CSDLVideoSync::get_video_buffer(uint8_t **y,
  430.  uint8_t **u,
  431.  uint8_t **v)
  432. {
  433.   
  434.   if (m_dont_fill != 0) 
  435.     return (0);
  436.   if (m_buffer_filled[m_fill_index] != 0) {
  437.     m_decode_waiting = 1;
  438.     SDL_SemWait(m_decode_sem);
  439.     if (m_dont_fill != 0)
  440.       return 0;
  441.     if (m_buffer_filled[m_fill_index] != 0)
  442.       return 0;
  443.   }
  444.   *y = m_y_buffer[m_fill_index];
  445.   *u = m_u_buffer[m_fill_index];
  446.   *v = m_v_buffer[m_fill_index];
  447.   return (1);
  448. }
  449. int CSDLVideoSync::filled_video_buffers (uint64_t time)
  450. {
  451.   int ix;
  452.   if (m_dont_fill == 1)
  453.     return 0;
  454.   m_play_this_at[m_fill_index] = time;
  455.   m_buffer_filled[m_fill_index] = 1;
  456.   ix = m_fill_index;
  457.   m_fill_index++;
  458.   m_fill_index %= MAX_VIDEO_BUFFERS;
  459.   m_filled_frames++;
  460.   if (m_msec_per_frame == 0) {
  461.     m_msec_per_frame = time - m_last_filled_time;
  462.   }
  463.   m_last_filled_time = time;
  464.   m_psptr->wake_sync_thread();
  465. #ifdef VIDEO_SYNC_FILL
  466.   video_message(LOG_DEBUG, "Filled %llu %d", time, ix);
  467. #endif
  468.   return (1);
  469. }
  470. /*
  471.  * CSDLVideoSync::set_video_frame - called from codec to indicate a new
  472.  * frame is ready.
  473.  * Inputs - y - pointer to y buffer - should point to first byte to copy
  474.  *          u - pointer to u buffer
  475.  *          v - pointer to v buffer
  476.  *          pixelw_y - width of row in y buffer (may be larger than width
  477.  *                   set up above.
  478.  *          pixelw_uv - width of row in u or v buffer.
  479.  *          time - time to display
  480.  *          current_time - current time we're displaying - this allows the
  481.  *            codec to intelligently drop frames if it's falling behind.
  482.  */
  483. int CSDLVideoSync::set_video_frame(const uint8_t *y, 
  484. const uint8_t*u, 
  485. const uint8_t *v,
  486. int pixelw_y, 
  487. int pixelw_uv, 
  488. uint64_t time)
  489. {
  490.   uint8_t *dst;
  491.   const uint8_t *src;
  492.   unsigned int ix;
  493.   if (m_dont_fill != 0) {
  494. #ifdef VIDEO_SYNC_FILL
  495.     video_message(LOG_DEBUG, "Don't fill in video sync");
  496. #endif
  497.     return (m_paused);
  498.   }
  499.   /*
  500.    * Do we have a buffer ?  If not, indicate that we're waiting, and wait
  501.    */
  502.   if (m_buffer_filled[m_fill_index] != 0) {
  503.     m_decode_waiting = 1;
  504.     SDL_SemWait(m_decode_sem);
  505.     if (m_buffer_filled[m_fill_index] != 0) {
  506. #ifdef VIDEO_SYNC_FILL
  507.       video_message(LOG_DEBUG, "Wait but filled %d", m_fill_index);
  508. #endif
  509.       return m_paused;
  510.     }
  511.   }  
  512.   /*
  513.    * copy the relevant data to the local buffers
  514.    */
  515.   m_play_this_at[m_fill_index] = time;
  516.   src = y;
  517.   dst = m_y_buffer[m_fill_index];
  518.   for (ix = 0; ix < m_height; ix++) {
  519.     memcpy(dst, src, m_width);
  520.     dst += m_width;
  521.     src += pixelw_y;
  522.   }
  523.   src = u;
  524.   dst = m_u_buffer[m_fill_index];
  525.   unsigned int uvheight = m_height/2;
  526.   unsigned int uvwidth = m_width/2;
  527.   for (ix = 0; ix < uvheight; ix++) {
  528.     memcpy(dst, src, uvwidth);
  529.     dst += uvwidth;
  530.     src += pixelw_uv;
  531.   }
  532.   src = v;
  533.   dst = m_v_buffer[m_fill_index];
  534.   for (ix = 0; ix < uvheight; ix++) {
  535.     memcpy(dst, src, uvwidth);
  536.     dst += uvwidth;
  537.     src += pixelw_uv;
  538.   }
  539.   /*
  540.    * advance the buffer, and post to the sync task
  541.    */
  542.   m_buffer_filled[m_fill_index] = 1;
  543.   ix = m_fill_index;
  544.   m_fill_index++;
  545.   m_fill_index %= MAX_VIDEO_BUFFERS;
  546.   m_filled_frames++;
  547.   if (m_msec_per_frame == 0) {
  548.     m_msec_per_frame = time - m_last_filled_time;
  549.   }
  550.   m_last_filled_time = time;
  551.   m_psptr->wake_sync_thread();
  552. #ifdef VIDEO_SYNC_FILL
  553.   video_message(LOG_DEBUG, "filled %llu %d", time, ix);
  554. #endif
  555.   return (m_paused);
  556. }
  557. // called from sync thread.  Don't call on play, or m_dont_fill race
  558. // condition may occur.
  559. void CSDLVideoSync::flush_sync_buffers (void)
  560. {
  561.   // Just restart decode thread if waiting...
  562.   m_dont_fill = 1;
  563.   m_eof_found = 0;
  564.   m_paused = 1;
  565.   if (m_decode_waiting) {
  566.     SDL_SemPost(m_decode_sem);
  567.     // start debug
  568.   }
  569. }
  570. // called from decode thread on both stop/start.
  571. void CSDLVideoSync::flush_decode_buffers (void)
  572. {
  573.   for (int ix = 0; ix < MAX_VIDEO_BUFFERS; ix++) {
  574.     m_buffer_filled[ix] = 0;
  575.   }
  576.   m_fill_index = m_play_index = 0;
  577.   m_dont_fill = 0;
  578. }
  579. void CSDLVideoSync::set_screen_size (int scaletimes2)
  580. {
  581.   m_video_scale = scaletimes2;
  582. }
  583. void CSDLVideoSync::set_fullscreen (int fullscreen)
  584. {
  585.   m_fullscreen = fullscreen;
  586. }
  587. void CSDLVideoSync::do_video_resize (void)
  588. {
  589.   if (m_image) {
  590.     SDL_FreeYUVOverlay(m_image);
  591.     m_image = NULL;
  592.   }
  593.   if (m_screen) {
  594.     SDL_FreeSurface(m_screen);
  595.     m_screen = NULL;
  596.   }
  597. #ifdef OLD_SURFACE
  598.   int mask = SDL_SWSURFACE | SDL_ASYNCBLIT | SDL_RESIZABLE;
  599. #else
  600.   int mask = SDL_HWSURFACE | SDL_RESIZABLE;
  601. #endif
  602.   int video_scale = m_video_scale;
  603.   if (m_fullscreen != 0) {
  604.     mask |= SDL_FULLSCREEN;
  605. #ifdef _WIN32
  606. video_scale = 2;
  607. #endif
  608.   }
  609.   int w = m_width * video_scale / 2;
  610.   int h = m_height * video_scale / 2;
  611.     
  612.   video_message(LOG_DEBUG, "Setting video mode %d %d %x", 
  613. w, h, mask);
  614.   m_screen = SDL_SetVideoMode(w, h, m_video_bpp, 
  615.       mask);
  616.   if (m_screen == NULL) {
  617.   m_screen = SDL_SetVideoMode(w, h, m_video_bpp, mask);
  618.   if (m_screen == NULL) {
  619.   video_message(LOG_CRIT, "sdl error message is %s", SDL_GetError());
  620. abort();
  621.   }
  622.   }
  623.   m_dstrect.x = 0;
  624.   m_dstrect.y = 0;
  625.   m_dstrect.w = m_screen->w;
  626.   m_dstrect.h = m_screen->h;
  627.   SDL_FreeYUVOverlay(m_image);
  628. #ifdef OLD_SURFACE
  629.   if (video_scale == 4) {
  630.     m_image = SDL_CreateYUVOverlay(m_width << 1, 
  631.  m_height << 1,
  632.  SDL_YV12_OVERLAY, 
  633.  m_screen);
  634.   } else 
  635. #endif
  636.     {
  637.     m_image = SDL_CreateYUVOverlay(m_width, 
  638.  m_height,
  639.  SDL_YV12_OVERLAY, 
  640.  m_screen);
  641.   }
  642. }
  643. static void c_video_configure (void *ifptr,
  644.       int w,
  645.       int h,
  646.       int format)
  647. {
  648.   // asdf - ignore format for now
  649.   ((CSDLVideoSync *)ifptr)->config(w, h);
  650. }
  651. static int c_video_get_buffer (void *ifptr, 
  652.        uint8_t **y,
  653.        uint8_t **u,
  654.        uint8_t **v)
  655. {
  656.   return (((CSDLVideoSync *)ifptr)->get_video_buffer(y, u, v));
  657. }
  658. static int c_video_filled_buffer(void *ifptr, uint64_t time)
  659. {
  660.   return (((CSDLVideoSync *)ifptr)->filled_video_buffers(time));
  661. }
  662. static int c_video_have_frame (void *ifptr,
  663.        const uint8_t *y,
  664.        const uint8_t *u,
  665.        const uint8_t *v,
  666.        int m_pixelw_y,
  667.        int m_pixelw_uv,
  668.        uint64_t time)
  669. {
  670.   CSDLVideoSync *foo = (CSDLVideoSync *)ifptr;
  671.   return (foo->set_video_frame(y, 
  672.        u, 
  673.        v, 
  674.        m_pixelw_y,
  675.        m_pixelw_uv,
  676.        time));
  677. }
  678. static video_vft_t video_vft = 
  679. {
  680.   message,
  681.   c_video_configure,
  682.   c_video_get_buffer,
  683.   c_video_filled_buffer,
  684.   c_video_have_frame,
  685. };
  686. video_vft_t *get_video_vft (void)
  687. {
  688.   return (&video_vft);
  689. }
  690. CVideoSync *create_video_sync (CPlayerSession *psptr) 
  691. {
  692.   return new CSDLVideoSync(psptr);
  693. }
  694. /* end file video.cpp */