Answered by:
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,
JesseJesse 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,
JesseJesse 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