C++ 使用ffmpeg和XAudio2解码和播放音频-频率raito错误
我使用ffmpeg对音频进行解码,并使用XAudio2 API进行输出,它使用pts与视频输出同步工作和播放。但它的音调很高(即听起来像花栗鼠)C++ 使用ffmpeg和XAudio2解码和播放音频-频率raito错误,c++,windows,audio,ffmpeg,xaudio2,C++,Windows,Audio,Ffmpeg,Xaudio2,我使用ffmpeg对音频进行解码,并使用XAudio2 API进行输出,它使用pts与视频输出同步工作和播放。但它的音调很高(即听起来像花栗鼠) #include "DVDAudioCodecFFmpeg.h" #include "Log.h" CDVDAudioCodecFFmpeg::CDVDAudioCodecFFmpeg() : CDVDAudioCodec() { m_iBufferSize = 0; m_pCodecContext = NULL; m_b
设置断点我可以看到它设置了CreateSourceVoice中音频编解码器的正确采样率。我被难住了 任何帮助都将不胜感激#include "DVDAudioCodecFFmpeg.h" #include "Log.h" CDVDAudioCodecFFmpeg::CDVDAudioCodecFFmpeg() : CDVDAudioCodec() { m_iBufferSize = 0; m_pCodecContext = NULL; m_bOpenedCodec = false; } CDVDAudioCodecFFmpeg::~CDVDAudioCodecFFmpeg() { Dispose(); } bool CDVDAudioCodecFFmpeg::Open(AVCodecID codecID, int iChannels, int iSampleRate) { AVCodec* pCodec; m_bOpenedCodec = false; av_register_all(); pCodec = avcodec_find_decoder(codecID); m_pCodecContext = avcodec_alloc_context3(pCodec);//avcodec_alloc_context(); avcodec_get_context_defaults3(m_pCodecContext, pCodec); if (!pCodec) { CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Open() Unable to find codec"); return false; } m_pCodecContext->debug_mv = 0; m_pCodecContext->debug = 0; m_pCodecContext->workaround_bugs = 1; if (pCodec->capabilities & CODEC_CAP_TRUNCATED) m_pCodecContext->flags |= CODEC_FLAG_TRUNCATED; m_pCodecContext->channels = iChannels; m_pCodecContext->sample_rate = iSampleRate; //m_pCodecContext->bits_per_sample = 24; /* //FIXME BRENT if( ExtraData && ExtraSize > 0 ) { m_pCodecContext->extradata_size = ExtraSize; m_pCodecContext->extradata = m_dllAvCodec.av_mallocz(ExtraSize + FF_INPUT_BUFFER_PADDING_SIZE); memcpy(m_pCodecContext->extradata, ExtraData, ExtraSize); } */ // set acceleration //m_pCodecContext->dsp_mask = FF_MM_FORCE | FF_MM_MMX | FF_MM_MMXEXT | FF_MM_SSE; //BRENT if (avcodec_open2(m_pCodecContext, pCodec, NULL) < 0) { CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Open() Unable to open codec"); Dispose(); return false; } m_bOpenedCodec = true; return true; } void CDVDAudioCodecFFmpeg::Dispose() { if (m_pCodecContext) { if (m_bOpenedCodec) avcodec_close(m_pCodecContext); m_bOpenedCodec = false; av_free(m_pCodecContext); m_pCodecContext = NULL; } m_iBufferSize = 0; } int CDVDAudioCodecFFmpeg::Decode(BYTE* pData, int iSize) { int iBytesUsed; if (!m_pCodecContext) return -1; //Copy into a FFMpeg AVPAcket again AVPacket packet; av_init_packet(&packet); packet.data=pData; packet.size=iSize; int iOutputSize = AVCODEC_MAX_AUDIO_FRAME_SIZE; //BRENT iBytesUsed = avcodec_decode_audio3(m_pCodecContext, (int16_t *)m_buffer, &iOutputSize/*m_iBufferSize*/, &packet); m_iBufferSize = iOutputSize;//BRENT return iBytesUsed; } int CDVDAudioCodecFFmpeg::GetData(BYTE** dst) { *dst = m_buffer; return m_iBufferSize; } void CDVDAudioCodecFFmpeg::Reset() { if (m_pCodecContext) avcodec_flush_buffers(m_pCodecContext); } int CDVDAudioCodecFFmpeg::GetChannels() { if (m_pCodecContext) return m_pCodecContext->channels; return 0; } int CDVDAudioCodecFFmpeg::GetSampleRate() { if (m_pCodecContext) return m_pCodecContext->sample_rate; return 0; } int CDVDAudioCodecFFmpeg::GetBitsPerSample() { if (m_pCodecContext) return 16; return 0; }
#include "DVDAudioDevice.h" HANDLE m_hBufferEndEvent; CDVDAudio::CDVDAudio() { m_pXAudio2 = NULL; m_pMasteringVoice = NULL; m_pSourceVoice = NULL; m_pWfx = NULL; m_VoiceCallback = NULL; m_hBufferEndEvent = CreateEvent(NULL, false, false, "Buffer end event"); } CDVDAudio::~CDVDAudio() { m_pXAudio2 = NULL; m_pMasteringVoice = NULL; m_pSourceVoice = NULL; m_pWfx = NULL; m_VoiceCallback = NULL; CloseHandle(m_hBufferEndEvent); m_hBufferEndEvent = NULL; } bool CDVDAudio::Create(int iChannels, int iBitrate, int iBitsPerSample, bool bPasstrough) { CoInitializeEx(NULL, COINIT_MULTITHREADED); HRESULT hr = XAudio2Create( &m_pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR); if (SUCCEEDED(hr)) { m_pXAudio2->CreateMasteringVoice( &m_pMasteringVoice ); } // Create source voice WAVEFORMATEXTENSIBLE wfx; memset(&wfx, 0, sizeof(WAVEFORMATEXTENSIBLE)); wfx.Format.wFormatTag = WAVE_FORMAT_PCM; wfx.Format.nSamplesPerSec = iBitrate;//pFFMpegData->pAudioCodecCtx->sample_rate;//48000 by default wfx.Format.nChannels = iChannels;//pFFMpegData->pAudioCodecCtx->channels; wfx.Format.wBitsPerSample = 16; wfx.Format.nBlockAlign = wfx.Format.nChannels*16/8; wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign; wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); wfx.Samples.wValidBitsPerSample = wfx.Format.wBitsPerSample; if(wfx.Format.nChannels == 1) { wfx.dwChannelMask = SPEAKER_MONO; } else if(wfx.Format.nChannels == 2) { wfx.dwChannelMask = SPEAKER_STEREO; } else if(wfx.Format.nChannels == 5) { wfx.dwChannelMask = SPEAKER_5POINT1; } wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; unsigned int flags = 0;//XAUDIO2_VOICE_NOSRC;// | XAUDIO2_VOICE_NOPITCH; //Source voice m_VoiceCallback = new StreamingVoiceCallback(this); hr = m_pXAudio2->CreateSourceVoice(&m_pSourceVoice,(WAVEFORMATEX*)&wfx, 0 , 1.0f, m_VoiceCallback); if(!SUCCEEDED(hr)) return false; // Start sound hr = m_pSourceVoice->Start(0); if(!SUCCEEDED(hr)) return false; return true; } DWORD CDVDAudio::AddPackets(unsigned char* data, DWORD len) { memset(&m_SoundBuffer,0,sizeof(XAUDIO2_BUFFER)); m_SoundBuffer.AudioBytes = len; m_SoundBuffer.pAudioData = data; m_SoundBuffer.pContext = NULL;//(VOID*)data; XAUDIO2_VOICE_STATE state; while(m_pSourceVoice->GetState( &state ), state.BuffersQueued > 60) { WaitForSingleObject( m_hBufferEndEvent, INFINITE ); } m_pSourceVoice->SubmitSourceBuffer( &m_SoundBuffer ); return 0; } void CDVDAudio::Destroy() { m_pMasteringVoice->DestroyVoice(); m_pXAudio2->Release(); m_pSourceVoice->DestroyVoice(); delete m_VoiceCallback; m_VoiceCallback = NULL; }
#包括“dvdadiocodecffmpeg.h” #包括“Log.h” CDVDAudioCodecFFmpeg::CDVDAudioCodecFFmpeg():CDVDAudioCodec() { m_iBufferSize=0; m_pCodecContext=NULL; m_bOpenedCodec=假; } CDVDAudioCodecFFmpeg::~CDVDAudioCodecFFmpeg() { 处置(); } bool-CDVDAudioCodecFFmpeg::Open(AVCodecID-codecID,int-ichannes,int-iSampleRate) { AVCodec*pCodec; m_bOpenedCodec=假; av_寄存器_all(); pCodec=avcodec\u find\u解码器(codecID); m_pCodecContext=avcodec_alloc_context3(pCodec);//avcodec_alloc_context(); avcodec_get_context_defaults3(m_pCodecContext,pCodec); 如果(!pCodec) { CLog::Log(LOGERROR,“CDVDAudioCodecFFmpeg::Open()找不到编解码器”); 返回false; } m_pCodecContext->debug_mv=0; m_pCodecContext->debug=0; m_pCodecContext->workarou\u bugs=1; if(pCodec->功能和编解码器\u CAP\u截断) m_pCodecContext->flags |=编解码器_FLAG_截断; m_pCodecContext->channels=i通道; m_pCodecContext->sample_rate=iSampleRate; //m_pCodecContext->bits_per_sample=24; /*//修理我,布伦特 如果(ExtraData&&ExtraSize>0) { m_pCodecContext->extradata_size=ExtraSize; m_pCodecContext->extradata=m_dllAvCodec.av_mallocz(ExtraSize+FF_INPUT_BUFFER_PADDING_SIZE); memcpy(m_pCodecContext->extradata、extradata、ExtraSize); } */ //设定加速度 //m|u pCodecContext->dsp_mask=FF|MM|u FORCE | FF|MM|u MMX | FF|MM|MMXEXT | FF|u MM|SSE;//BRENT if(avcodec_open2(m_pCodecContext,pCodec,NULL)<0) { CLog::Log(LOGERROR,“CDVDAudioCodecFFmpeg::Open()无法打开编解码器”); 处置(); 返回false; } m_bOpenedCodec=真; 返回true; } void CDVDAudioCodecFFmpeg::Dispose() { if(m_pCodecContext) { 如果(m_bOpenedCodec)avcodec_close(m_pCodecContext); m_bOpenedCodec=假; av_free(m_pCodecContext); m_pCodecContext=NULL; } m_iBufferSize=0; } int-CDVDAudioCodecFFmpeg::Decode(字节*pData,int-iSize) { 使用的int-ibytes; if(!m_pCodecContext)返回-1; //再次复制到FFMpeg AV数据包中 数据包; av_初始_数据包(&数据包); packet.data=pData; packet.size=iSize; int iOutputSize=AVCODEC\u MAX\u AUDIO\u FRAME\u SIZE;//布伦特 iBytesUsed=avcodec\u decode\u audio3(m_pCodecContext,(int16_t*)m_buffer,&iOutputSize/*m_iBufferSize*/,&packet); m_iBufferSize=iOutputSize;//布伦特 返回已使用的IBytes; } int CDVDAudioCodecFFmpeg::GetData(字节**dst) { *dst=m_缓冲区; 返回m_iBufferSize; } 无效CDVDAudioCodecFFmpeg::Reset() { if(m_pCodecContext)avcodec_flush_缓冲区(m_pCodecContext); } int-CDVDAudioCodecFFmpeg::GetChannels() { 如果(m_pCodecContext)返回m_pCodecContext->channels; 返回0; } int-CDVDAudioCodecFFmpeg::GetSampleRate() { 如果(m_pCodecContext)返回m_pCodecContext->sample_rate; 返回0; } int-CDVDAudioCodecFFmpeg::GetBitsPerSample() { if(m_pCodecContext)返回16; 返回0; }
#包括“DVDPlayerAudio.h” #包括“dvdemuxutils.h” #包括“Log.h” #包括 #包括“DVDAudioCodecFFmpeg.h”//FIXME移动到编解码器工厂!! CDVDPlayerAudio::CDVDPlayerAudio(CDVDClock*pClock):CThread() { m_pClock=pClock; m_pAudioCodec=NULL; m_binInitializeDoutPutDevice=false; m_iSourceChannels=0; m_音频时钟=0; //m_currentpsitem.pts=DVD_NOPTS_值; //m_currentpsitem.timestamp=0; 设置速度(DVD_播放速度_正常); 初始化CriticalSection(&m_-CriticalSection); m_messageQueue.SetMaxDataSize(10*16*1024); //g_DVD PerformanceCounter.EnableAudioQueue(&m_packetQueue); } CDVDPlayerAudio::~CDVDPlayerAudio() { //g_DVD PerformanceCounter.DisableAudioQueue(); //关闭流,不要等待音频完成 CloseStream(真); 删除关键部分(&m_部分); } bool CDVDPlayerAudio::OpenStream(CDemuxStreamAudio*pDemuxStream) { //如果总是空的!!!!,在这里删除m_pAudioCodec时可能会崩溃。 if(m_pAudioCodec) { CLog::Log(LOGFATAL,“CDVDPlayerAudio::OpenStream()m_pAudioCodec!=NULL”); 返回false; } AVCodecID codecID=pDemuxStream->codec; CLog::Log(LOGNOTICE,“查找%i的音频编解码器”,codecID); //m_pAudioCodec=CDVDFactoryCodec::CreateAudioCodec(pDemuxStream); m_pAudioCodec=新的CDVDAudioCodecFFmpeg;//需要FIXME BRENT编解码器工厂! 如果(!m_pAudioCodec->Open(pDemuxStream->codec,pDemuxStream->iChannels,pDemuxStream->iSampleRate)) { m_pAudioCodec->Dispose(); 删除m_Paudio编解码器; m_pAudioCodec=NULL; 返回false; } if(!m_pAudioCodec) { CLog::Log(LOGERROR,“不支持的音频编解码器”); 返回false; } m_codec=pDemuxStream->codec; m_iSourceChannels=pDemuxStream->iChannels; m_messageQueue.Init(); CLog::Log(LOGNOTICE,“创建音频线程”); 创建(); 返回true; } void CDVDPlayerAudio::CloseStream(bool bWaitForBuffers) { //等待缓冲区为空 if(bWaitForBuffers)m_messageQueue.WaitUntilEmpty(); //向音频队列发送中止消息 m_messageQueue.Abort(); CLog::Log(LOGNOTICE,“等待音频线程退出”); //关闭adio_解码线程并等待它 StopThread();//将此->m_bStop设置为true 此->WaitForThreadExit(无限); //取消指定队列 m_messageQueue.End(); 木块:原木(L)