📄 video_sdl.cpp
字号:
SDL_UnlockYUVOverlay(m_image); } } #ifdef CHECK_SYNC_TIMEelse {#ifdef VIDEO_SYNC_PLAY video_message(LOG_DEBUG, "Video lagging current time "LLU" "LLU" "LLU, play_this_at, current_time, m_msec_per_frame);#endif /* * Else - we're lagging - just skip and hope we catch up... */ m_skipped_render++; m_consec_skipped++; }#endif /* * Advance the buffer */ m_buffer_filled[m_play_index] = 0;#ifdef VIDEO_SYNC_FILL uint32_t temp; temp = m_play_index;#endif m_play_index++; m_play_index %= MAX_VIDEO_BUFFERS; m_total_frames++; // // okay - we need to signal the decode task to continue... if (m_decode_waiting) { m_decode_waiting = 0; SDL_SemPost(m_decode_sem);#ifdef VIDEO_SYNC_FILL video_message(LOG_DEBUG, "wait posting %d", temp);#endif } if (m_buffer_filled[m_play_index] == 1) { if (m_play_this_at[m_play_index] < current_time) return (0); else { m_msec_per_frame = m_play_this_at[m_play_index] - current_time; return (m_msec_per_frame); } } /* * we don't have next frame decoded yet. Wait a minimal time - this * means the decode task will signal */ m_msec_per_frame = 0; return (10);}int CSDLVideoSync::get_video_buffer(uint8_t **y, uint8_t **u, uint8_t **v){ if (m_dont_fill != 0) return (0); if (m_buffer_filled[m_fill_index] != 0) { m_decode_waiting = 1; SDL_SemWait(m_decode_sem); if (m_dont_fill != 0) return 0; if (m_buffer_filled[m_fill_index] != 0) return 0; } *y = m_y_buffer[m_fill_index]; *u = m_u_buffer[m_fill_index]; *v = m_v_buffer[m_fill_index]; return (1);}void CSDLVideoSync::filled_video_buffers (uint64_t time){ int ix; if (m_dont_fill == 1) return; m_play_this_at[m_fill_index] = time; m_buffer_filled[m_fill_index] = 1; ix = m_fill_index; m_fill_index++; m_fill_index %= MAX_VIDEO_BUFFERS; m_filled_frames++; if (m_msec_per_frame == 0) { m_msec_per_frame = time - m_last_filled_time; } m_last_filled_time = time; m_psptr->wake_sync_thread();#ifdef VIDEO_SYNC_FILL video_message(LOG_DEBUG, "Filled %llu %d", time, ix);#endif}/* * CSDLVideoSync::set_video_frame - called from codec to indicate a new * frame is ready. * Inputs - y - pointer to y buffer - should point to first byte to copy * u - pointer to u buffer * v - pointer to v buffer * pixelw_y - width of row in y buffer (may be larger than width * set up above. * pixelw_uv - width of row in u or v buffer. * time - time to display * current_time - current time we're displaying - this allows the * codec to intelligently drop frames if it's falling behind. */void CSDLVideoSync::set_video_frame(const uint8_t *y, const uint8_t*u, const uint8_t *v, int pixelw_y, int pixelw_uv, uint64_t time){ uint8_t *dst; const uint8_t *src; unsigned int ix; if (m_dont_fill != 0) {#ifdef VIDEO_SYNC_FILL video_message(LOG_DEBUG, "Don't fill in video sync");#endif return; } /* * Do we have a buffer ? If not, indicate that we're waiting, and wait */ if (m_buffer_filled[m_fill_index] != 0) { m_decode_waiting = 1; SDL_SemWait(m_decode_sem); if (m_buffer_filled[m_fill_index] != 0) {#ifdef VIDEO_SYNC_FILL video_message(LOG_DEBUG, "Wait but filled %d", m_fill_index);#endif return; } } /* * copy the relevant data to the local buffers */ m_play_this_at[m_fill_index] = time; src = y; dst = m_y_buffer[m_fill_index]; for (ix = 0; ix < m_height; ix++) { memcpy(dst, src, m_width); dst += m_width; src += pixelw_y; } src = u; dst = m_u_buffer[m_fill_index]; unsigned int uvheight = m_height/2; unsigned int uvwidth = m_width/2; for (ix = 0; ix < uvheight; ix++) { memcpy(dst, src, uvwidth); dst += uvwidth; src += pixelw_uv; } src = v; dst = m_v_buffer[m_fill_index]; for (ix = 0; ix < uvheight; ix++) { memcpy(dst, src, uvwidth); dst += uvwidth; src += pixelw_uv; } /* * advance the buffer, and post to the sync task */ m_buffer_filled[m_fill_index] = 1; ix = m_fill_index; m_fill_index++; m_fill_index %= MAX_VIDEO_BUFFERS; m_filled_frames++; if (m_msec_per_frame == 0) { m_msec_per_frame = time - m_last_filled_time; } m_last_filled_time = time; m_psptr->wake_sync_thread();#ifdef VIDEO_SYNC_FILL video_message(LOG_DEBUG, "filled %llu %d", time, ix);#endif return;}// called from sync thread. Don't call on play, or m_dont_fill race// condition may occur.void CSDLVideoSync::flush_sync_buffers (void){ // Just restart decode thread if waiting... m_dont_fill = 1; m_eof_found = 0; m_paused = 1; if (m_decode_waiting) { SDL_SemPost(m_decode_sem); // start debug }}// called from decode thread on both stop/start.void CSDLVideoSync::flush_decode_buffers (void){ for (int ix = 0; ix < MAX_VIDEO_BUFFERS; ix++) { m_buffer_filled[ix] = 0; } m_fill_index = m_play_index = 0; m_dont_fill = 0;}void CSDLVideoSync::set_screen_size (int scaletimes2){ m_video_scale = scaletimes2;}void CSDLVideoSync::set_fullscreen (int fullscreen){ m_fullscreen = fullscreen;}void CSDLVideoSync::do_video_resize (int pixel_width, int pixel_height, int max_width, int max_height, bool resize){#if 0 player_debug_message("do_video_resize %d,%d,%d,%d\n", pixel_width,pixel_height,max_width,max_height);#endif // Save values for future use (i.e. -1 values as argument will // restore an argument.) if (pixel_width > -1) m_pixel_width = pixel_width; if (pixel_height > -1) m_pixel_height = pixel_height; if (max_width > -1) m_max_width = max_width; if (max_height > -1) m_max_height = max_height; // Check and see if all we wanted was to transfer values. if (!resize) { return; } if (m_image) { SDL_FreeYUVOverlay(m_image); m_image = NULL; } if (m_screen) { SDL_FreeSurface(m_screen); m_screen = NULL; }#ifdef OLD_SURFACE int mask = SDL_SWSURFACE | SDL_ASYNCBLIT | SDL_RESIZABLE;#else int mask = SDL_HWSURFACE | SDL_RESIZABLE;#endif int video_scale = m_video_scale; if (m_fullscreen != 0) { mask |= SDL_FULLSCREEN;#ifdef _WIN32 video_scale = 2;#endif } int w = m_width * video_scale / 2; if (m_double_width) w *= 2; int h = m_height * video_scale / 2; // Check and see if we should use old values. if (pixel_width == -1 && m_pixel_width) pixel_width = m_pixel_width; if (pixel_height == -1 && m_pixel_height) pixel_height = m_pixel_height; if (max_width == -1 && m_max_width) max_width = m_max_width; if (max_height == -1 && m_max_height) max_height = m_height; // It is only when we have positive values larger than zero for // pixel sizes that we resize if (pixel_width > 0 && pixel_height > 0) { // Square pixels needs no resize. if (pixel_width != pixel_height) { // enable different handling of full screen versus non full screen if (m_fullscreen == 0) { if (pixel_width > pixel_height) w = h * pixel_width / pixel_height; else w = w * pixel_height / pixel_width; } else { // For now we do the same as in non full screen. if (pixel_width > pixel_height) w = h * pixel_width / pixel_height; else w = w * pixel_height / pixel_width; } } } if (m_fullscreen == 1) { if (max_width > 0 && w > max_width) w = max_width; if (max_height > 0 && h > max_height) h = max_height; } video_message(LOG_DEBUG, "Setting video mode %d %d %x", w, h, mask); m_screen = SDL_SetVideoMode(w, h, m_video_bpp, mask); if (m_screen == NULL) { m_screen = SDL_SetVideoMode(w, h, m_video_bpp, mask); if (m_screen == NULL) { video_message(LOG_CRIT, "sdl error message is %s", SDL_GetError()); abort(); } } m_dstrect.x = 0; m_dstrect.y = 0; m_dstrect.w = m_screen->w; m_dstrect.h = m_screen->h; SDL_FreeYUVOverlay(m_image);#ifdef OLD_SURFACE if (video_scale == 4) { m_image = SDL_CreateYUVOverlay(m_width << 1, m_height << 1, SDL_YV12_OVERLAY, m_screen); } else #endif { m_image = SDL_CreateYUVOverlay(m_width, m_height, SDL_YV12_OVERLAY, m_screen); }}void CSDLVideoSync::double_width (void){ m_double_width = 1;}static void c_video_configure (void *ifptr, int w, int h, int format){ // asdf - ignore format for now ((CSDLVideoSync *)ifptr)->config(w, h);}static int c_video_get_buffer (void *ifptr, uint8_t **y, uint8_t **u, uint8_t **v){ return (((CSDLVideoSync *)ifptr)->get_video_buffer(y, u, v));}static void c_video_filled_buffer(void *ifptr, uint64_t time){ ((CSDLVideoSync *)ifptr)->filled_video_buffers(time);}static void c_video_have_frame (void *ifptr, const uint8_t *y, const uint8_t *u, const uint8_t *v, int m_pixelw_y, int m_pixelw_uv, uint64_t time){ CSDLVideoSync *foo = (CSDLVideoSync *)ifptr; foo->set_video_frame(y, u, v, m_pixelw_y, m_pixelw_uv, time);}static video_vft_t video_vft = { message, c_video_configure, c_video_get_buffer, c_video_filled_buffer, c_video_have_frame,};video_vft_t *get_video_vft (void){ return (&video_vft);}CVideoSync *create_video_sync (CPlayerSession *psptr) { return new CSDLVideoSync(psptr);}/* end file video.cpp */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -