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

📄 audio_encoder_class.cpp

📁 完整的RTP RTSP代码库
💻 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. 2002.  All Rights Reserved. *  * Contributor(s):  *	Bill May		wmay@cisco.com	 *	Peter Maersk-Moller	peter@maersk-moller.net */#include "mp4live.h"#include "audio_encoder.h"#include "mp4av.h"//#define DEBUG_SYNC 1//#define DEBUG_AUDIO_RESAMPLER 1//#define DEBUG_AUDIO_SYNC 1CAudioEncoder::CAudioEncoder(CAudioProfile *profile,			     CAudioEncoder *next, 			     u_int8_t srcChannels,			     u_int32_t srcSampleRate,			     uint16_t mtu,			     bool realTime) :  CMediaCodec(profile, mtu, next, realTime) {    m_audioSrcChannels = srcChannels;    m_audioSrcSampleRate = srcSampleRate;    m_audioPreEncodingBuffer = NULL;    m_audioPreEncodingBufferLength = 0;    m_audioPreEncodingBufferMaxLength = 0;    m_audioResample = NULL;    m_audioSrcFrameNumber = 0;}void CAudioEncoder::Initialize (void){  // called from derived classes init function from the start function  // in the media flow  m_audioSrcFrameNumber = 0;  m_audioDstFrameNumber = 0;  m_audioDstSampleNumber = 0;  m_audioSrcElapsedDuration = 0;  m_audioDstElapsedDuration = 0;  // destination parameters are from the audio profile  m_audioDstType = GetFrameType();  m_audioDstSampleRate = m_pConfig->GetIntegerValue(CFG_AUDIO_SAMPLE_RATE);  m_audioDstChannels = m_pConfig->GetIntegerValue(CFG_AUDIO_CHANNELS);  m_audioDstSamplesPerFrame = GetSamplesPerFrame();  // if we need to resample  if (m_audioDstSampleRate != m_audioSrcSampleRate) {    // create a resampler for each audio destination channel -     // we will combine the channels before resampling    m_audioResample = (resample_t *)malloc(sizeof(resample_t) *					   m_audioDstChannels);    for (int ix = 0; ix < m_audioDstChannels; ix++) {      m_audioResample[ix] = st_resample_start(m_audioSrcSampleRate, 					      m_audioDstSampleRate);    }  }  // this calculation doesn't take into consideration the resampling  // size of the src.  4 times might not be enough - we need most likely  // 2 times the max of the src samples and the dest samples  m_audioPreEncodingBufferLength = 0;  m_audioPreEncodingBufferMaxLength =    4 * DstSamplesToBytes(m_audioDstSamplesPerFrame);  m_audioPreEncodingBuffer = (u_int8_t*)realloc(						m_audioPreEncodingBuffer,						m_audioPreEncodingBufferMaxLength);}// Audio encoding main processint CAudioEncoder::ThreadMain(void) {  CMsg* pMsg;  bool stop = false;  debug_message("audio encoder thread %s %s %s start", Profile()->GetName(),		Profile()->GetStringValue(CFG_AUDIO_ENCODER), 		Profile()->GetStringValue(CFG_AUDIO_ENCODING));  while (stop == false && SDL_SemWait(m_myMsgQueueSemaphore) == 0) {    pMsg = m_myMsgQueue.get_message();    if (pMsg != NULL) {      switch (pMsg->get_value()) {      case MSG_NODE_STOP_THREAD:	DoStopAudio();	stop = true;	break;      case MSG_NODE_START:	// DoStartTransmit();  Anything ?	break;      case MSG_NODE_STOP:	DoStopAudio();	break;      case MSG_SINK_FRAME: {	uint32_t dontcare;	CMediaFrame *mf = (CMediaFrame*)pMsg->get_message(dontcare);	if (m_stop_thread == false)	  ProcessAudioFrame(mf);	if (mf->RemoveReference()) {	  delete mf;	}	break;      }      }            delete pMsg;    }  }  while ((pMsg = m_myMsgQueue.get_message()) != NULL) {    if (pMsg->get_value() == MSG_SINK_FRAME) {      uint32_t dontcare;      CMediaFrame *mf = (CMediaFrame*)pMsg->get_message(dontcare);      if (mf->RemoveReference()) {	delete mf;      }    }    delete pMsg;  }  if (m_audioResample != NULL) {    for (uint ix = 0; ix < m_audioDstChannels; ix++) {      st_resample_stop(m_audioResample[ix]);      m_audioResample[ix] = NULL;    }    free(m_audioResample);  }  CHECK_AND_FREE(m_audioPreEncodingBuffer);  debug_message("audio encoder thread %s exit", Profile()->GetName());  return 0;}void CAudioEncoder::AddSilenceFrame(void){  int bytes = DstSamplesToBytes(m_audioDstSamplesPerFrame);  uint8_t *pSilenceData = (uint8_t *)Malloc(bytes);  memset(pSilenceData, 0, bytes);  bool rc = EncodeSamples(			  (int16_t*)pSilenceData,			  m_audioDstSamplesPerFrame,			  m_audioDstChannels);  if (!rc) {    debug_message("failed to encode audio");    return;  }  ForwardEncodedAudioFrames();  free(pSilenceData);}void CAudioEncoder::ProcessAudioFrame(CMediaFrame *pFrame){  const u_int8_t* frameData = (const uint8_t *)pFrame->GetData();  u_int32_t frameDataLength = pFrame->GetDataLength();  Timestamp srcFrameTimestamp = pFrame->GetTimestamp();;  bool pcmMalloced = false;  bool pcmBuffered;  const u_int8_t* pcmData = frameData;  u_int32_t pcmDataLength = frameDataLength;  uint32_t audioSrcSamplesPerFrame = SrcBytesToSamples(frameDataLength);  Duration subtractDuration = 0;  /*************************************************************************   * First convert input samples to format we need them to be in   *************************************************************************/  if (m_audioSrcChannels != m_audioDstChannels) {    // Convert the channels if they don't match    // we either double the channel info, or combine    // the left and right    uint32_t samples = SrcBytesToSamples(frameDataLength);    uint32_t dstLength = DstSamplesToBytes(samples);    pcmData = (u_int8_t *)Malloc(dstLength);    pcmDataLength = dstLength;    pcmMalloced = true;    int16_t *src = (int16_t *)frameData;    int16_t *dst = (int16_t *)pcmData;    if (m_audioSrcChannels == 1) {      // 1 channel to 2      for (uint32_t ix = 0; ix < samples; ix++) {	*dst++ = *src;	*dst++ = *src++;      }    } else {      // 2 channels to 1      for (uint32_t ix = 0; ix < samples; ix++) {	int32_t sum = *src++;	sum += *src++;	sum /= 2;	if (sum < -32768) sum = -32768;	else if (sum > 32767) sum = 32767;	*dst++ = sum & 0xffff;      }    }  }  // resample audio, if necessary  if (m_audioSrcSampleRate != m_audioDstSampleRate) {    subtractDuration =       DstSamplesToTicks(DstBytesToSamples(m_audioPreEncodingBufferLength));      ResampleAudio(pcmData, pcmDataLength);    // resampled data is now available in m_audioPreEncodingBuffer    pcmBuffered = true;  } else if (audioSrcSamplesPerFrame != m_audioDstSamplesPerFrame) {    // reframe audio, if necessary    // e.g. MP3 is 1152 samples/frame, AAC is 1024 samples/frame    // add samples to end of m_audioPreEncodingBuffer    // InitAudio() ensures that buffer is large enough    if (m_audioPreEncodingBuffer == NULL) {      m_audioPreEncodingBuffer = 	(u_int8_t*)realloc(m_audioPreEncodingBuffer,			   m_audioPreEncodingBufferMaxLength);    }    subtractDuration =       DstSamplesToTicks(DstBytesToSamples(m_audioPreEncodingBufferLength));    memcpy(	   &m_audioPreEncodingBuffer[m_audioPreEncodingBufferLength],	   pcmData,	   pcmDataLength);    m_audioPreEncodingBufferLength += pcmDataLength;    pcmBuffered = true;  } else {    // default case - just use what we're passed    pcmBuffered = false;  }   srcFrameTimestamp -= subtractDuration;  /************************************************************************   * Loop while we have enough samples   ************************************************************************/  Duration frametime = DstSamplesToTicks(m_audioDstSamplesPerFrame);  if (m_audioDstFrameNumber == 0)    debug_message("%s:frametime "U64, Profile()->GetName(), frametime);  while (1) {    /*     * Record starting timestamps     */    if (m_audioSrcFrameNumber == 0) {      /*       * we use m_audioStartTimestamp to determine audio output start time       */      m_audioStartTimestamp = srcFrameTimestamp;#ifdef DEBUG_AUDIO_SYNC      if (Profile()->GetBoolValue(CFG_AUDIO_DEBUG))	debug_message("%s:m_audioStartTimestamp = "U64, 		      Profile()->GetName(), m_audioStartTimestamp);#endif    }        if (m_audioDstFrameNumber == 0) {      // we wait until we see the first encoded frame.      // this is because encoders usually buffer the first few      // raw audio frames fed to them, and this number varies      // from one encoder to another      // We use this value to determine if we need to drop due to      // a bad input frequency      m_audioEncodingStartTimestamp = srcFrameTimestamp;    }        // we calculate audioSrcElapsedDuration by taking the current frame's    // timestamp and subtracting the audioEncodingStartTimestamp (and NOT

⌨️ 快捷键说明

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