C++ 使用ffmpeg和XAudio2解码和播放音频-频率raito错误

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

我使用ffmpeg对音频进行解码,并使用XAudio2 API进行输出,它使用pts与视频输出同步工作和播放。但它的音调很高(即听起来像花栗鼠)

#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;
}
设置断点我可以看到它设置了CreateSourceVoice中音频编解码器的正确采样率。我被难住了

任何帮助都将不胜感激

#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)