⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video_sdl.cpp

📁 jpeg and mpeg 编解码技术源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	  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 + -