Direct3D-Video-Bewegungsschätzung

Dieser Artikel enthält Anleitungen für die Bewegungsvektorschätzung mit Direct3D 12-Video-APIs. Dieses Feature wurde in Windows 10 Version 2004 (10.0; Build 19041). Die Bewegungsschätzung ist der Prozess der Bestimmung von Bewegungsvektoren, die die Transformation von einem 2D-Bild zu einem anderen beschreiben. Die Bewegungsschätzung ist ein wesentlicher Bestandteil der Videocodierung und kann in Bildfrequenzkonvertierungsalgorithmen verwendet werden.

Während die Bewegungsschätzung mit Shadern implementiert werden kann, besteht der Zweck der Funktion D3D12 Motion Estimation darin, eine feste Funktionsbeschleunigung für die Bewegungssuche verfügbar zu machen, um diesen Teil der Arbeit aus 3D auszulagern. Dies geschieht häufig in Form der Verfügbarmachen des GPU-Videoencoder-Bewegungsschätzungs. Das Ziel der D3D12-Bewegungsschätzung ist ein optischer Fluss. Beachten Sie jedoch, dass Encoder-Bewegungsschätzungen möglicherweise zur Verbesserung der Komprimierung optimiert werden können.

Suchen nach Support

Bestimmen Sie die Unterstützung für alle D3D-Videofeatures, indem Sie ID3D12VideoDevice::CheckFeatureSupport aufrufen und einen Wert aus der D3D12_FEATURE_VIDEO-Enumeration übergeben, um das Feature anzugeben, für das die Unterstützung abgefragt wird. Verwenden Sie zum Abfragen der unterstützten Blockgröße und Auflösungen für ein bestimmtes Format den wert D3D12_FEATURE_VIDEO_MOTION_ESTIMATOR, und geben Sie eine D3D12_FEATURE_DATA_VIDEO_MOTION_ESTIMATOR-Struktur für pFeatureSupportData an, wie im folgenden Beispiel gezeigt. In der aktuellen Version wird nur DXGI_FORMAT_NV12 unterstützt, sodass Inhalte in anderen Formaten möglicherweise farbkonvertiert und nach unten geschaltet werden müssen, um die Bewegungsschätzung zu verwenden.

D3D12_FEATURE_DATA_VIDEO_MOTION_ESTIMATOR MotionEstimatorSupport = {0u, DXGI_FORMAT_NV12};
VERIFY(spVideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_MOTION_ESTIMATOR, &MotionEstimatorSupport, sizeof(MotionEstimatorSupport)));

Das Bewegungsschätzungskontextobjekt

Das ID3D12VideoMotionEstimator-Objekt verwaltet den Kontext für Videobewegungsschätzungsvorgänge. Erstellen Sie eine neue Instanz dieser Schnittstelle, indem Sie ID3D12VideoDevice1::CreateVideoMotionEstimatoraufrufen.

Die ausgewählte Blockgröße, Genauigkeit und der unterstützte Größenbereich hängen von den Werten ab, die von der Hardware unterstützt werden, die von der D3D12_FEATURE_VIDEO_MOTION_ESTIMATOR Featureüberprüfung zurückgegeben wird. Sie können einen kleineren Größenbereich auswählen, als der Treiber unterstützt. Der Größenbereich informiert über interne Zuordnungsgrößen.

D3D12_VIDEO_MOTION_ESTIMATOR_DESC motionEstimatorDesc = { 
    0, //NodeIndex
    DXGI_FORMAT_NV12, 
    D3D12_VIDEO_MOTION_ESTIMATOR_SEARCH_BLOCK_SIZE_16X16,
    D3D12_VIDEO_MOTION_ESTIMATOR_VECTOR_PRECISION_QUARTER_PEL, 
    {1920, 1080, 1280, 720} // D3D12_VIDEO_SIZE_RANGE
    }; 

CComPtr<ID3D12VideoMotionEstimator> spVideoMotionEstimator;
VERIFY_SUCCEEDED(spVideoDevice->CreateVideoMotionEstimator(
    &motionEstimatorDesc, 
    nullptr,
    IID_PPV_ARGS(&spVideoMotionEstimator)));

Storage von Bewegungsvektoren

Id3D12VideoMotionVectorHeap speichert Bewegungsvektoren. Diese Schnittstelle wird von der D3D12_VIDEO_MOTION_ESTIMATOR_OUTPUT-Struktur verwendet, die von ID3D12VideoEncodeCommandList::EstimateMotionzurückgegeben wird. Die aufgelöste 2D-Ausgabetextur ist eine DXGI_FORMAT_R16G16_SINT Textur, in der R die horizontale Komponente und G die vertikale Komponente des Bewegungsvektors enthält. Diese Textur ist so dimensiont, dass sie ein Komponentenpaar pro Block aufnehmen kann. Rufen Sie ID3D12VideoEncodeCommandList::ResolveMotionVectorHeap auf, um die Motion Vector-Ausgabe von EstimateMotion aus hardwareabhängigen Formaten in ein konsistentes Format zu übersetzen, das von den Video motion estimation-APIs definiert wird.

D3D12_VIDEO_MOTION_VECTOR_HEAP_DESC MotionVectorHeapDesc = { 
    0, // NodeIndex 
    DXGI_FORMAT_NV12, 
    D3D12_VIDEO_MOTION_ESTIMATOR_SEARCH_BLOCK_SIZE_16X16,
    D3D12_VIDEO_MOTION_ESTIMATOR_VECTOR_PRECISION_QUARTER_PEL, 
    {1920, 1080, 1280, 720} // D3D12_VIDEO_SIZE_RANGE
    }; 

CComPtr<ID3D12VideoMotionVectorHeap> spVideoMotionVectorHeap;
VERIFY_SUCCEEDED(spVideoDevice->CreateVideoMotionVectorHeap(
    &MotionVectorHeapDesc, 
    nullptr, 
    IID_PPV_ARGS(&spVideoMotionVectorHeap)));
    CD3DX12_RESOURCE_DESC::Tex2D(
        DXGI_FORMAT_R16G16_SINT, 
        Align(1920, 16) / 16, // This example uses a 16x16 block size. Pixel width and height
        Align(1080, 16) / 16, // are adjusted to store the vectors for those blocks.
        1, // ArraySize
        1  // MipLevels
        );

    ATL::CComPtr< ID3D12Resource > spResolvedMotionVectors;
    VERIFY_SUCCEEDED(pDevice->CreateCommittedResource(
        &Properties,
        D3D12_HEAP_FLAG_NONE,
        &resolvedMotionVectorDesc,
        D3D12_RESOURCE_STATE_COMMON,
        nullptr,
        IID_PPV_ARGS(&spResolvedMotionVectors)));

ID3D12VideoMotionVectorHeap wird auch zum Bereitstellen von Hinweisvektoren in der D3D12_VIDEO_MOTION_ESTIMATOR_INPUT-Struktur verwendet.

Schätzen der Bewegung in einer Befehlsliste

Rufen Sie EstimateMotion aus einer ID3D12VideoEncodeCommandList auf, um den Vorgang zur Bewegungsschätzung aufzurufen.

Im folgenden Beispiel wird die Bewegungssuche ausgeführt und die Bewegungsvektoren mit D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODEin die 2D-Textur aufgelöst. D3D12-Ressourcen, die als Eingabe für EstimateMotion verwendet werden, müssen sich im D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ Zustand befinden, und die von ResolveMotionVectorHeap geschriebene Ressource muss sich im D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE Zustand befinden.

const D3D12_VIDEO_MOTION_ESTIMATOR_OUTPUT outputArgs = {spVideoMotionVectorHeap};

const D3D12_VIDEO_MOTION_ESTIMATOR_INPUT inputArgs = {
    spCurrentResource,
    0,
    spReferenceResource,
    0,
    nullptr // pHintMotionVectorHeap
    };

spCommandList->EstimateMotion(spVideoMotionEstimator, &outputArgs, &inputArgs);

const D3D12_RESOLVE_VIDEO_MOTION_VECTOR_HEAP_OUTPUT outputArgs = { 
    spResolvedMotionVectors,
    {}};

const D3D12_RESOLVE_VIDEO_MOTION_VECTOR_HEAP_INPUT inputArgs = {
    spVideoMotionVectorHeap,
    1920,
    1080
    };

spCommandList->ResolveMotionVectorHeap(&outputArgs, &inputArgs);
        
VERIFY(spCommandList->Close());

// Execute Commandlist.
ID3D12CommandList *ppCommandLists[1] = { spCommandList.p };
spCommandQueue->ExecuteCommandLists(1, ppCommandLists);

Geschützte Ressourcen

Die Direct3D 12-Bewegungsvektorschätzung unterstützt das Lesen von und Schreiben in hardwaregeschützte DRM-Ressourcen, wenn dies vom Treiber unterstützt wird. Wenn die Eingaberessourcen hardware-DRM-geschützt sind, handelt es sich bei der Ausgabe auch um eine hardwaregeschützte DRM-Ressource. Die Methoden zum Erstellen des Kontextobjekts für die Bewegungsschätzung und des Bewegungsvektorheaps ID3D12VideoDevice1::CreateVideoMotionEstimator und ID3D12VideoDevice1::CreateVideoMotionVectorHeapakzeptieren jeweils eine ID3D12ProtectedResourceSession, die zum Verwalten des Zugriffs auf geschützte Ressourcen verwendet wird.

Verwenden Sie ID3D12VideoMotionEstimator::GetProtectedResourceSession und ID3D12VideoMotionVectorHeap::GetProtectedResourceSession, um die ID3D12ProtectedResourceSession-Objekte abzurufen, die beim Erstellen der Objekte bereitgestellt wurden.