locked
IMFMediaEngine::TransferVideoFrame and IWICBitmap

    Question

  • Im trying to get data to a IWICBitmap object from a playing video using IMFMediaEngine::TransferVideoFrame using the following code:

    HRESULT hr = _me()->TransferVideoFrame(mIWICBitmap,&src,&dst,&backColor);
    

    Where mIWICBitmap is a IWICBitmap object.

    This returns an HRESULT that maps to "No such interface supported"

    Does anyone know how to get data from TransferVideoFrame into a IWICBitmap?

    Friday, November 16, 2012 6:49 AM

Answers

  • Hi,

    I can make sure that this API can be used in Windows Store App.

    How about the D3D surface?

     ComPtr<ID3D11Texture2D> spTextureDst;

                    m_spMediaEngine->TransferVideoFrame(spTextureDst.Get(), nullptr, &m_rcTarget, &m_bkgColor)
                    );

    Best regards,
    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us

    • Marked as answer by monarchorbis Tuesday, November 20, 2012 6:48 PM
    Monday, November 19, 2012 3:02 AM
  • I ended up making two textures. One that was bound to the rendering pipeline and one with cpu_read permissions (because you can't do both in one texture) and copying between the two to read the pixels:

    //make first texture cpu readable
    memset( &texDesc, 0,sizeof(texDesc) );
    texDesc.Width = size.x;
    texDesc.Height = size.y;
    texDesc.MipLevels = 0;
    texDesc.ArraySize = 1;
    texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    texDesc.SampleDesc.Count = 1;
    texDesc.SampleDesc.Quality =  0;
    texDesc.Usage = D3D11_USAGE_STAGING;
    texDesc.BindFlags = 0;
    texDesc.CPUAccessFlags =  D3D11_CPU_ACCESS_READ;
    texDesc.MiscFlags = 0;
    					
    HRESULT hr = mDX11Device->CreateTexture2D(&texDesc,NULL,&_tex);
    ThrowIfFailed(hr);
    
    //Make Second Texture as a render target.
    texDesc.Usage = D3D11_USAGE_DEFAULT;
    texDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
    texDesc.CPUAccessFlags = 0;
    
    hr = mDX11Device->CreateTexture2D(&texDesc,NULL,&_tex2);
    ThrowIfFailed(hr);


    //Copy the videoFrame to the render target texture.
    HRESULT hr = _me()->TransferVideoFrame((mD3D11Texture.Get()),&src,&dst,&backColor);
    ThrowIfFailed(hr);

    //copy the render target texture to the readable texture. mDX11DeviceContext->CopySubresourceRegion1(mD3D11TextureRead.Get(),0,0,0,0,mD3D11Texture.Get(),0,NULL,0); mDX11DeviceContext->Flush(); //Map the readable texture; mDX11DeviceContext->Map(mD3D11TextureRead.Get(),0,D3D11_MAP_READ,0,&mMapped); memcpy(pDst_data,mMapped.pData,datalen); //unmap so we can copy during next update. mDX11DeviceContext->Unmap(mD3D11TextureRead.Get(),0);

    I would love to know if there is a better way to do this and thanks for pointing me in the right direction.

    -Aubrey



    • Edited by monarchorbis Tuesday, November 20, 2012 3:35 PM
    • Marked as answer by monarchorbis Tuesday, November 20, 2012 7:26 PM
    Tuesday, November 20, 2012 3:32 PM

All replies

  • Hi,

    I can make sure that this API can be used in Windows Store App.

    How about the D3D surface?

     ComPtr<ID3D11Texture2D> spTextureDst;

                    m_spMediaEngine->TransferVideoFrame(spTextureDst.Get(), nullptr, &m_rcTarget, &m_bkgColor)
                    );

    Best regards,
    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us

    • Marked as answer by monarchorbis Tuesday, November 20, 2012 6:48 PM
    Monday, November 19, 2012 3:02 AM
  • Thanks for the reply. I've tried what you suggested. But I can't see how to get the bytes from the surface, which is why I chose a WIC Bitmap in the first place. Any ideas would be welcome. 

    Thanks,

    Aubrey

    Tuesday, November 20, 2012 8:03 AM
  • I ended up making two textures. One that was bound to the rendering pipeline and one with cpu_read permissions (because you can't do both in one texture) and copying between the two to read the pixels:

    //make first texture cpu readable
    memset( &texDesc, 0,sizeof(texDesc) );
    texDesc.Width = size.x;
    texDesc.Height = size.y;
    texDesc.MipLevels = 0;
    texDesc.ArraySize = 1;
    texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    texDesc.SampleDesc.Count = 1;
    texDesc.SampleDesc.Quality =  0;
    texDesc.Usage = D3D11_USAGE_STAGING;
    texDesc.BindFlags = 0;
    texDesc.CPUAccessFlags =  D3D11_CPU_ACCESS_READ;
    texDesc.MiscFlags = 0;
    					
    HRESULT hr = mDX11Device->CreateTexture2D(&texDesc,NULL,&_tex);
    ThrowIfFailed(hr);
    
    //Make Second Texture as a render target.
    texDesc.Usage = D3D11_USAGE_DEFAULT;
    texDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
    texDesc.CPUAccessFlags = 0;
    
    hr = mDX11Device->CreateTexture2D(&texDesc,NULL,&_tex2);
    ThrowIfFailed(hr);


    //Copy the videoFrame to the render target texture.
    HRESULT hr = _me()->TransferVideoFrame((mD3D11Texture.Get()),&src,&dst,&backColor);
    ThrowIfFailed(hr);

    //copy the render target texture to the readable texture. mDX11DeviceContext->CopySubresourceRegion1(mD3D11TextureRead.Get(),0,0,0,0,mD3D11Texture.Get(),0,NULL,0); mDX11DeviceContext->Flush(); //Map the readable texture; mDX11DeviceContext->Map(mD3D11TextureRead.Get(),0,D3D11_MAP_READ,0,&mMapped); memcpy(pDst_data,mMapped.pData,datalen); //unmap so we can copy during next update. mDX11DeviceContext->Unmap(mD3D11TextureRead.Get(),0);

    I would love to know if there is a better way to do this and thanks for pointing me in the right direction.

    -Aubrey



    • Edited by monarchorbis Tuesday, November 20, 2012 3:35 PM
    • Marked as answer by monarchorbis Tuesday, November 20, 2012 7:26 PM
    Tuesday, November 20, 2012 3:32 PM
  • Hi - trying to follow your example, I am getting an error when calling TransferVideoFrame.

    Do you happen to have a working example I could try out?


    Blog: http://socialebola.wordpress.com

    Tuesday, March 19, 2013 8:53 AM