Hardware-accelerated decoding with D3D11 and IMFTransform RRS feed

  • Question

  • Hi, I've been trying to get hardware-accelerated video decoding working with D3D11 and IMFTransform using this article:

    I have two questions - first, I'm unable to create a Texture2D with the D3D11_BIND_DECODER flag, which is necessary to create the output view. Do you know why this might be the case?

    Second, I don't understand where the actual decoding is taking place. I understand I can call SubmitDecoderBuffer, but I was under the impression that this would simply call IMFTransform::ProcessOutput. I need to implement the ProcessOutput function though, and don't know how the actual decoding will work. Please let me know!

    I'd be happy to provide some code.

    Thank you!
    Tuesday, May 28, 2019 6:13 AM

All replies

  • The article mostly explains what decoder MFT does inside and you normally have an out of the box decoder MFT. To  get hardware-accelerated video decoding you can just use standard OS functionality via IMFTransform interface.

    • you don't create textures, decoder MFT does this (see "MFT_OUTPUT_STREAM_PROVIDES_SAMPLES flag" in the linked article)
    • decoding takes place between `IMFTransform::ProcessInput` and `IMFTransform::ProcessOutput` calls; it's MFT's resposibility to split decoding work internally as needed
    • you don't need to do `SubmitDecoderBuffer` as decoder does this internally
    • you don't implement `ProcessOutput` on your own, you use existing decoder MFT's method

    Tuesday, May 28, 2019 9:48 AM
  • Thank you! I got it working with the H.264 decoder MFT. My issue now is that when I decode a frame, I'm unable to copy the resulting texture (D3D11_USAGE_DEFAULT) to my staging texture. Here's the code to get from the IMFSample (from the MFT_OUTPUT_DATA_BUFFER) to the ID3D11Texture2D:

    DWORD bufLength;
    IMFMediaBuffer *mfOutputBuffer = NULL;
    IMFSample* mfOutputSample = outputBuffer.pSample;

    IMFDXGIBuffer* pDXGIBuffer = NULL;
    ID3D11Texture2D* pSurface = NULL;

    mfOutputSample->GetBufferByIndex(0, &mfOutputBuffer);
    CHECK_HR(mfOutputBuffer->GetCurrentLength(&bufLength), "Get buffer length failed.\n");

    // Now we get Texture2D
    hr = mfOutputBuffer->QueryInterface(__uuidof(IMFDXGIBuffer), (void**)&pDXGIBuffer);
    CHECK_HR(hr, "Failed to get IMFDXGIBuffer from IMFMediaBuffer");

    //hr = pDXGIBuffer->GetResource(__uuidof(ID3D11Texture2D), (void**)&pSurface);

    hr = pDXGIBuffer->GetResource(IID_PPV_ARGS(&pSurface));
    CHECK_HR(hr, "Failed to GetResource, IMFDXGIBuffer to ID3D11Texture2D");

    std::cout << "Got ID3D11Texture2D from IMFSample" << std::endl;

    // Save to file
    SaveToFile(pDevice, pContext, pSurface);

    In the function SaveToFile, I have the following:

    D3D11_TEXTURE2D_DESC desc_orig;

    ID3D11Texture2D *pStagingSurface;

    desc_orig.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
    desc_orig.Usage = D3D11_USAGE_STAGING;
    HRESULT hr = pDevice->CreateTexture2D(&desc_orig, NULL, &pStagingSurface);

    pContext->CopyResource(pStagingSurface, pSurface); // This fails and exits with error code 2173

    Do you have any idea why the CopyResource function might be exiting with error code 2173 even though I created the staging texture with exactly the same attributes as the original one obtained from the IMFSample?


    Friday, May 31, 2019 10:26 AM
  • Changing CPUAccessFlags and Usage is insufficient. You normally enable D3D debug layer in order to capture additional diagnostic messages. They will guide you through reporting things you need to fix in code (you will have debug output generated around your copy attempt).

    Friday, May 31, 2019 2:19 PM