C++ 如何将对象连接到过滤器图形?
我需要做的是从C++ 如何将对象连接到过滤器图形?,c++,audio,directshow,C++,Audio,Directshow,我需要做的是从DirectShow获取解码的样本帧(如vector),为了做到这一点,我遵循以下实现 这是我的实现 bool coAudioPlayerSampleGrabber::LoadImp(SoundDataType dataType, unsigned char const * pData, int64_t dataLen) { Cleanup(); m_bReady = false; HRESULT hr = S_OK; assert
DirectShow
获取解码的样本帧(如vector
),为了做到这一点,我遵循以下实现
这是我的实现
bool coAudioPlayerSampleGrabber::LoadImp(SoundDataType dataType,
unsigned char const * pData,
int64_t dataLen)
{
Cleanup();
m_bReady = false;
HRESULT hr = S_OK;
assert(pData);
assert(dataLen);
m_memBuffer.resize(dataLen);
memcpy(m_memBuffer.data(), pData, dataLen);
m_memBufferDataType = dataType;
m_pMediaType = new CMediaType();
m_pMediaType->majortype = MEDIATYPE_Stream;
switch (dataType)
{
case SoundDataType::WAV: m_pMediaType->subtype = MEDIASUBTYPE_WAVE; break;
case SoundDataType::MP3: m_pMediaType->subtype = MEDIASUBTYPE_MPEG1Audio; break;
default: return false;
}
m_pMemStream = new CMemStream((BYTE*)m_memBuffer.data(), m_memBuffer.size());
m_pMemReader = new CMemReader(m_pMemStream, m_pMediaType, &hr);
if (FAILED(hr) || m_pMemReader == NULL)
{
printf("Could not create filter - HRESULT 0x%8.8X\n", hr);
return false;
}
// Make sure we don't accidentally go away!
m_pMemReader->AddRef();
// *** Create the Filter Graph Manager
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pGraph));
if (FAILED(hr))
{
if (hr == CO_E_NOTINITIALIZED)
{
printf("coAudioPlayerSampleGrabberImplementation::Load: FAILED CoCreateInstance(CLSID_FilterGraph,...) FAILED hRes: %x (CoInitialize has not been called)\n", hr);
}
else
{
printf("coAudioPlayerSampleGrabberImplementation::Load: FAILED CoCreateInstance(CLSID_FilterGraph FAILED hRes: %x\n", hr);
}
return false;
}
hr = m_pGraph->QueryInterface(IID_PPV_ARGS(&m_pControl));
if (FAILED(hr))
{
std::cout << "coAudioPlayerSampleGrabberImplementation::Load: FAILED QueryInterface IMediaControl" << std::endl;
return false;
}
hr = m_pGraph->QueryInterface(IID_PPV_ARGS(&m_pEvent));
if (FAILED(hr))
{
std::cout << "coAudioPlayerSampleGrabberImplementation::Load: FAILED QueryInterface IMediaEventEx" << std::endl;
return false;
}
// *** end Create the Filter Graph Manager
// *** Add the Sample Grabber to the Filter Graph
// Create the Sample Grabber filter.
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&m_pGrabberF));
if (FAILED(hr))
{
std::cout << "coAudioPlayerSampleGrabberImplementation::Load: FAILED CoCreateInstance CLSID_SampleGrabber" << std::endl;
return false;
}
hr = m_pGraph->AddFilter(m_pGrabberF, LPCWSTR("Sample Grabber"));
if (FAILED(hr))
{
std::cout << "coAudioPlayerSampleGrabberImplementation::Load: FAILED AddFilter m_pGrabberF" << std::endl;
return false;
}
hr = m_pGrabberF->QueryInterface(IID_PPV_ARGS(&m_pGrabber));
if (FAILED(hr))
{
std::cout << "coAudioPlayerSampleGrabberImplementation::Load: FAILED QueryInterface ISampleGrabber" << std::endl;
return false;
}
// *** end Add the Sample Grabber to the Filter Graph
// *** Set the Media Type
hr = m_pGrabber->SetMediaType(m_pMediaType);
if (FAILED(hr))
{
std::cout << "coAudioPlayerSampleGrabberImplementation::Load: FAILED SetMediaType" << std::endl;
return false;
}
// *** end Set the Media Type
IPin *ppinOut = m_pMemReader->GetPin(0);
hr = m_pGraph->Render(ppinOut);
if (FAILED(hr))
{
printf("coAudioPlayerSampleGrabberImplementation::Load: FAILED to load (Render) audio file from data (hRes: %x)\n", hr);
return false;
}
m_bReady = true;
return m_bReady;
}
EDIT2
为了在图中加入m_pMemReader
,我添加了这一行
hr = m_pGraph->AddFilter(m_pMemReader, NULL);
然后,在我将媒体类型设置为MEDIATYPE\u Audio
时,我收到一个错误0x80040200
-指定的媒体类型无效。
,如果我尝试将媒体类型设置为MEDIATYPE\u Stream
时,我会收到以下错误0x80040266
-
引脚无法连接,因为它们不支持相同的传输。
例如,上游过滤器可能需要IAsyncReader接口,而下游过滤器需要IMemInputPin
这里有什么问题?我从这里理解的是-我的上游过滤器是
CMemReader*m_pMemReader代码>,但它继承自IBaseFilter
的引擎盖下的CMemReader
,则我的下游是IBaseFilter*m_pGrabberF
也是IBaseFilter
。我在这里遗漏了什么?DirectShow已经过时了。您应该改用MediaFoundation。我没有测试它,但我认为下面的代码将解码音频并允许您操作原始音频帧():
DirectShow已经过时了。您应该改用MediaFoundation。我没有测试它,但我认为下面的代码将解码音频并允许您操作原始音频帧():
代码中存在一些问题,总体上代码片段不一致,甚至没有说明无法构建它。您可能应该创建一个小项目并上传到GitHub作为参考
需要解决的问题有:
没有明显的原因说明为什么m_pMemReader
会有一个属于筛选图的合适pin
样本抓取器初始化为媒体类型MEDIATYPE\u流
,这与您解码音频的意图相矛盾(您需要MEDIATYPE\u音频
,mediatsubtype\u PCM
)
通常,使用渲染
方法根本不是一个好主意;我将留下来阅读与使用DirectShow Intelligent Connect相关的问题
由于您似乎主要是试图让它盲目地工作,因此最好使用(类似于SDK工具)并以交互方式构建管道,以了解需要构建什么样的过滤图。您将更好地了解如何从代码中构建类似的gaph。代码中存在一些问题,总体而言,代码片段是不一致的,甚至没有告诉您无法构建它。您可能应该创建一个小项目并上传到GitHub作为参考
需要解决的问题有:
没有明显的原因说明为什么m_pMemReader
会有一个属于筛选图的合适pin
样本抓取器初始化为媒体类型MEDIATYPE\u流
,这与您解码音频的意图相矛盾(您需要MEDIATYPE\u音频
,mediatsubtype\u PCM
)
通常,使用渲染
方法根本不是一个好主意;我将留下来阅读与使用DirectShow Intelligent Connect相关的问题
由于您似乎主要是试图让它盲目地工作,因此最好使用(类似于SDK工具)并以交互方式构建管道,以了解需要构建什么样的过滤图。您将更好地了解如何从代码中构建类似的gaph。我编辑了我的问题,我的编辑与案例2中关于类型的内容有关。但我真的不明白你对案例1和3的想法。关于我看到的第一个案例-我创建了CMemReader
给它一个源字节流,然后我得到IPin
并将其传递给Render
,所以我假设它应该开始呈现给定的源字节流,不是吗?关于案例3,我需要用什么来代替呢?也许你可以在你的答案中添加一个代码?首先,没有地方可以添加代码-你没有可构建的项目。其次,您得到的错误是VFW_E_NOT_IN_GRAPH
,这正是我在上面的1中所写的。您无法渲染
甚至不属于筛选图的内容。我编辑了我的问题EDIT2
,请您看一下。老实说,我不知道它与此问题和之前的问题有什么关系。你为什么要在这里使用CMemReader,“它与”你是指错误,对吗?我不知道,但这是我得到的。正如您在问题中看到的,我正在使用CMemReader
来读取字节流。我没有一个文件作为源,我只有一个字节指针和大小,因此为此我使用CMemReader
。否?我编辑了我的问题,我的编辑与案例2有关类型。但我真的不明白你对案例1和3的想法。关于我看到的第一个案例-我创建了CMemReader
给它一个源字节流,然后我得到IPin
并将其传递给Render
,所以我假设它应该开始呈现给定的源字节流,不是吗?关于案例3,我需要用什么来代替呢?也许你可以在你的答案中添加一个代码?首先,没有地方可以添加代码-你没有可构建的项目。其次,您得到的错误是VFW_E_NOT_IN_GRAPH
,这正是我在上面的1中所写的。您无法渲染
甚至不属于筛选图的内容。我编辑了我的问题EDIT2
,请您看一下。老实说,我不知道它与此问题和之前的问题有什么关系。你为什么要在这里使用CMemReader,“它与”你是指错误,对吗?我不知道,但这是我得到的。正如您在问题中看到的,我正在使用CMemReader
来读取字节流。我没有一个文件作为源,我只有一个字节指针和大小,因此为此我使用
m_pMediaType = new CMediaType();
m_pMediaType->majortype = MEDIATYPE_Audio; <---------- First line
switch (dataType)
{
//case SoundDataType::WAV: m_pMediaType->subtype = MEDIASUBTYPE_WAVE; break;
case SoundDataType::WAV: m_pMediaType->subtype = MEDIASUBTYPE_PCM; break; <-------- Second line
case SoundDataType::MP3: m_pMediaType->subtype = MEDIASUBTYPE_MPEG1Audio; break;
default: return false;
}
hr = m_pGraph->AddFilter(m_pMemReader, NULL);
IMFSourceReader *pReader = NULL;
hr = MFCreateSourceReaderFromURL(L"C:\\users\\video", NULL, &pReader);
if (FAILED(hr))
{
printf("Error opening input file");
}
IMFMediaType *type = NULL;
IMFMediaType *pPartialType = NULL;
hr = MFCreateMediaType(&pPartialType);
hr = pPartialType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
hr = pPartialType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
// Set this type on the source reader. The source reader will
// load the necessary decoder.
if (SUCCEEDED(hr))
{
hr = pReader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, NULL, pPartialType);
}
hr = pReader->GetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, &type);
//Do something with type which is a pointer to IMFMediaType
IMFSample *pSample = NULL;
IMFMediaBuffer *pBuffer = NULL;
BYTE *pAudioData = NULL;
DWORD cbBuffer = 0;
while(true){
DWORD dwFlags = 0;
hr = pReader->ReadSample((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, NULL, &dwFlags, NULL, &pSample);
hr = pSample->ConvertToContiguousBuffer(&pBuffer);
hr = pBuffer->Lock(&pAudioData, NULL, &cbBuffer);
//Do something with the pAudioData which is an array of unsigned chars of lenth cbBuffer
}