Directshow CLSID_AsyncReader:how to set the Output Pin sample size?

134 views Asked by At

I'm trying to play a wav file(44100sr 16bits 2 channels) from the disk , and I need to process the audio data in the SampleGrabber filter callback ,but it always received 44100 bytes data four times per seconds, I want to change the callback rate to 10 times per seconds(audio sample size:17640 bytes per callback),not four times(44100 bytes per time), How can I make it works as expected?

hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&m_pBgmAudioGrabber);
BREAK_IF_FAILED(hr);
        
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, 0, &pAudioMixInputPin);
g_DSHelper.SetAudioFilterBuffer(pAudioMixInputPin);
BREAK_IF_FAILED(hr);

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

BREAK_IF_FAILED(hr);
        
hr = CoCreateInstance(CLSID_AsyncReader, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&m_pBGMAudioSrcFilter);
RETURN_IF_FAILED(hr, hr);
InfoLog(_T("Create BGM source filter CLSID_AsyncReader OK!"));

hr = CoCreateInstance(CLSID_WavParser, NULL, CLSCTX_INPROC, IID_IBaseFilter, (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, PINDIR_INPUT, 0, &pWavParseInputPin);
g_DSHelper.SetAudioFilterBuffer(pWavParseInputPin);

RETURN_IF_FAILED(hr, hr)
        
CComPtr<IPin> pAudioBGMOutputPin;
        
hr = g_DSHelper.GetPin(m_pBGMAudioSrcFilter, PINDIR_OUTPUT, 0, &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, PINDIR_OUTPUT, 0, &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,NULL);
RETURN_IF_FAILED(hr, hr)
g_DSHelper.SetAudioFilterBuffer(pBgmRenderPin);
        

hr = m_pGraph->ConnectDirect(pAudioMixOutputPin, pBgmRenderPin,NULL);
RETURN_IF_FAILED(hr, hr)

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

There are 1 answers

2
Roman Ryltsov On

... always received 44100 bytes data four times per seconds, I want to change the callback rate to 10 times per second...

You can't have this. When you set it to stream data in suitable format that fit your needs, it is your task from there to break the stream it pieces suitable for your processing.

When you are playing from file, the source filter is pushing the data at maximal rate and in chunks that make sense for reader, demultiplexer, decoder. You almost never, if ever at all, have flexibility over this process and - as opposed to live audio capture - you cannot request certain data granularity.

Just consume the data at this rate and split it into pieces necessary for your internal preocessing yourself, it is a relatively easy task.