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

📄 video_sdl.cpp

📁 完整的RTP RTSP代码库
💻 CPP
字号:
/* * 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. 2001-2005.  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 "video_sdl.h"#include "SDL_error.h"#include "SDL_syswm.h"#include "our_config_file.h"#include "mpeg4ip_utils.h"#include "player_util.h"//#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#define WM_WIN 1#endif#if defined (__unix__)#define WM_X11#endif#ifdef _WIN32DEFINE_MESSAGE_MACRO(video_message, "videosync")#else#define video_message(loglevel, fmt...) message(loglevel, "videosync", fmt)#endif/* * CSDLVideo class is the interface to SDL.  We probably want to  * move this to another file, to leave the ring buffer code (what is * CSDLVideoSync) alone * Having this seperate allows us to keep the video window present between * changing sessions. */CSDLVideo::CSDLVideo(int initial_x, int initial_y, uint32_t mask){  char buf[32];  const SDL_VideoInfo *video_info;  m_mutex = SDL_CreateMutex();  m_image = NULL;  m_screen = NULL;  m_pos_x = initial_x;  m_pos_y = initial_y;  m_mask = mask;  m_name = NULL;  m_pixel_width = -1;  m_pixel_height = -1;  m_max_width = -1;  m_max_height = -1;  // One time initialization stuff  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());  }  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;  }  m_old_win_w = m_old_win_h = 0;  m_old_w = m_old_h = 0;  SDL_ShowCursor(SDL_DISABLE);  //Query the current Window system resolution   SDL_SysWMinfo         info;  SDL_VERSION(&info.version);  if (SDL_GetWMInfo(&info)) {#if defined(WM_X11)  if ( info.subsystem == SDL_SYSWM_X11 ) {        info.info.x11.lock_func();	m_max_width = DisplayWidth(info.info.x11.display,                             DefaultScreen(info.info.x11.display));	m_max_height = DisplayHeight(info.info.x11.display,                             DefaultScreen(info.info.x11.display));        info.info.x11.unlock_func();        video_message(LOG_INFO, "Max Window resolution %dx%d", m_max_width, m_max_height);  } else {      video_message(LOG_ERR, "Failed to get Max resolution foe window system");  }#elif defined (WM_WIN)      m_max_width=GetSystemMetrics(SM_CXSCREEN);      m_max_height=GetSystemMetrics(SM_CYSCREEN);      video_message(LOG_INFO, "Max Window resolution %dx%d", m_max_width, m_max_height);#endif  }}/* * Clean up - free everything */CSDLVideo::~CSDLVideo (void){  CHECK_AND_FREE(m_name);  if (m_image) {    SDL_FreeYUVOverlay(m_image);    m_image = NULL;  }  if (m_screen) {    SDL_FreeSurface(m_screen);    m_screen = NULL;  }  if (m_mutex) {    SDL_DestroyMutex(m_mutex);    m_mutex = NULL;  }}void CSDLVideo::set_name (const char *name){  CHECK_AND_FREE(m_name);  m_name = strdup(name);}void CSDLVideo::set_image_size (unsigned int w, unsigned int h, double aspect){  m_image_w = w;  m_image_h = h;  m_aspect_ratio = aspect;  // don't actually do anything until set_screen_size is called}/* * Set the correct screen size. */void  CSDLVideo::set_screen_size(bool fullscreen, int video_scale, 				 int pixel_width, int pixel_height,				 int max_width, int max_height){  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 we should use old values.  if (pixel_width == -1 && m_pixel_width > -1) pixel_width = m_pixel_width;  if (pixel_height == -1 && m_pixel_height > -1) pixel_height = m_pixel_height;  if (max_width == -1 && m_max_width > -1) max_width = m_max_width;  if (max_height == -1 && m_max_height > -1) max_height = m_image_h;  if (video_scale <= 0) video_scale = m_video_scale;  int win_w = m_image_w * video_scale / 2;  int win_h = m_image_h * video_scale / 2;      // It is only when we have positive values larger than zero for  // pixel sizes that we resize  if (pixel_width > 0 && pixel_height > 0) {    // wmay - just use the passed in values.    win_w = (win_h * pixel_width) / pixel_height;#if 0    // Square pixels needs no resize.    if (pixel_width != pixel_height) {       // enable different handling of full screen versus non full screen      if (fullscreen == false) {	if (pixel_width > pixel_height)	  win_w = win_h * pixel_width / pixel_height;	else 	  win_h = win_w * pixel_height / pixel_width;      } else { 	// For now we do the same as in non full screen.	if (pixel_width > pixel_height)	  win_w = win_h * pixel_width / pixel_height;	else 	  win_h = win_w * pixel_height / pixel_width;      }    }#endif  } else {    // this case is when we set it from the aspect ratio defined.    if (m_aspect_ratio != 0.0 && m_aspect_ratio != 1.0) {      double win_wf = m_aspect_ratio;      int win_wtest;      win_wf *= win_h;      video_message(LOG_INFO, "aspect ratio %g %g %d %d", 		    m_aspect_ratio, win_wf, win_w, win_h);      win_wtest = (int)win_wf;      if (win_wtest >= win_w) {	win_w = win_wtest;      } else {	video_message(LOG_ERR, "aspect ratio width less than orig");      }    }  }  if (fullscreen) {    //Suren, get the max resolution of window system and scale to that    //--------    if(m_max_width > 0 ) win_w = m_max_width;    if (m_max_height > 0 ) win_h = m_max_height;    video_message(LOG_INFO, "Setting full screen mode %dx%d", win_w, win_h);    //--------  }  m_video_scale = video_scale;#ifdef OLD_SURFACE  int mask = SDL_SWSURFACE | SDL_ASYNCBLIT;#else  int mask = SDL_HWSURFACE;#endif  if (fullscreen) {    mask |= SDL_FULLSCREEN;#ifdef _WIN32    video_scale = 2;#endif  }  mask |= m_mask;  if (win_w == m_old_win_w &&      win_h == m_old_win_h &&      m_image_w == m_old_w &&      m_image_h == m_old_h &&      m_fullscreen == fullscreen) {    return;  }  video_message(LOG_DEBUG, "Setting video mode %d %d %x %g", 		win_w, win_h, mask, m_aspect_ratio);  m_fullscreen = fullscreen;  SDL_LockMutex(m_mutex);  if (m_image) {    SDL_FreeYUVOverlay(m_image);    m_image = NULL;  }  if (m_screen) {    SDL_FreeSurface(m_screen);    m_screen = NULL;  }  m_screen = SDL_SetVideoMode(win_w, win_h, m_video_bpp, 			      mask);  if (m_screen == NULL) {    m_screen = SDL_SetVideoMode(win_w, win_h, m_video_bpp, mask);    if (m_screen == NULL) {      video_message(LOG_CRIT, "sdl error message is %s", SDL_GetError());      SDL_Delay(1000);      abort();    }  }  if (m_pos_x != 0 || m_pos_y != 0) {    // we only try this the first time the video window gets initialized -     // not if we're resize a persistent connection    SDL_SysWMinfo info;    SDL_VERSION(&info.version);    int ret;    ret = SDL_GetWMInfo(&info);    if (ret > 0) {#ifdef unix      if (info.subsystem == SDL_SYSWM_X11) {	info.info.x11.lock_func();#if 0	XMoveWindow(info.info.x11.display, info.info.x11.wmwindow, 		    m_pos_x, m_pos_y);#else	XWindowChanges xchang;	memset(&xchang, 0, sizeof(xchang));	xchang.x = m_pos_x;	xchang.y = m_pos_y;	xchang.stack_mode = Above;	XConfigureWindow(info.info.x11.display,			 info.info.x11.wmwindow,			 CWStackMode | CWX | CWY,			 &xchang);#endif	info.info.x11.unlock_func();      }#endif    }    m_pos_x = 0;    m_pos_y = 0;  }  m_dstrect.x = 0;  m_dstrect.y = 0;  m_dstrect.w = m_screen->w;  m_dstrect.h = m_screen->h;#ifdef OLD_SURFACE  if (video_scale == 4) {    m_image = SDL_CreateYUVOverlay(m_image_w << 1, 				   m_image_h << 1,				   SDL_YV12_OVERLAY, 				   m_screen);  } else #endif    {    m_image = SDL_CreateYUVOverlay(m_image_w, 				   m_image_h,				   SDL_YV12_OVERLAY, 				   m_screen);    }  if (m_image_w > m_image->pitches[0]) {    video_message(LOG_ERR, "Window returned width of %u %u requested", 		  m_image->pitches[0], m_image_w);  }  if (m_name && strlen(m_name) != 0) {    SDL_WM_SetCaption(m_name, NULL);  }  SDL_UnlockMutex(m_mutex);  m_old_win_w = win_w;  m_old_win_h = win_h;  m_old_w = m_image_w;  m_old_h = m_image_h;}/* * Display the image - copy the yuv buffers to the SDL overlay * height and width are set via set_image_size call */void CSDLVideo::display_image (const uint8_t *y, const uint8_t *u, 			       const uint8_t *v,			       uint32_t yStride, uint32_t uvStride){  unsigned int ix;  uint8_t *to;  const uint8_t *from;  if (yStride == 0) yStride = m_image_w;  if (uvStride == 0)  uvStride = m_image_w / 2;  SDL_LockMutex(m_mutex);  if (SDL_LockYUVOverlay(m_image)) {    video_message(LOG_ERR, "Failed to lock image");    SDL_UnlockMutex(m_mutex);    return;  }   // 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 == false && m_video_scale == 4) {    // when scaling to 200%, don't use SDL stretch blit    // use a smoothing (averaging) blit instead    // we only do this for maybe windows - otherwise, let SDL do it.#if 0    // sorry - too many problems with this...    FrameDoublerMmx(y, m_image->pixels[0], 		    m_image_w, m_image_h);    FrameDoublerMmx(v, m_image->pixels[1], 		    m_image_w >> 1, m_image_h >> 1);    FrameDoublerMmx(u, m_image->pixels[2], 		    m_image_w >> 1, m_image_h >> 1);#else    FrameDoubler(y, m_image->pixels[0], 		 m_image_w, m_image_h, m_image->pitches[0]);    FrameDoubler(v, m_image->pixels[1], 		 m_image_w >> 1, m_image_h >> 1, m_image->pitches[1]);    FrameDoubler(u, m_image->pixels[2], 		 m_image_w >> 1, m_image_h >> 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_image_w * m_image_h * sizeof(uint8_t);      unsigned int width = m_image_w, height = m_image_h;      if (yStride != m_image->pitches[0]) {	// The width is not equal to the size in the SDL buffers - 	// we need to copy a row at a time	to = (uint8_t *)m_image->pixels[0];	from = y;	for (ix = 0; ix < height; ix++) {	  memcpy(to, from, MIN(width, m_image->pitches[0]));	  to += m_image->pitches[0];	  from += yStride;	}      } else {	// Copy entire Y frame	memcpy(m_image->pixels[0], 	       y,	       bufsize);      }      // We reduce the sizes for U and V planes (they are 1/4 the size)      bufsize /= 4;      width /= 2;      height /= 2;#ifdef SWAP_UV#define V 2#define U 1#else#define V 1#define U 2#endif      // Copy the U and V - same comments as above      if (uvStride != m_image->pitches[V]) {	to = (uint8_t *)m_image->pixels[V];	from = v;	for (ix = 0; ix < height; ix++) {	  memcpy(to, from, MIN(m_image->pitches[V], width));	  to += m_image->pitches[V];	  from += uvStride;	}      } else {	memcpy(m_image->pixels[V], 	       v,	       bufsize);      }      if (uvStride != m_image->pitches[U]) {	to = (uint8_t *)m_image->pixels[U];	from = u;	for (ix = 0; ix < height; ix++) {	  memcpy(to, from, MIN(width, m_image->pitches[U]));	  to += m_image->pitches[U];	  from += uvStride;	}      } else {	memcpy(m_image->pixels[U], 	       u,	       bufsize);      }          }  // unlock, then display  SDL_UnlockYUVOverlay(m_image);  // Actually display the video#ifndef darwin  int rval = #endif    SDL_DisplayYUVOverlay(m_image, &m_dstrect);  SDL_UnlockMutex(m_mutex);#ifndef darwin#define CORRECT_RETURN 0  if (rval != CORRECT_RETURN) {    video_message(LOG_ERR, "Return from display is %d", rval);  }#else#define CORRECT_RETURN 1#endif}#define BLANK_Y (0)#define BLANK_U (0x80)#define BLANK_V (0x80)void CSDLVideo::blank_image (void){  unsigned int ix;  uint8_t *to;  if (SDL_LockYUVOverlay(m_image)) {    video_message(LOG_ERR, "Failed to lock image");    return;  }   uint32_t bufsize = m_image_w * m_image_h * sizeof(uint8_t);  unsigned int width = m_image_w, height = m_image_h;  if (width != m_image->pitches[0]) {    // The width is not equal to the size in the SDL buffers -     // we need to copy a row at a time    to = (uint8_t *)m_image->pixels[0];    for (ix = 0; ix < height; ix++) {      memset(to, BLANK_Y, MIN(width, m_image->pitches[0]));      to += m_image->pitches[0];    }  } else {    // Copy entire Y frame    memset(m_image->pixels[0], 	   BLANK_Y,	   bufsize);  }        // We reduce the sizes for U and V planes (they are 1/4 the size)  bufsize /= 4;  width /= 2;  height /= 2;#ifdef SWAP_UV#define V 2#define U 1#else#define V 1#define U 2#endif  // Copy the U and V - same comments as above  if (width != m_image->pitches[V]) {    to = (uint8_t *)m_image->pixels[V];    for (ix = 0; ix < height; ix++) {      memset(to, BLANK_U, MIN(width, m_image->pitches[V]));      to += m_image->pitches[V];    }  } else {    memset(m_image->pixels[V], 	   BLANK_U,	   bufsize);  }  if (width != m_image->pitches[U]) {    to = (uint8_t *)m_image->pixels[U];    for (ix = 0; ix < height; ix++) {      memset(to, BLANK_V, MIN(m_image->pitches[U],width));      to += m_image->pitches[U];    }  } else {    memset(m_image->pixels[U], 	   BLANK_V,	   bufsize);  }        SDL_UnlockYUVOverlay(m_image);  SDL_DisplayYUVOverlay(m_image, &m_dstrect);}void CSDLVideo::set_cursor (bool setit){  SDL_ShowCursor(setit ? SDL_ENABLE : SDL_DISABLE);}void DestroyVideoPersistence (void *persist){  CSDLVideo *temp = (CSDLVideo *)persist;  delete temp;  SDL_Quit();}

⌨️ 快捷键说明

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