UPDATE成功!!下
一部部分成功の編集を参照してください、多分十分なあなたの質問に答えるために。お読みください。
私のシステムでは、例外をデバッグすると、TransferVideoFrame()
を呼び出すときにOnTimer()
関数が失敗したことが示されました。エラーはInvalidArgumentException
でした。
グーグルの話が私の最初の発見につながりました。明らかにa bug in NVIDIA driversがあります。つまり、ビデオの再生は11と10の機能レベルで失敗するようです。
次のようにだから私の最初の変更が機能CreateDX11Device()
にあった:今
static const D3D_FEATURE_LEVEL levels[] = {
/*
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
*/
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1
};
TransferVideoFrame()
はまだ失敗し、代わりに無効な引数の(HRESULTとして)E_FAIL
を与えます。テクスチャを事前に作成するCreateTexture2D()
を使用せずにTransferVideoFrame()
の使用を示す例とした
-
もっとグーグルは私second discoveryにつながりました。私はあなたにすでにOnTimer()
にいくつかのコードがありましたが、使用されていなかったので、同じリンクを見つけたと思います。
とにかく、私は今、ビデオフレーム取得するには、このコードを使用する:これを実行した後
ComPtr <ID3D11Texture2D> spTextureDst;
m_spDX11SwapChain->GetBuffer (0, IID_PPV_ARGS (&spTextureDst));
m_spMediaEngine->TransferVideoFrame (spTextureDst.Get(), nullptr, &m_rcTarget, &m_bkgColor);
を、私はTransferVideoFrame()
が成功したことを確認(良い!)が、コピーしたテクスチャにMap()
を呼び出す - m_spCopyTexture
- そのために失敗しましたテクスチャはCPUの読み取りアクセスで作成されませんでした。
私はちょうどコピーの対象としてm_spRenderTexture
を読み書きしましたが、そのフラグには正しいフラグがあり、以前の変更のためにもう使用しませんでした。
//copy the render target texture to the readable texture.
m_spDX11DeviceContext->CopySubresourceRegion(m_spRenderTexture.Get(),0,0,0,0,spTextureDst.Get(),0,NULL);
m_spDX11DeviceContext->Flush();
//Map the readable texture;
D3D11_MAPPED_SUBRESOURCE mapped = {0};
HRESULT hr = m_spDX11DeviceContext->Map(m_spRenderTexture.Get(),0,D3D11_MAP_READ,0,&mapped);
void* buffer = ::CoTaskMemAlloc(176 * 144 * 3);
memcpy(buffer, mapped.pData,176 * 144 * 3);
//unmap so we can copy during next update.
m_spDX11DeviceContext->Unmap(m_spRenderTexture.Get(),0);
私のシステムでは、OnTimer()
関数は失敗しません。ビデオフレームはテクスチャにレンダリングされ、ピクセルデータは正常にメモリバッファにコピーアウトされます。
さらに問題があるかどうかを調べる前に、私がこれまでに行っていたのと同じ進歩を遂げることができるかどうかを見ておくとよいでしょう。この回答に詳細な情報を追加すると、できるだけヘルプを追加して回答を追加します。
EDIT FramePlayer::CreateBackBuffers()
//make first texture cpu readable
D3D11_TEXTURE2D_DESC texDesc = {0};
texDesc.Width = 176;
texDesc.Height = 144;
texDesc.MipLevels = 1;
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 | D3D11_CPU_ACCESS_WRITE;
texDesc.MiscFlags = 0;
MEDIA::ThrowIfFailed(m_spDX11Device->CreateTexture2D(&texDesc,NULL,&m_spRenderTexture));
におけるテクスチャの説明を行わ
変更(私はあなたが認識していると確信している)いつかアップクリアする必要がありますメモリリークがあることにも注意してください - 次の行に割り当てられたメモリは解放されません。
void* buffer = ::CoTaskMemAlloc(176 * 144 * 3); // sizes changed for my test
SUCCESS
私は現在、個々のフレームを保存することに成功しましたが、今はコピーテクスチャを使用していません。
まず、the DirectXTex Libraryの最新バージョンをダウンロードしました。これはDX11テクスチャヘルパー機能を提供します。たとえば、テクスチャから画像を抽出してファイルに保存するなどです。既存のプロジェクトとしてソリューションにDirectXTexライブラリを追加するためのThe instructionsは、Windows 8 Storeアプリケーションに必要な変更を注意深く熟読する必要があります。
一旦、上記ライブラリーは、含まれる参照され組み込まれて、最後に、FramePlayer::OnTimer()
でコードの中央部分は、次のようにする必要があるFramePlayer.cpp
#include "..\DirectXTex\DirectXTex.h" // nb - use the relative path you copied to
#include <wincodec.h>
に次#include
年代に追加されます。毎回同じファイル名に保存するだけですので、これを修正する必要があります。私はそれ以上にこれを取るために、今の時間を持っていないが、私は私がこれまで:-)達成したものに非常に満足している名前
// new frame available at the media engine so get it
ComPtr<ID3D11Texture2D> spTextureDst;
MEDIA::ThrowIfFailed(m_spDX11SwapChain->GetBuffer(0, IID_PPV_ARGS(&spTextureDst)));
auto rcNormalized = MFVideoNormalizedRect();
rcNormalized.left = 0;
rcNormalized.right = 1;
rcNormalized.top = 0;
rcNormalized.bottom = 1;
MEDIA::ThrowIfFailed(m_spMediaEngine->TransferVideoFrame(spTextureDst.Get(), &rcNormalized, &m_rcTarget, &m_bkgColor));
// capture an image from the DX11 texture
DirectX::ScratchImage pImage;
HRESULT hr = DirectX::CaptureTexture(m_spDX11Device.Get(), m_spDX11DeviceContext.Get(), spTextureDst.Get(), pImage);
if (SUCCEEDED(hr))
{
// get the image object from the wrapper
const DirectX::Image *pRealImage = pImage.GetImage(0, 0, 0);
// set some place to save the image frame
StorageFolder ^dataFolder = ApplicationData::Current->LocalFolder;
Platform::String ^szPath = dataFolder->Path + "\\frame.png";
// save the image to file
hr = DirectX::SaveToWICFile(*pRealImage, DirectX::WIC_FLAGS_NONE, GUID_ContainerFormatPng, szPath->Data());
}
// and the present it to the screen
MEDIA::ThrowIfFailed(m_spDX11SwapChain->Present(1, 0));
にフレーム番号)
あなたが取ることができます新鮮な外観とあなたの結果をコメントで更新しますか?
私はWP 8.1用のアプリケーションを開発しているので、私とコードを共有できますか?C++プログラミングには不明ですか?それはあなたから大きな助けになるでしょう。 – Xyroid
こんにちは、私はwinrtアプリで作業しており、私はまたビデオからフレームを抽出する必要があります。私はあなたのコードを使用しましたが、最初の2フレームしか抽出しません。変更が必要なものはありますか?私はあなたがこの質問の編集aprtで述べたようにコードを更新しました。 –
作業コードを共有できますか? –