Directshow CLSID_AsyncReader:如何设置输出引脚样本大小?

问题描述

我正在尝试从磁盘播放 wav 文件(44100sr 16 位 2 声道),我需要在 samplegrabber 过滤器回调中处理音频数据,但它总是每秒四次收到 44100 字节数据,我想要要将回调速率更改为每秒 10 次(音频样本大小:每次回调 17640 字节),而不是四次(每次 44100 字节),我该如何使其按预期工作?

''' hr = CoCreateInstance(CLSID_samplegrabber,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void **)&m_pBgmAudioGrabber); BREAK_IF_Failed(小时);

    hr = m_pGraph->AddFilter((IBaseFilter*)m_pBgmAudioGrabber,L"Bgm Audio Mix");
    BREAK_IF_Failed(hr);

    hr = InitBgmAudioGrabble();
    BREAK_IF_Failed(hr);

    CComPtr<IPin> pAudioMixInputPin;
    hr = g_DSHelper.GetPin(m_pBgmAudioGrabber,PINDIR_INPUT,&pAudioMixInputPin);
    g_DSHelper.SetAudioFilterBuffer(pAudioMixInputPin);
    BREAK_IF_Failed(hr)

    CComPtr<IPin> pAudioMixOutputPin;
    hr = g_DSHelper.GetPin(m_pBgmAudioGrabber,PINDIR_OUTPUT,&pAudioMixOutputPin);
    g_DSHelper.SetAudioFilterBuffer(pAudioMixOutputPin);

    BREAK_IF_Failed(hr)
    
    hr = CoCreateInstance(CLSID_AsyncReader,(void**)&m_pBGMAudioSrcFilter);
    RETURN_IF_Failed(hr,hr)
    InfoLog(_T("Create BGM source filter CLSID_AsyncReader OK!"));

    hr = CoCreateInstance(CLSID_WavParser,(void**)&m_pWaveParserFilter);
    RETURN_IF_Failed(hr,hr)
    InfoLog(_T("Create CLSID_WavParser OK!"));
    hr = m_pGraph->AddFilter(m_pWaveParserFilter,L"Wav Parser");
    RETURN_IF_Failed(hr,hr)
    InfoLog(_T("AddFilter CLSID_WavParser OK!"));
    
    

    CComPtr<IFileSourceFilter> pSourceFilter;
    hr = m_pBGMAudioSrcFilter->QueryInterface(IID_IFileSourceFilter,(void**)&pSourceFilter);
    RETURN_IF_Failed(hr,hr)
    InfoLog(_T("QueryInterface IID_IFileSourceFilter OK!"));
    
    HRESULT hr = pSourceFilter->Load(m_strBkgMusicPath,NULL );
    
    RETURN_IF_Failed(hr,hr)
    InfoLog(_T("Load %s OK!"),m_strBkgMusicPath);

    hr = m_pGraph->AddFilter(m_pBGMAudioSrcFilter,L"Async Source");
    RETURN_IF_Failed(hr,hr)
    InfoLog(_T("AddFilter AsyncSource OK!"));

    CComPtr<IPin> pWavParseInputPin;
    hr = g_DSHelper.GetPin(m_pWaveParserFilter,&pWavParseInputPin);
    g_DSHelper.SetAudioFilterBuffer(pWavParseInputPin);

    RETURN_IF_Failed(hr,hr)
    
    CComPtr<IPin> pAudioBGMOutputPin;
    
    hr = g_DSHelper.GetPin(m_pBGMAudioSrcFilter,&pAudioBGMOutputPin);
    g_DSHelper.SetAudioFilterBuffer(pAudioBGMOutputPin);

    RETURN_IF_Failed(hr,hr)

    hr = m_pGraph->ConnectDirect(pAudioBGMOutputPin,pWavParseInputPin,NULL);
    RETURN_IF_Failed(hr,hr)
    InfoLog(_T("Connect of pBkgAudioPathOutputPin and pWavParseInputPin OK!"));

    CComPtr<IPin> pWavParSEOutputPin;
    hr = g_DSHelper.GetPin(m_pWaveParserFilter,&pWavParSEOutputPin);
    g_DSHelper.SetAudioFilterBuffer(pWavParSEOutputPin);

    RETURN_IF_Failed(hr,hr)

    hr = m_BgmAudioRenderDevice.Create(m_strAudioRenderdeviceid);
    RETURN_IF_Failed(hr,hr);
    
    hr = m_BgmAudioRenderDevice.SetAudioRenderFormat(g_RecordingConfig.AudioSamplePerSecond(),g_RecordingConfig.AudioBitsPerSample(),g_RecordingConfig.AudioChannels());
    RETURN_IF_Failed(hr,hr);
    
    hr = m_pGraph->AddFilter(m_BgmAudioRenderDevice.GetBaseFilter(),L"BGM Audio Render");
    RETURN_IF_Failed(hr,hr);

    CComPtr<IPin> pBgmRenderPin  = m_BgmAudioRenderDevice.GetInputPin();
    hr = m_pGraph->ConnectDirect(pWavParSEOutputPin,pAudioMixInputPin,hr)
    g_DSHelper.SetAudioFilterBuffer(pBgmRenderPin);
    

    hr = m_pGraph->ConnectDirect(pAudioMixOutputPin,pBgmRenderPin,hr)

    if (m_pMC)
    {
        hr = m_pMC->StopWhenReady();
        BREAK_IF_Failed(hr)
    }

'''

解决方法

...总是每秒收到四次 44100 字节的数据,我想将回调率更改为每秒 10 次...

你不能拥有这个。当您将其设置为以适合您需要的合适格式流式传输数据时,您的任务就是打破它适合您处理的流。

当您从文件播放时,源过滤器以最大速率推送数据,并以对读取器、解复用器、解码器有意义的块的形式推送数据。您几乎永远不会(如果有的话)在此过程中具有灵活性,并且与实时音频捕获相反,您无法请求特定的数据粒度。

只需以这种速率消耗数据并将其拆分为您自己内部处理所需的部分,这是一项相对容易的任务。