如何将对象连接到过滤图? [英] How to connect object to the filter graph?
问题描述
我需要做的-从 DirectShow
获取解码后的样本帧(例如 vector< frames>
),为了做到这一点,我遵循此实现 https://docs.microsoft.com/zh-cn/Windows/Win32/DirectShow/using-the-sample-grabber
有我的实现方式
bool coAudioPlayerSampleGrabber :: LoadImp(SoundDataType dataType,unsigned char const * pData,int64_t dataLen){清理();m_bReady = false;HRESULT hr = S_OK;assert(pData);断言(dataLen);m_memBuffer.resize(dataLen);memcpy(m_memBuffer.data(),pData,dataLen);m_memBufferDataType = dataType;m_pMediaType = new CMediaType();m_pMediaType-> majortype = MEDIATYPE_Stream;开关(数据类型){情况SoundDataType :: WAV:m_pMediaType-> subtype = MEDIASUBTYPE_WAVE;休息;情况SoundDataType :: MP3:m_pMediaType-> subtype = MEDIASUBTYPE_MPEG1Audio;休息;默认值:返回false;否则返回false.}m_pMemStream = new CMemStream((BYTE *)m_memBuffer.data(),m_memBuffer.size());m_pMemReader =新的CMemReader(m_pMemStream,m_pMediaType,& hr);如果(FAILED(hr)|| m_pMemReader == NULL){printf(无法创建过滤器-HRESULT 0x%8.8X \ n",hr);返回false;}//确保我们不会意外消失!m_pMemReader-> AddRef();//***创建过滤器图形管理器hr = CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_PPV_ARGS(& m_pGraph));如果(FAILED(hr)){如果(hr == CO_E_NOTINITIALIZED){printf("coAudioPlayerSampleGrabberImplementation :: Load:FAILED CoCreateInstance(CLSID_FilterGraph,...)FAILED hRes:%x(未调用CoInitialize)\ n",hr);}别的{printf("coAudioPlayerSampleGrabberImplementation :: Load:FAILED CoCreateInstance(CLSID_FilterGraph FAILED hRes:%x \ n,hr);}返回false;}hr = m_pGraph-> QueryInterface(IID_PPV_ARGS(& m_pControl));如果(FAILED(hr)){std :: cout<<"coAudioPlayerSampleGrabberImplementation :: Load:FAILED QueryInterface IMediaControl"<<std :: endl;返回false;}hr = m_pGraph-> QueryInterface(IID_PPV_ARGS(& m_pEvent));如果(FAILED(hr)){std :: cout<<"coAudioPlayerSampleGrabberImplementation :: Load:FAILED QueryInterface IMediaEventEx"<<std :: endl;返回false;}//***结束创建过滤器图形管理器//***将样本抓取器添加到过滤器图形//创建Sample Grabber过滤器.hr = CoCreateInstance(CLSID_SampleGrabber,NULL,CLSCTX_INPROC_SERVER,IID_PPV_ARGS(& m_pGrabberF));如果(FAILED(hr)){std :: cout<<"coAudioPlayerSampleGrabberImplementation :: Load:FAILED CoCreateInstance CLSID_SampleGrabber"<<std :: endl;返回false;}hr = m_pGraph-> AddFilter(m_pGrabberF,LPCWSTR("Sample Grabber")));如果(FAILED(hr)){std :: cout<<"coAudioPlayerSampleGrabberImplementation :: Load:FAILED AddFilter m_pGrabberF"<<std :: endl;返回false;}hr = m_pGrabberF-> QueryInterface(IID_PPV_ARGS(& m_pGrabber));如果(FAILED(hr)){std :: cout<<"coAudioPlayerSampleGrabberImplementation :: Load:FAILED QueryInterface ISampleGrabber"<<std :: endl;返回false;}//***结束将Sample Grabber添加到过滤器图//***设置媒体类型hr = m_pGrabber-> SetMediaType(m_pMediaType);如果(FAILED(hr)){std :: cout<<"coAudioPlayerSampleGrabberImplementation :: Load:FAILED SetMediaType"<<std :: endl;返回false;}//*** end设置媒体类型IPin * ppinOut = m_pMemReader-> GetPin(0);hr = m_pGraph-> Render(ppinOut);如果(FAILED(hr)){printf("coAudioPlayerSampleGrabberImplementation :: Load:FAILED无法从数据中加载(渲染)音频文件(hRes:%x)\ n",hr);返回false;}m_bReady = true;返回m_bReady;}
我在这里遇到错误:
IPin * ppinOut = m_pMemReader-> GetPin(0);hr = m_pGraph-> Render(ppinOut);如果(FAILED(hr))< -------------在这里!!{printf("TV_AudioPlayerSampleGrabberImplementation :: Load:FAILED无法从数据(hRes:%x)中加载(渲染)音频文件",hr);返回false;}
错误代码为- 0x8004025F
,根据此错误表 https://docs.microsoft.com/zh-cn/windows/win32/directshow/using-the-sample-grabber#build-the-filter-graph >
但是此示例在此方法中使用文件路径作为第一个参数. pGraph-> AddSourceFilter(pszVideoFile,L& quot; Source& quot;& pSourceF)
,我不没有文件路径,而是我有 m_pMemReader = new CMemReader(m_pMemStream,m_pMediaType和& hr)
.
问题是-如果我有 CMemReader
,如何将对象连接到过滤图?
编辑
更改了这些行
m_pMediaType = new CMediaType();m_pMediaType-> majortype = MEDIATYPE_Audio;< ----------第一行开关(数据类型){//案例SoundDataType :: WAV:m_pMediaType-> subtype = MEDIASUBTYPE_WAVE;休息;情况SoundDataType :: WAV:m_pMediaType-> subtype = MEDIASUBTYPE_PCM;休息;< --------第二行情况SoundDataType :: MP3:m_pMediaType-> subtype = MEDIASUBTYPE_MPEG1Audio;休息;默认值:返回false;否则返回false.}
EDIT2
为了在图形中包含 m_pMemReader
,我添加了这一行
hr = m_pGraph-> AddFilter(m_pMemReader,NULL);
然后在我将媒体类型设置为 MEDIATYPE_Audio
时出现错误 0x80040200
-指定的媒体类型无效.
,如果我尝试将媒体类型用作 MEDIATYPE_Stream
我得到关注错误 0x80040266
-
针无法连接,因为它们不支持相同的传输.例如,上游过滤器可能需要IAsyncReader接口,而下游过滤器则需要IMemInputPin.
这是什么问题?我从这里无法理解的是-我的上游过滤器是 CMemReader * m_pMemReader;
,但是 CMemReader
是它继承自 IBaseFilter
,然后是我的下游是 IBaseFilter * m_pGrabberF;
,它也是 IBaseFilter
.我在这里想念什么?
DirectShow已过时.您应该改用MediaFoundation.我没有对其进行测试,但是我认为以下代码将解码音频并让您处理原始音频帧( SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,NULL,pPartialType);}hr = pReader-> GetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,& type);//使用类型指向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);//使用pAudioData做某事,pAudioData是lenth cbBuffer的无符号字符数组} What I need to do is - get decoded sample frames (like There is my implementation I get an error here : Error code is - Cannot perform the requested function on an object that is not in the filter graph. I see there is an example in doc https://docs.microsoft.com/en-us/windows/win32/directshow/using-the-sample-grabber#build-the-filter-graph But this an example use path to file as a first param in this method Question is - How to connect object to the filter graph if I have EDIT changed these lines EDIT2 In order to include Then in I set media type as Pins cannot connect because they don't support the same transport.
For example, the upstream filter might require the IAsyncReader interface, while the downstream filter requires IMemInputPin. What is a problem here? What I undrstand from here is - my upstream filter is DirectShow is outdated. You should use MediaFoundation instead. I didn't test it but I think the following code will decode audio and let you manipulate raw audio frames (https://docs.microsoft.com/en-us/windows/win32/medfound/tutorial--decoding-audio):
这篇关于如何将对象连接到过滤图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!vector<frames>
) from DirectShow
in order to do it I follow this implementation https://docs.microsoft.com/en-us/windows/win32/directshow/using-the-sample-grabberbool 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;
}
IPin *ppinOut = m_pMemReader->GetPin(0);
hr = m_pGraph->Render(ppinOut);
if (FAILED(hr)) <------------- HERE!!
{
printf("TV_AudioPlayerSampleGrabberImplementation::Load: FAILED to load (Render) audio file from data (hRes: %x)\n", hr);
return false;
}
0x8004025F
, which according to this error table https://docs.microsoft.com/en-us/windows/win32/directshow/error-and-success-codes means that
pGraph->AddSourceFilter(pszVideoFile, L"Source", &pSourceF)
, I don't have path to file instead I have m_pMemReader = new CMemReader(m_pMemStream, m_pMediaType, &hr)
.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;
}
m_pMemReader
to graph I added this linehr = m_pGraph->AddFilter(m_pMemReader, NULL);
MEDIATYPE_Audio
I get an error 0x80040200
- The specified media type is invalid.
, if I try to use media type as MEDIATYPE_Stream
I get follow error 0x80040266
-
CMemReader * m_pMemReader;
, but CMemReader
under the hood it inherit from IBaseFilter
, then my downstream is IBaseFilter * m_pGrabberF;
which is also IBaseFilter
. What am I missing here?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
}