📄 video_sdl.cpp
字号:
memcpy(m_image->pixels[V],
m_v_buffer[m_play_index],
bufsize);
}
if (width != m_image->pitches[U]) {
to = (uint8_t *)m_image->pixels[U];
from = m_u_buffer[m_play_index];
for (ix = 0; ix < height; ix++) {
memcpy(to, from, width);
to += m_image->pitches[U];
from += width;
}
} else {
memcpy(m_image->pixels[U],
m_u_buffer[m_play_index],
bufsize);
}
}
int rval = SDL_DisplayYUVOverlay(m_image, &m_dstrect);
if (rval != 0) {
video_message(LOG_ERR, "Return from display is %d", rval);
}
SDL_UnlockYUVOverlay(m_image);
}
}
#ifdef CHECK_SYNC_TIME
else {
#if 0
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);
}
int CSDLVideoSync::filled_video_buffers (uint64_t time)
{
int ix;
if (m_dont_fill == 1)
return 0;
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
return (1);
}
/*
* 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.
*/
int 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 (m_paused);
}
/*
* 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 m_paused;
}
}
/*
* 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 (m_paused);
}
// 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 (void)
{
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;
int h = m_height * video_scale / 2;
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);
}
}
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 int c_video_filled_buffer(void *ifptr, uint64_t time)
{
return (((CSDLVideoSync *)ifptr)->filled_video_buffers(time));
}
static int 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;
return (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 + -