オブジェクトをフィルターグラフに接続する方法は?

Nov 22 2020

私がする必要があるのは-それを行うためにvector<frames>からデコードされたサンプルフレーム(のような)を取得DirectShowすることです私はこの実装に従いますhttps://docs.microsoft.com/en-us/windows/win32/directshow/using-the-sample-grabber

私の実装があります

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;
}

ここでエラーが発生します:

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、このエラーテーブルによるとhttps://docs.microsoft.com/en-us/windows/win32/directshow/error-and-success-codes という意味です

フィルタグラフにないオブジェクトに対して、要求された機能を実行できません。

ドキュメントに例があるようです https://docs.microsoft.com/en-us/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;            <---------- 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;
    }

EDIT2

m_pMemReaderグラフに含めるために、この線を追加しました

hr = m_pGraph->AddFilter(m_pMemReader, NULL);

次にMEDIATYPE_Audio、エラーが発生したときにメディアタイプを設定します0x80040200- The specified media type is invalid.MEDIATYPE_Streamフォローエラーが発生したときにメディアタイプを使用しようとすると0x80040266-

ピンは同じトランスポートをサポートしていないため、接続できません。たとえば、アップストリームフィルタにはIAsyncReaderインターフェイスが必要であり、ダウンストリームフィルタにはIMemInputPinが必要な場合があります。

ここでの問題は何ですか?私がここから理解しているのは-私の上流のフィルターはですがCMemReader * m_pMemReader;、内部ではCMemReaderそれが継承しているIBaseFilterので、私の下流のフィルターIBaseFilter * m_pGrabberF;IBaseFilterです。ここで何が欠けていますか?

回答

1 user123 Nov 22 2020 at 19:07

DirectShowは古くなっています。代わりにMediaFoundationを使用する必要があります。私はそれをテストしませんでしたが、次のコードはオーディオをデコードし、生のオーディオフレームを操作できると思います(https://docs.microsoft.com/en-us/windows/win32/medfound/tutorial--decoding-audio):

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
}
1 RomanR. Nov 22 2020 at 20:18

コードにはいくつかの問題があり、全体的にコードスニペットは一貫性がなく、ビルドできないとさえ言われていません。おそらく、小さなプロジェクトを作成し、GitHubにアップロードして参照として使用する必要があります。

解決すべき問題は次のとおりです。

  1. m_pMemReaderフィルタグラフに属する適切なピンがある理由は明らかではありません。
  2. サンプルグラバーは、MEDIATYPE_Streamオーディオをデコードするという意図と矛盾するメディアタイプで初期化されます(代わりにMEDIATYPE_Audio、が必要になりMEDIASUBTYPE_PCMます)
  3. 一般に、Renderメソッドを使用することはまったくお勧めできません。DirectShow Intelligent Connectの使用に関連する問題について読むために、このリファレンスを残しておきます

ほとんど目隠しをして機能させようとしているように見えるので、GraphStudioNext(SDK GraphEditツールのアナログ)を使用してパイプラインをインタラクティブに構築し、構築する必要のあるフィルターグラフの種類を把握することをお勧めします。そうすれば、コードから同様のギャップを構築することについてより良いアイデアを得ることができます。