microsoft / media-foundation

Repository for Windows Media Foundation related tools and samples
MIT License
144 stars 31 forks source link

TransferVideoFrame in MediaEngineDCompWin32Sample always returns black #45

Closed DougRogers closed 1 year ago

DougRogers commented 1 year ago

I added TransferVideoFrame to MediaEngineDCompWin32Sample to get a screen capture, but I am not able to capture the current video image.

Here is the code I added

In the class

   ID3D11Texture2D *TransferVideoFrame(ID3D11Device *&pDevice, ID3D11DeviceContext *&pContext);
    winrt::com_ptr<ID3D11Device> _d3d11Device;
      winrt::com_ptr<ID3D11DeviceContext> _context;

Getting the context when creating the device


    ID3D11DeviceContext *context;

        THROW_IF_FAILED(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, creationFlags, featureLevels, ARRAYSIZE(featureLevels),
                                          D3D11_SDK_VERSION, d3d11Device.put(), nullptr, &context));

        _context.copy_from(context);

TransferVideoFrame function

    ID3D11Texture2D *MediaEngineWrapper::TransferVideoFrame(ID3D11Device *&pDevice, ID3D11DeviceContext *&pContext)
    {

        ID3D11Texture2D *returnTexture;

        RunSyncInMTA(
            [&]()
            {
                HRESULT hr;
                auto lock = m_lock.lock();

                DWORD width, height;
                m_mediaEngine->GetNativeVideoSize(&width, &height);

                pDevice  = _d3d11Device.get();
                pContext = _context.get();

                HANDLE swapChainHandle;
                hr = m_mediaEngineEx->GetVideoSwapchainHandle(&swapChainHandle);

                D3D11_TEXTURE2D_DESC desc;
                RtlZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
                desc.Width     = width;
                desc.Height    = height;
                desc.MipLevels = 1;
                desc.ArraySize = 1;
                desc.Format           = DXGI_FORMAT_B8G8R8A8_UNORM;

                desc.SampleDesc.Count = 1;
                desc.Usage            = D3D11_USAGE_DEFAULT;
                desc.BindFlags        = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
                desc.CPUAccessFlags   = 0;
                desc.MiscFlags        = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;

                winrt::com_ptr<ID3D11Texture2D> pTexture;
                hr = _d3d11Device->CreateTexture2D(&desc, nullptr, pTexture.put());

                auto rcNormalized = MFVideoNormalizedRect();

                RECT rect;
                rect.top    = 0;
                rect.left   = 0;
                rect.bottom = height;
                rect.right  = width;

                LONGLONG pts;
                if (m_mediaEngine->OnVideoStreamTick(&pts) == S_OK)
                {
                    hr = m_mediaEngine->TransferVideoFrame(pTexture.get(), &rcNormalized, &rect, nullptr);

                    if (hr == S_OK)
                    {
                        pTexture.copy_to(&returnTexture);
                    }
                }
            });

        return returnTexture;
    }

The texture is always black, I have tried different formats, but nothing works. hr is S_OK is all calls.

DougRogers commented 1 year ago

MiscFlags was not set properly. Works correctly now.