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

📄 media_source.cpp

📁 网络MPEG4IP流媒体开发源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * 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-2002.  All Rights Reserved. *  * Contributor(s):  *		Dave Mackie		dmackie@cisco.com */#include "mp4live.h"#include "media_source.h"#include "audio_encoder.h"#include "video_encoder.h"#include "video_util_rgb.h"#include <mp4av.h>#include "mpeg4ip_byteswap.h"//#define DEBUG_AUDIO_RESAMPLER 1//#define DEBUG_SYNC 1//#define DEBUG_SYNC_DRIFT 1//#define DEBUG_SYNC_DROPS 1//#define DEBUG_SYNC_LAG 1CMediaSource::CMediaSource() {  m_pSinksMutex = SDL_CreateMutex();  if (m_pSinksMutex == NULL) {    debug_message("CreateMutex error");  }  for (int i = 0; i < MAX_SINKS; i++) {    m_sinks[i] = NULL;  }  m_source = false;  m_sourceVideo = false;  m_sourceAudio = false;  m_maxAheadDuration = TimestampTicks / 20 ;	// 50 msec  m_videoSource = this;  m_videoSrcYImage = NULL;  m_videoDstYImage = NULL;  m_videoYResizer = NULL;  m_videoSrcUVImage = NULL;  m_videoDstUVImage = NULL;  m_videoUVResizer = NULL;  m_videoEncoder = NULL;  m_videoDstPrevImage = NULL;  m_videoDstPrevReconstructImage = NULL;  m_videoDstPrevFrame = NULL;  m_audioPreEncodingBuffer = NULL;  m_audioEncoder = NULL;  m_audioResample = NULL;}CMediaSource::~CMediaSource() {  SDL_DestroyMutex(m_pSinksMutex);  m_pSinksMutex = NULL;	  if (m_audioResample != NULL) {    for (int ix = 0; ix < m_audioDstChannels; ix++) {      free(m_audioResample[ix]);      m_audioResample[ix] = NULL;    }    free(m_audioResample);    m_audioResample = NULL;  }}bool CMediaSource::AddSink(CMediaSink* pSink) {  bool rc = false;  if (SDL_LockMutex(m_pSinksMutex) == -1) {    debug_message("AddSink LockMutex error");    return rc;  }  for (int i = 0; i < MAX_SINKS; i++) {    if (m_sinks[i] == NULL) {      m_sinks[i] = pSink;      rc = true;      break;    }  }  if (SDL_UnlockMutex(m_pSinksMutex) == -1) {    debug_message("UnlockMutex error");  }  return rc;}void CMediaSource::RemoveSink(CMediaSink* pSink) {  if (SDL_LockMutex(m_pSinksMutex) == -1) {    debug_message("RemoveSink LockMutex error");    return;  }  for (int i = 0; i < MAX_SINKS; i++) {    if (m_sinks[i] == pSink) {      int j;      for (j = i; j < MAX_SINKS - 1; j++) {	m_sinks[j] = m_sinks[j+1];      }      m_sinks[j] = NULL;      break;    }  }  if (SDL_UnlockMutex(m_pSinksMutex) == -1) {    debug_message("UnlockMutex error");  }}void CMediaSource::RemoveAllSinks(void) {  if (SDL_LockMutex(m_pSinksMutex) == -1) {    debug_message("RemoveAllSinks LockMutex error");    return;  }  for (int i = 0; i < MAX_SINKS; i++) {    if (m_sinks[i] == NULL) {      break;    }    m_sinks[i] = NULL;  }  if (SDL_UnlockMutex(m_pSinksMutex) == -1) {    debug_message("UnlockMutex error");  }}Duration CMediaSource::GetElapsedDuration(){  if (m_sourceVideo && m_sourceAudio) {    return MIN(m_videoSrcElapsedDuration, m_audioSrcElapsedDuration);  } else if (m_sourceVideo) {    return m_videoSrcElapsedDuration;  } else if (m_sourceAudio) {    return m_audioSrcElapsedDuration;  }  return 0;}void CMediaSource::ForwardFrame(CMediaFrame* pFrame){  if (SDL_LockMutex(m_pSinksMutex) == -1) {    debug_message("ForwardFrame LockMutex error");    return;  }  for (int i = 0; i < MAX_SINKS; i++) {    if (m_sinks[i] == NULL) {      break;    }    m_sinks[i]->EnqueueFrame(pFrame);  }  if (SDL_UnlockMutex(m_pSinksMutex) == -1) {    debug_message("UnlockMutex error");  }  if (pFrame->RemoveReference()) delete pFrame;  return;}void CMediaSource::DoStopSource(){  if (!m_source) {    return;  }  DoStopVideo();  DoStopAudio();  m_source = false;}bool CMediaSource::InitVideo(			     MediaType srcType,			     bool realTime){  m_sourceRealTime = realTime;  m_sinkRealTime = m_pConfig->GetBoolValue(CONFIG_RTP_ENABLE);  m_videoSrcType = srcType;  m_videoSrcFrameNumber = 0;  m_audioSrcFrameNumber = 0;	// ensure audio is also at zero  m_videoDstFrameRate =    m_pConfig->GetFloatValue(CONFIG_VIDEO_FRAME_RATE);  m_videoDstFrameDuration =     (Duration)(((float)TimestampTicks / m_videoDstFrameRate) + 0.5);  m_videoDstFrameNumber = 0;  m_videoEncodedFrames = 0;  m_videoDstWidth =    m_pConfig->m_videoWidth;  m_videoDstHeight =    m_pConfig->m_videoHeight;  m_videoDstAspectRatio =     (float)m_pConfig->m_videoWidth / (float)m_pConfig->m_videoHeight;  m_videoDstYSize = m_videoDstWidth * m_videoDstHeight;  m_videoDstUVSize = m_videoDstYSize / 4;  m_videoDstYUVSize = (m_videoDstYSize * 3) / 2;  // intialize encoder  m_videoEncoder =     VideoEncoderCreate(m_pConfig->GetStringValue(CONFIG_VIDEO_ENCODER));  m_videoDstType = m_videoEncoder->GetFrameType();  m_videoDstType = MPEG4VIDEOFRAME;  if (!m_videoEncoder) {    return false;  }  if (!m_videoEncoder->Init(m_pConfig, realTime)) {    delete m_videoEncoder;    m_videoEncoder = NULL;    return false;  }#ifdef DEBUG_VCODEC_SHADOW  m_videoEncoderShadow = VideoEncoderCreate("ffmpeg");  m_videoEncoderShadow->Init(m_pConfig, realTime);#endif  m_videoWantKeyFrame = true;  m_videoEncodingDrift = 0;  m_videoEncodingMaxDrift = m_videoDstFrameDuration;  m_videoSrcElapsedDuration = 0;  m_videoDstElapsedDuration = 0;  m_otherTotalDrift = 0;  m_otherLastTotalDrift = 0;  m_videoDstPrevImage = NULL;  m_videoDstPrevReconstructImage = NULL;  m_videoDstPrevFrame = NULL;  m_videoDstPrevFrameLength = 0;  return true;}void CMediaSource::SetVideoSrcSize(				   u_int16_t srcWidth,				   u_int16_t srcHeight,				   u_int16_t srcStride,				   bool matchAspectRatios){  // N.B. InitVideo() must be called first  m_videoSrcWidth = srcWidth;  m_videoSrcHeight = srcHeight;  m_videoSrcAspectRatio = (float)srcWidth / (float)srcHeight;  m_videoMatchAspectRatios = matchAspectRatios;  SetVideoSrcStride(srcStride);}void CMediaSource::SetVideoSrcStride(				     u_int16_t srcStride){  // N.B. SetVideoSrcSize() should be called once before   m_videoSrcYStride = srcStride;  m_videoSrcUVStride = srcStride / 2;  // these next three may change below  m_videoSrcAdjustedHeight = m_videoSrcHeight;  m_videoSrcYCrop = 0;  m_videoSrcUVCrop = 0;  // match aspect ratios  if (m_videoMatchAspectRatios       && fabs(m_videoSrcAspectRatio - m_videoDstAspectRatio) > 0.01) {    m_videoSrcAdjustedHeight =      (u_int16_t)(m_videoSrcWidth / m_videoDstAspectRatio);    if ((m_videoSrcAdjustedHeight % 16) != 0) {      m_videoSrcAdjustedHeight += 16 - (m_videoSrcAdjustedHeight % 16);    }    if (m_videoSrcAspectRatio < m_videoDstAspectRatio) {      // crop src      m_videoSrcYCrop = m_videoSrcYStride * 	((m_videoSrcHeight - m_videoSrcAdjustedHeight) / 2);      m_videoSrcUVCrop = m_videoSrcYCrop / 4;    }  }  m_videoSrcYSize = m_videoSrcYStride     * MAX(m_videoSrcHeight, m_videoSrcAdjustedHeight);  m_videoSrcUVSize = m_videoSrcYSize / 4;  m_videoSrcYUVSize = (m_videoSrcYSize * 3) / 2;  // resizing  DestroyVideoResizer();  if (m_videoSrcWidth != m_videoDstWidth       || m_videoSrcAdjustedHeight != m_videoDstHeight) {    m_videoSrcYImage =       scale_new_image(m_videoSrcWidth, 		      m_videoSrcAdjustedHeight, 1);    m_videoSrcYImage->span = m_videoSrcYStride;    m_videoDstYImage =       scale_new_image(m_videoDstWidth, 		      m_videoDstHeight, 1);    m_videoYResizer =       scale_image_init(m_videoDstYImage, m_videoSrcYImage, 		       Bell_filter, Bell_support);    m_videoSrcUVImage =       scale_new_image(m_videoSrcWidth / 2, 		      m_videoSrcAdjustedHeight / 2, 1);    m_videoSrcUVImage->span = m_videoSrcUVStride;    m_videoDstUVImage =       scale_new_image(m_videoDstWidth / 2, 		      m_videoDstHeight / 2, 1);    m_videoUVResizer =       scale_image_init(m_videoDstUVImage, m_videoSrcUVImage, 		       Bell_filter, Bell_support);  }}void CMediaSource::ProcessVideoYUVFrame(					u_int8_t* pY,					u_int8_t* pU,					u_int8_t* pV,					u_int16_t yStride,					u_int16_t uvStride,					Timestamp srcFrameTimestamp){  Duration temp;  m_videoSrcPrevElapsedDuration = m_videoSrcElapsedDuration;  if (m_videoSrcFrameNumber == 0) {    if (m_audioSrcFrameNumber == 0) {      m_encodingStartTimestamp = GetTimestamp();    }    m_videoStartTimestamp = srcFrameTimestamp;  }  m_videoSrcFrameNumber++;  temp = srcFrameTimestamp - m_videoStartTimestamp;  if (temp <= m_videoSrcElapsedDuration) {#ifdef DEBUG_SYNC    error_message("video duplication in source timestamp %llu %llu",		  srcFrameTimestamp, temp);#endif  }  m_videoSrcElapsedDuration = temp;  // drop src frames as needed to match target frame rate  if (m_videoDstElapsedDuration > m_videoSrcElapsedDuration) {#ifdef DEBUG_SYNC    debug_message("Dropping at %llu before %llu", 		  m_videoSrcElapsedDuration, m_videoDstElapsedDuration);#endif    return;  }  // if we're running in real-time mode  if (m_sourceRealTime) {    // add any external drift (i.e. audio encoding drift)    // to our drift measurement#if 0    debug_message("drift %llu other last %llu %llu", 		  m_videoEncodingDrift,		  m_otherLastTotalDrift, m_otherTotalDrift);#endif    m_videoEncodingDrift +=       m_otherTotalDrift - m_otherLastTotalDrift;    m_otherLastTotalDrift = m_otherTotalDrift;    // check if we are falling behind    if (m_videoEncodingDrift >= m_videoEncodingMaxDrift) {#ifdef DEBUG_SYNC_DROPS      debug_message("video skipping src frame %llu drift %llu max %llu", 		    m_videoSrcElapsedDuration,		    m_videoEncodingDrift, m_videoEncodingMaxDrift);      if (m_otherLastTotalDrift != 0 || m_otherTotalDrift != 0) {	debug_message("video other last %llu %llu", 		      m_otherLastTotalDrift, m_otherTotalDrift);      }#endif

⌨️ 快捷键说明

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