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
    }