To exhibit the issue I made this sample code which decodes a frame, attempt to drain, flushes and then exit.
/* compile: g++ d3d12_mft.cpp -o d3d12_mft.exe -ld3d12 -ldxgi -lmfplat -lmfreadwrite */
#undef WINVER
#define WINVER 0x0A00
#define NTDDI_VERSION 0x0A00000B // NTDDI_WIN10_CO
#include <windows.h>
#include <d3dx12.h>
#include <assert.h>
#include <dxgi.h>
#include <dxgi1_5.h>
#include <initguid.h>
#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <mferror.h>
#include <mfd3d12.h>
#include <wrl.h>
#if !defined(NDEBUG)
# include <d3d12sdklayers.h>
#endif
using Microsoft::WRL::ComPtr;
static void init_direct3d(ComPtr<ID3D12Device> &d3device)
{
HRESULT hr;
UINT creationFlags = 0;
#ifndef NDEBUG
{
ComPtr<ID3D12Debug> debugController;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(debugController.GetAddressOf()))))
{
debugController->EnableDebugLayer();
creationFlags |= DXGI_CREATE_FACTORY_DEBUG;
}
}
#endif
ComPtr<IDXGIFactory2> factory;
hr = CreateDXGIFactory2(creationFlags, IID_PPV_ARGS(factory.GetAddressOf()));
ComPtr<IDXGIAdapter1> adapter;
for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != factory->EnumAdapters1(adapterIndex, adapter.GetAddressOf()); ++adapterIndex)
{
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
continue;
if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_12_0, IID_PPV_ARGS(d3device.GetAddressOf()))))
break;
}
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
ComPtr<ID3D12Device> d3device;
(void)hPrevInstance;
(void)hInstance;
(void)nCmdShow;
(void)lpCmdLine;
HRESULT hr;
CoInitializeEx(0, COINIT_MULTITHREADED);
init_direct3d(d3device);
#ifndef NDEBUG
ComPtr<ID3D12DebugDevice> debugDevice;
hr = d3device.As(&debugDevice);
#endif
MFStartup(MF_VERSION, MFSTARTUP_FULL);
UINT resetToken;
ComPtr<IMFDXGIDeviceManager> dxgiDeviceManager;
MFCreateDXGIDeviceManager(&resetToken, dxgiDeviceManager.GetAddressOf());
dxgiDeviceManager->ResetDevice(d3device.Get(), resetToken);
ComPtr<IMFSourceReader> sourceReader;
{
ComPtr<IMFAttributes> creationAttributes;
MFCreateAttributes(creationAttributes.GetAddressOf(), 1);
creationAttributes->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, dxgiDeviceManager.Get());
// creationAttributes->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE);
MFCreateSourceReaderFromURL(L"http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_30fps_normal.mp4",
creationAttributes.Get(), sourceReader.GetAddressOf());
}
{
ComPtr<IMFMediaType> pVideoMediaType;
hr = MFCreateMediaType(&pVideoMediaType);
hr = pVideoMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
hr = pVideoMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12);
// hr = pVideoMediaType->SetUINT32(MF_MT_D3D_RESOURCE_VERSION, MF_D3D12_RESOURCE);
// hr = pVideoMediaType->SetUINT32(MF_MT_D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS, TRUE);
hr = sourceReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, pVideoMediaType.Get());
assert(SUCCEEDED(hr));
}
ComPtr<IMFTransform> transform;
{
ComPtr<IMFSourceReaderEx> sourceReaderEx;
sourceReader.As(&sourceReaderEx);
GUID cat = MFT_CATEGORY_VIDEO_DECODER;
hr = sourceReaderEx->GetTransformForStream(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, &cat, transform.GetAddressOf());
hr = transform->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)dxgiDeviceManager.Get());
}
hr = sourceReader->SetStreamSelection(MF_SOURCE_READER_ALL_STREAMS, FALSE);
hr = sourceReader->SetStreamSelection(MF_SOURCE_READER_FIRST_VIDEO_STREAM, TRUE);
size_t decodedFrames = 0;
ComPtr<IMFD3D12SynchronizationObjectCommands> pMFSyncCmd;
ComPtr<IMFD3D12SynchronizationObject> pMFSyncObjs;
HANDLE sampleResourceReady = CreateEvent(NULL, TRUE, FALSE, NULL);
HANDLE sampleResourceFinalRelease = CreateEvent(NULL, TRUE, FALSE, NULL);
while (true)
{
DWORD readFlags = decodedFrames == 0 ? 0 : MF_SOURCE_READER_CONTROLF_DRAIN;
DWORD dwActualStreamIndex;
DWORD dwStreamFlags;
LONGLONG llTimestamp;
ComPtr<IMFSample> sample;
hr = sourceReader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, readFlags, &dwActualStreamIndex, &dwStreamFlags, &llTimestamp, sample.GetAddressOf());
assert(SUCCEEDED(hr));
if (decodedFrames++ == 0)
{
}
if (!sample.Get())
break; // finished draining
DWORD bufferCount;
sample->GetBufferCount(&bufferCount);
ComPtr<IMFMediaBuffer> output_media_buffer;
hr = sample->GetBufferByIndex(0, output_media_buffer.GetAddressOf());
ComPtr<IMFDXGIBuffer> spDXGIBuffer;
hr = output_media_buffer.As(&spDXGIBuffer);
if (SUCCEEDED(hr))
{
ComPtr<ID3D12Resource> texture;
hr = spDXGIBuffer->GetResource(IID_PPV_ARGS(&texture));
assert(SUCCEEDED(hr));
texture->SetName(L"MFT texture");
hr = spDXGIBuffer->GetUnknown(MF_D3D12_SYNCHRONIZATION_OBJECT, IID_PPV_ARGS(pMFSyncCmd.GetAddressOf()));
assert(SUCCEEDED(hr));
hr = spDXGIBuffer->GetUnknown(MF_D3D12_SYNCHRONIZATION_OBJECT, IID_PPV_ARGS(pMFSyncObjs.GetAddressOf()));
assert(SUCCEEDED(hr));
pMFSyncCmd->SignalEventOnResourceReady(sampleResourceReady);
}
}
hr = WaitForSingleObjectEx(sampleResourceReady, INFINITE, TRUE);
assert(hr == WAIT_OBJECT_0);
if (false)
{
ComPtr<IMFMediaSource> mediaSource;
const GUID GUID_NULL = {0x0000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
sourceReader->GetServiceForStream(MF_SOURCE_READER_MEDIASOURCE, GUID_NULL, IID_PPV_ARGS(&mediaSource));
if (mediaSource.Get())
mediaSource->Stop();
}
sourceReader->Flush(MF_SOURCE_READER_ALL_STREAMS);
// pMFSyncObjs->Reset();
pMFSyncObjs->SignalEventOnFinalResourceRelease(sampleResourceFinalRelease);
hr = WaitForSingleObjectEx(sampleResourceFinalRelease, INFINITE, TRUE);
assert(hr == WAIT_OBJECT_0);
// ERROR: A ID3D12Resource is referenced by GPU operations in-flight on Command Queue
// hr = transform->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, 0);
transform.Reset();
hr = dxgiDeviceManager->ResetDevice(nullptr, resetToken);
#ifndef NDEBUG
if (debugDevice.Get())
debugDevice->ReportLiveDeviceObjects((D3D12_RLDO_FLAGS)(D3D12_RLDO_IGNORE_INTERNAL | D3D12_RLDO_DETAIL));
#endif
MFShutdown();
CloseHandle(sampleResourceReady);
CloseHandle(sampleResourceFinalRelease);
d3device.Reset();
CoUninitialize();
return 0;
}
When you run this code, you can see a report of live objects before the program exits, with a lot of internal things to the Media Foundation decoder, ie things I did not create myself.
D3D12 WARNING: Live ID3D12Device at 0x000001FF74BB0208, Refcount: 76 [ STATE_CREATION WARNING #274: LIVE_DEVICE]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7C1B1120, Name: MFT texture, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA69AC0, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA6BF50, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA6E3E0, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA70870, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA72D00, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA755A0, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA77A30, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA79EC0, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA7C350, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA7E7E0, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA80C70, Refcount: 2, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA83100, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12CommandAllocator at 0x000001FF7BA83DC0, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #571: LIVE_COMMANDALLOCATOR]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA862E0, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12CommandAllocator at 0x000001FF7BA86FA0, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #571: LIVE_COMMANDALLOCATOR]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA874B0, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12CommandAllocator at 0x000001FF7BA8A180, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #571: LIVE_COMMANDALLOCATOR]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7BA8E6A0, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12CommandAllocator at 0x000001FF7BA8EB00, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #571: LIVE_COMMANDALLOCATOR]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7C1B5700, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12CommandAllocator at 0x000001FF7BA8ED80, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #571: LIVE_COMMANDALLOCATOR]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7C1B5270, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12CommandAllocator at 0x000001FF7C1B7C70, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #571: LIVE_COMMANDALLOCATOR]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7C1B4950, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12CommandAllocator at 0x000001FF7C1BA0B0, Refcount: 1, IntRef: 1 [ STATE_CREATION WARNING #571: LIVE_COMMANDALLOCATOR]
D3D12 WARNING: Live ID3D12Resource at 0x000001FF7C1B3710, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #575: LIVE_RESOURCE]
D3D12 WARNING: Live ID3D12CommandAllocator at 0x000001FF7C1BA5B0, Refcount: 1, IntRef: 1 [ STATE_CREATION WARNING #571: LIVE_COMMANDALLOCATOR]
D3D12 WARNING: Live ID3D12Fence at 0x000001FF7B82C890, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING: Live ID3D12CommandQueue at 0x000001FF7C1BD780, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #1054: LIVE_VIDEODECODECOMMANDQUEUE]
D3D12 WARNING: Live ID3D12VideoDecodeCommandList at 0x000001FF7C1EE7C0, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #982: LIVE_VIDEODECODECOMMANDLIST]
D3D12 WARNING: Live ID3D12Fence at 0x000001FF7C2FD410, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING: Live ID3D12Fence at 0x000001FF7C2F9A40, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING: Live ID3D12Fence at 0x000001FF7C2FB160, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING: Live ID3D12Fence at 0x000001FF7C2FAA70, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING: Live ID3D12Fence at 0x000001FF7C2F9EE0, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING: Live ID3D12Fence at 0x000001FF7C2FA130, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING: Live ID3D12Fence at 0x000001FF7C2FA380, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING: Live ID3D12Fence at 0x000001FF7C2FBCF0, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING: Live ID3D12Fence at 0x000001FF7C2FCD20, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING: Live ID3D12Fence at 0x000001FF7C2FA820, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING: Live ID3D12Fence at 0x000001FF7C2FD1C0, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING: Live ID3D12Fence at 0x000001FF7C2FACC0, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #580: LIVE_MONITOREDFENCE]
D3D12 WARNING: Live ID3D12VideoDecoder at 0x000001FF74E16A60, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #983: LIVE_VIDEODECODER]
D3D12 WARNING: Live ID3D12VideoDecoderHeap at 0x000001FF7C1BA330, Refcount: 1, IntRef: 0 [ STATE_CREATION WARNING #1084: LIVE_VIDEODECODERHEAP]
When the app is closing, there is this report, where the pointers correspond to the ID3D12Fence
seen above:
D3D12 WARNING: Process is terminating. Using simple reporting. Please call ReportLiveObjects() at runtime for standard reporting. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Producer at 0x000001FF74BB01E8, Refcount: 26. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF72D6A030, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF74E7DF70, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF74E79A30, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF74C48E30, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF74D8ABF0, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF74C49D40, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF74C49F90, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF7B7026E0, Refcount: 0. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF7C2FD410, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF7C2F9A40, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF7C2FB160, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF7C2FAA70, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF7C2F9EE0, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF7C2FA130, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF7C2FA380, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF7C2FBCF0, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF7C2FCD20, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF7C2FA820, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF7C2FD1C0, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object at 0x000001FF7C2FACC0, Refcount: 1. [ STATE_CREATION WARNING #0: UNKNOWN]
D3D12 WARNING: Live Object : 20 [ STATE_CREATION WARNING #0: UNKNOWN]