void AudioEngine::mixAudio(Uint8 *pDestBuffer, int destBufferLen) { int numFrames = destBufferLen/(2*getChannels()); // 16 bit samples. if (m_AudioSources.size() == 0) { return; } if (!m_pTempBuffer || m_pTempBuffer->getNumFrames() < numFrames) { if (m_pTempBuffer) { delete[] m_pMixBuffer; } m_pTempBuffer = AudioBufferPtr(new AudioBuffer(numFrames, m_AP)); m_pMixBuffer = new float[getChannels()*numFrames]; } for (int i = 0; i < getChannels()*numFrames; ++i) { m_pMixBuffer[i]=0; } { lock_guard lock(m_Mutex); AudioSourceMap::iterator it; for (it = m_AudioSources.begin(); it != m_AudioSources.end(); it++) { m_pTempBuffer->clear(); it->second->fillAudioBuffer(m_pTempBuffer); addBuffers(m_pMixBuffer, m_pTempBuffer); } } calcVolume(m_pMixBuffer, numFrames*getChannels(), getVolume()); for (int i = 0; i < numFrames; ++i) { m_pLimiter->process(m_pMixBuffer+i*getChannels()); for (int j = 0; j < getChannels(); ++j) { ((short*)pDestBuffer)[i*2+j]=short(m_pMixBuffer[i*2+j]*32768); } } }
// 获取声音缓冲区 ///////////////////////////////////////////////////////////////////////////////// AudioBufferPtr AudioEngine::Buffer(size_t bufID) const { AudioBufsConstIter iter(audioBufs_.find(bufID)); if (iter != audioBufs_.end()) { return iter->second; } BOOST_ASSERT(false); return AudioBufferPtr(); }
void AudioDecoderThread::decodePacket(AVPacket* pPacket) { char* pDecodedData = 0; AVPacket* pTempPacket = new AVPacket; av_init_packet(pTempPacket); pTempPacket->data = pPacket->data; pTempPacket->size = pPacket->size; AVFrame* pDecodedFrame; pDecodedFrame = avcodec_alloc_frame(); while (pTempPacket->size > 0) { int gotFrame = 0; int bytesDecoded; int bytesConsumed = avcodec_decode_audio4(m_pStream->codec, pDecodedFrame, &gotFrame, pTempPacket); if (gotFrame) { bytesDecoded = av_samples_get_buffer_size(0, m_pStream->codec->channels, pDecodedFrame->nb_samples, m_pStream->codec->sample_fmt, 1); pDecodedData = (char*)(pDecodedFrame->data[0]); } else { bytesDecoded = 0; } // This is triggered for some strange/broken videos. // AVG_ASSERT(bytesConsumed != 0); if (bytesConsumed < 0) { // Error decoding -> throw away current packet. bytesDecoded = 0; pTempPacket->size = 0; } else { pTempPacket->data += bytesConsumed; pTempPacket->size -= bytesConsumed; } if (bytesDecoded > 0) { int framesDecoded = bytesDecoded/(m_pStream->codec->channels* getBytesPerSample(m_InputSampleFormat)); AudioBufferPtr pBuffer; bool bNeedsResample = (m_InputSampleRate != m_AP.m_SampleRate || m_InputSampleFormat != AV_SAMPLE_FMT_S16 || m_pStream->codec->channels != m_AP.m_Channels); bool bIsPlanar = false; #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 27, 0) bIsPlanar = av_sample_fmt_is_planar((AVSampleFormat)m_InputSampleFormat); if (bIsPlanar) { char* pPackedData = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); planarToInterleaved(pPackedData, pDecodedFrame, m_pStream->codec->channels, framesDecoded); pBuffer = resampleAudio(pPackedData, framesDecoded, av_get_packed_sample_fmt((AVSampleFormat)m_InputSampleFormat)); av_free(pPackedData); bNeedsResample = false; } #endif if (bNeedsResample) { pBuffer = resampleAudio(pDecodedData, framesDecoded, m_InputSampleFormat); } else if (!bIsPlanar) { pBuffer = AudioBufferPtr(new AudioBuffer(framesDecoded, m_AP)); memcpy(pBuffer->getData(), pDecodedData, bytesDecoded); } m_LastFrameTime += float(pBuffer->getNumFrames())/m_AP.m_SampleRate; pushAudioMsg(pBuffer, m_LastFrameTime); } } #if LIBAVCODEC_VERSION_MAJOR > 53 avcodec_free_frame(&pDecodedFrame); delete pDecodedFrame; #endif delete pTempPacket; }