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

📄 video_sdl.cpp

📁 网络MPEG4IP流媒体开发源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is MPEG4IP. *  * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved. *  * Contributor(s):  *              Bill May        wmay@cisco.com *              video aspect ratio by: *              Peter Maersk-Moller peter@maersk-moller.net *//* * video.cpp - provides codec to video hardware class */#include <string.h>#include "player_session.h"#include "video_sdl.h"#include "player_util.h"#include <SDL_error.h>#include <SDL_syswm.h>//#define VIDEO_SYNC_PLAY 2//#define VIDEO_SYNC_FILL 1//#define SHORT_VIDEO 1//#define SWAP_UV 1#ifdef _WIN32// new hwsurface method doesn't work on windows.// If you have pre-directX 8.1 - you'll want to define OLD_SURFACE//#define OLD_SURFACE 1#endif#ifdef _WIN32DEFINE_MESSAGE_MACRO(video_message, "videosync")#else#define video_message(loglevel, fmt...) message(loglevel, "videosync", fmt)#endifCSDLVideoSync::CSDLVideoSync (CPlayerSession *psptr) : CVideoSync(psptr){  char buf[32];  if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0 || !SDL_VideoDriverName(buf, 1)) {    video_message(LOG_CRIT, "Could not init SDL video: %s", SDL_GetError());  }  m_screen = NULL;  m_image = NULL;  m_video_initialized = 0;  m_config_set = 0;  m_have_data = 0;  for (int ix = 0; ix < MAX_VIDEO_BUFFERS; ix++) {    m_y_buffer[ix] = NULL;    m_u_buffer[ix] = NULL;    m_v_buffer[ix] = NULL;    m_buffer_filled[ix] = 0;  }  m_play_index = m_fill_index = 0;  m_decode_waiting = 0;  m_dont_fill = 0;  m_paused = 1;  m_behind_frames = 0;  m_total_frames = 0;  m_behind_time = 0;  m_behind_time_max = 0;  m_skipped_render = 0;  m_video_scale = 2;  m_msec_per_frame = 0;  m_consec_skipped = 0;  m_fullscreen = 0;  m_filled_frames = 0;  m_double_width = 0;  m_pixel_width = 0;  m_pixel_height = 0;  m_max_width = 0;  m_max_height = 0;}CSDLVideoSync::~CSDLVideoSync (void){  if (m_fullscreen != 0) {    m_fullscreen = 0;    do_video_resize();  }  if (m_image) {    SDL_FreeYUVOverlay(m_image);    m_image = NULL;  }  if (m_screen) {    SDL_FreeSurface(m_screen);    m_screen = NULL;  }  for (int ix = 0; ix < MAX_VIDEO_BUFFERS; ix++) {    if (m_y_buffer[ix] != NULL) {      free(m_y_buffer[ix]);      m_y_buffer[ix] = NULL;    }    if (m_u_buffer[ix] != NULL) {      free(m_u_buffer[ix]);      m_u_buffer[ix] = NULL;    }    if (m_v_buffer[ix] != NULL) {      free(m_v_buffer[ix]);      m_v_buffer[ix] = NULL;    }  }}/* * CSDLVideoSync::config - routine for the codec to call to set up the * width, height and frame_rate of the video */void CSDLVideoSync::config (int w, int h){  m_width = w;  m_height = h;  for (int ix = 0; ix < MAX_VIDEO_BUFFERS; ix++) {    m_y_buffer[ix] = (uint8_t *)malloc(w * h * sizeof(uint8_t));    m_u_buffer[ix] = (uint8_t *)malloc(w/2 * h/2 * sizeof(uint8_t));    m_v_buffer[ix] = (uint8_t *)malloc(w/2 * h/2 * sizeof(uint8_t));    m_buffer_filled[ix] = 0;  }  m_config_set = 1;}/* * CSDLVideoSync::initialize_video - Called from sync task to initialize * the video window */  int CSDLVideoSync::initialize_video (const char *name, int x, int y){  if (m_video_initialized == 0) {    if (m_config_set) {      const SDL_VideoInfo *video_info;      video_info = SDL_GetVideoInfo();      switch (video_info->vfmt->BitsPerPixel) {      case 16:      case 32:	m_video_bpp = video_info->vfmt->BitsPerPixel;	break;      default:	m_video_bpp = 16;	break;      }      SDL_ShowCursor(SDL_DISABLE);      SDL_SysWMinfo info;      SDL_VERSION(&info.version);      int ret;      ret = SDL_GetWMInfo(&info);      // Oooh... fun... To scale the video, just pass the width and height      // to this routine. (ie: m_width *2, m_height * 2).#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;      m_screen = SDL_SetVideoMode(w,				  h,				  m_video_bpp,				  mask);      if (ret > 0) {#ifdef unix	//	player_debug_message("Trying");	if (info.subsystem == SDL_SYSWM_X11) {	  info.info.x11.lock_func();	  XMoveWindow(info.info.x11.display, info.info.x11.wmwindow, x, y);	  info.info.x11.unlock_func();	}#endif      }      SDL_WM_SetCaption(name, NULL);      m_dstrect.x = 0;      m_dstrect.y = 0;      m_dstrect.w = m_screen->w;      m_dstrect.h = m_screen->h;#if 1      video_message(LOG_DEBUG, "Created mscreen %p hxw %d %d", m_screen, m_height,			   m_width);#endif	do_video_resize();#ifdef OLD_SURFACE	if (video_scale == 4) {      m_image = SDL_CreateYUVOverlay(m_width << 1, 				     m_height << 1,				     SDL_YV12_OVERLAY, 				     m_screen);	} else {#else	  {#endif      m_image = SDL_CreateYUVOverlay(m_width, 				     m_height,				     SDL_YV12_OVERLAY, 				     m_screen);	}      m_video_initialized = 1;      return (1);    } else {      return (0);    }  }  return (1);}/* * CSDLVideoSync::is_video_ready - called from sync task to determine if * we have sufficient number of buffers stored up to start displaying */int CSDLVideoSync::is_video_ready (uint64_t &disptime){  disptime = m_play_this_at[m_play_index];  if (m_dont_fill) {    return 0;  }#ifdef SHORT_VIDEO  return (m_buffer_filled[m_play_index] == 1);#else  return (m_buffer_filled[(m_play_index + 2*MAX_VIDEO_BUFFERS/3) % MAX_VIDEO_BUFFERS] == 1);#endif}void CSDLVideoSync::play_video (void) {}/* * CSDLVideoSync::play_video_at - called from sync task to show the next * video frame (if the timing is right */int64_t CSDLVideoSync::play_video_at (uint64_t current_time, 				   int &have_eof){  uint64_t play_this_at;  unsigned int ix;  uint8_t *to, *from;  /*   * If the next buffer is not filled, indicate that, as well   */  if (m_buffer_filled[m_play_index] == 0) {    /*     * If we have end of file, indicate it     */    if (m_eof_found != 0) {      have_eof = 1;      return (-1);    }    return 10;  }    /*   * we have a buffer.  If it is in the future, don't play it now   */  play_this_at = m_play_this_at[m_play_index];  if (play_this_at > current_time) {    return (play_this_at - current_time);  }#if VIDEO_SYNC_PLAY  video_message(LOG_DEBUG, "play "LLU" at "LLU " %d", play_this_at, current_time,		       m_play_index);#endif  /*   * If we're behind - see if we should just skip it   */  if (play_this_at < current_time) {    m_behind_frames++;    uint64_t behind = current_time - play_this_at;    m_behind_time += behind;    if (behind > m_behind_time_max) m_behind_time_max = behind;#if 0    if ((m_behind_frames % 64) == 0) {      video_message(LOG_DEBUG, "behind "LLU" avg "LLU" max "LLU,			   behind, m_behind_time / m_behind_frames,			   m_behind_time_max);    }#endif  }  m_paused = 0;  /*   * If we're within 1/2 of the frame time, go ahead and display   * this frame   */#define CHECK_SYNC_TIME 1#ifdef CHECK_SYNC_TIME  int showed = 0;  if ((m_msec_per_frame == 0) ||       ((play_this_at + m_msec_per_frame) > current_time) ||      (m_consec_skipped > 10)) {#else    {#endif      showed = 1;      m_consec_skipped = 0;    if (SDL_LockYUVOverlay(m_image)) {      video_message(LOG_ERR, "Failed to lock image");    } else {    // Must always copy the buffer to memory.  This creates 2 copies of this    // data (probably a total of 6 - libsock -> rtp -> decoder -> our ring ->    // sdl -> hardware)#ifdef OLD_SURFACE    if (m_fullscreen == 0 && m_video_scale == 4) {      // when scaling to 200%, don't use SDL stretch blit      // use a smoothing (averaging) blit instead#ifdef USE_MMX      FrameDoublerMmx(m_y_buffer[m_play_index], m_image->pixels[0], 		      m_width, m_height);      FrameDoublerMmx(m_v_buffer[m_play_index], m_image->pixels[1], 		      m_width >> 1, m_height >> 1);      FrameDoublerMmx(m_u_buffer[m_play_index], m_image->pixels[2], 		      m_width >> 1, m_height >> 1);#else      FrameDoubler(m_y_buffer[m_play_index], m_image->pixels[0], 		   m_width, m_height, m_image->pitches[0]);      FrameDoubler(m_v_buffer[m_play_index], m_image->pixels[1], 		   m_width >> 1, m_height >> 1, m_image->pitches[1]);      FrameDoubler(m_u_buffer[m_play_index], m_image->pixels[2], 		   m_width >> 1, m_height >> 1, m_image->pitches[2]);#endif    } else #endif      {	// let SDL blit, either 1:1 for 100% or decimating by 2:1 for 50%	uint32_t bufsize = m_width * m_height * sizeof(uint8_t);	unsigned int width = m_width, height = m_height;	if (width != m_image->pitches[0]) {	  to = (uint8_t *)m_image->pixels[0];	  from = m_y_buffer[m_play_index];	  for (ix = 0; ix < height; ix++) {	    memcpy(to, from, width);	    to += m_image->pitches[0];	    from += width;	  }	} else {	  memcpy(m_image->pixels[0], 		 m_y_buffer[m_play_index], 		 bufsize);	}	bufsize /= 4;	width /= 2;	height /= 2;#ifdef SWAP_UV#define V 2#define U 1#else#define V 1#define U 2#endif	if (width != m_image->pitches[V]) {	    to = (uint8_t *)m_image->pixels[V];	    from = m_v_buffer[m_play_index];	  for (ix = 0; ix < height; ix++) {	    memcpy(to, from, width);	    to += m_image->pitches[V];	    from += width;	  }	} else {	  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);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -