Supporto di DXVA 2.0 in Media Foundation

Questo argomento descrive come supportare DirectX Video Acceleration (DXVA) 2.0 in una trasformazione di Media Foundation (MFT) usando In particolare Microsoft Direct3D 9, descrive in modo specifico la comunicazione tra il decodificatore e il renderer video, mediato dal caricatore della topologia. Questo argomento non descrive come implementare la decodifica DXVA.

Nel resto di questo argomento, il termine decodificatore si riferisce al decodificatore MFT, che riceve video compressi e restituisce video non compressi. Il termine dispositivo decodificatore fa riferimento a un acceleratore video hardware implementato dal driver grafico.

Suggerimento

Per informazioni sulla decodifica video di Microsoft Direct3D 11, vedi Supporto della decodifica video Direct3D 11 in Media Foundation.

 

Nota

Le app di Windows Store devono usare Direct3D 11.

 

Ecco i passaggi di base che un decodificatore deve eseguire per supportare DXVA 2.0 in Media Foundation:

  1. Aprire un handle per il dispositivo Direct3D 9.
  2. Trovare una configurazione del decodificatore DXVA.
  3. Allocare buffer non compressi.
  4. Decodificare i fotogrammi.

Questi passaggi sono descritti in modo più dettagliato nella parte restante di questo argomento.

Apertura di un handle dispositivo Direct3D

MFT usa gestione dispositivi Microsoft Direct3D per ottenere un handle per il dispositivo Direct3D 9. Per aprire l'handle del dispositivo, seguire questa procedura:

  1. Esporre l'attributo MF_SA_D3D_AWARE con il valore TRUE. Il caricatore della topologia esegue una query su questo attributo chiamando IMFTransform::GetAttributes. L'impostazione dell'attributo su TRUE notifica al caricatore della topologia che MFT supporta DXVA.
  2. All'inizio della negoziazione del formato, il caricatore della topologia chiama IMFTransform::P rocessMessage con il messaggio MFT_MESSAGE_SET_D3D_MANAGER . Il parametro ulParam è un puntatore IUnknown alla gestione dispositivi Direct3D del renderer video. Eseguire una query su questo puntatore per l'interfaccia IDirect3DDeviceManager9 .
  3. Chiama IDirect3DDeviceManager9::OpenDeviceHandle per ottenere un handle per il dispositivo Direct3D del renderer.
  4. Chiama IDirect3DDeviceManager9::GetVideoService e passa l'handle del dispositivo. Questo metodo restituisce un puntatore all'interfaccia IDirectXVideoDecoderService .
  5. Memorizzare nella cache i puntatori e l'handle del dispositivo.

Ricerca di una configurazione del decodificatore

MFT deve trovare una configurazione compatibile per il dispositivo decodificatore DXVA. Eseguire i passaggi seguenti all'interno del metodo IMFTransform::SetInputType , dopo aver convalidato il tipo di input:

  1. Chiama IDirectXVideoDecoderService::GetDecoderDeviceGuids. Questo metodo restituisce una matrice di GUID del dispositivo decodificatore.

  2. Scorrere la matrice di GUID del decodificatore per trovare quelli supportati dal decodificatore. Ad esempio, per un decodificatore MPEG-2, cercare DXVA2_ModeMPEG2_MOCOMP, DXVA2_ModeMPEG2_IDCT o DXVA2_ModeMPEG2_VLD.

  3. Quando si trova il GUID di un decodificatore candidato, passare il GUID al metodo IDirectXVideoDecoderService::GetDecoderRenderTargets . Questo metodo restituisce una matrice di formati di destinazione di rendering, specificati come valori D3DFORMAT .

  4. Scorrere i formati di destinazione di rendering e cercare un formato supportato dal decodificatore.

  5. Chiamare IDirectXVideoDecoderService::GetDecoderConfigurations. Passare lo stesso GUID del dispositivo decodificatore, insieme a una struttura DXVA2_VideoDesc che descrive il formato di output proposto. Il metodo restituisce una matrice di strutture DXVA2_ConfigPictureDecode . Ogni struttura descrive una possibile configurazione per il dispositivo decodificatore. Cercare una configurazione supportata dal decodificatore.

  6. Archiviare il formato e la configurazione della destinazione di rendering.

Nel metodo IMFTransform::GetOutputAvailableType restituire un formato video non compresso, in base al formato di destinazione di rendering proposto.

Nel metodo IMFTransform::SetOutputType controllare il tipo di supporto rispetto al formato di destinazione di rendering.

Fallback alla decodifica software

Se MFT non riesce a trovare una configurazione DXVA (ad esempio, se il driver grafico non dispone delle funzionalità appropriate), deve restituire il codice di errore MF_E_UNSUPPORTED_D3D_TYPE dai metodi SetInputType e SetOutputType . Il caricatore della topologia risponde inviando il messaggio MFT_MESSAGE_SET_D3D_MANAGER con il valore NULL per il parametro ulParam . MFT deve rilasciare il puntatore all'interfaccia IDirect3DDeviceManager9 . Il caricatore della topologia rinegozia il tipo di supporto e MFT può usare la decodifica software.

Allocazione di buffer non compressi

In DXVA 2.0, il decodificatore è responsabile dell'allocazione delle superfici Direct3D da usare come buffer video non compressi. Il decodificatore deve allocare 3 superfici per l'EVR da utilizzare per la dinterlacing. Questo numero è fisso, perché Media Foundation non fornisce un modo per l'EVR di specificare il numero di superfici richieste dal driver grafico per l'inserimento dei dati. Tre superfici dovrebbero essere sufficienti per qualsiasi conducente.

Nel metodo IMFTransform::GetOutputStreamInfo impostare il flag MFT_OUTPUT_STREAM_PROVIDES_SAMPLES nella struttura MFT_OUTPUT_STREAM_INFO . Questo flag notifica alla sessione multimediale che MFT alloca i propri esempi di output.

Per creare le superfici, chiamare IDirectXVideoAccelerationService::CreateSurface. L'interfaccia IDirectXVideoDecoderService eredita questo metodo da IDirectXVideoAccelerationService. È possibile eseguire questa operazione in SetInputType, dopo aver trovato il formato di destinazione di rendering.

Per ogni superficie, chiama MFCreateVideoSampleFromSurface per creare un campione multimediale per contenere la superficie. Il metodo restituisce un puntatore all'interfaccia IMFSample .

Decodifica

Per creare il dispositivo decodificatore, chiama IDirectXVideoDecoderService::CreateVideoDecoder. Il metodo restituisce un puntatore all'interfaccia IDirectXVideoDecoder del dispositivo decodificatore.

La decodifica deve essere eseguita all'interno del metodo IMFTransform::P rocessOutput . In ogni frame chiamare IDirect3DDeviceManager9::TestDevice per testare l'handle del dispositivo. Se il dispositivo è stato modificato, il metodo restituisce DXVA2_E_NEW_VIDEO_DEVICE. In questo caso, eseguire le operazioni seguenti:

  1. Chiudere l'handle del dispositivo chiamando IDirect3DDeviceManager9::CloseDeviceHandle.
  2. Rilasciare i puntatori IDirectXVideoDecoderService e IDirectXVideoDecoder .
  3. Aprire un nuovo handle del dispositivo.
  4. Negoziare una nuova configurazione del decodificatore, come descritto in "Ricerca di una configurazione del decodificatore" in precedenza in questa pagina.
  5. Creare un nuovo dispositivo decodificatore.

Supponendo che l'handle del dispositivo sia valido, il processo di decodifica funziona come segue:

  1. Ottenere una superficie disponibile attualmente non in uso. (Inizialmente tutte le superfici sono disponibili.
  2. Eseguire una query sull'esempio multimediale per l'interfaccia IMFTrackedSample .
  3. Chiamare IMFTrackedSample::SetAllocator e fornire un puntatore all'interfaccia IMFAsyncCallback , implementata dal decodificatore. Quando il renderer video rilascia l'esempio, viene richiamato il callback del decodificatore.
  4. Chiama IDirectXVideoDecoder::BeginFrame.
  5. Eseguire le operazioni seguenti una o più volte:
    1. Chiama IDirectXVideoDecoder::GetBuffer per ottenere un buffer del decodificatore DXVA.
    2. Riempire il buffer.
    3. Chiama IDirectXVideoDecoder::ReleaseBuffer.
    4. Chiamare IDirectXVideoDecoder::Execute per eseguire le operazioni di decodifica nel frame.

DXVA 2.0 usa le stesse strutture di dati di DXVA 1.0 per le operazioni di decodifica. Per il set originale di profili DXVA (per H.261, H.263 e MPEG-2), queste strutture di dati sono descritte nella specifica DXVA 1.0.

All'interno di ogni coppia di chiamate BeginFrame/Execute è possibile chiamare GetBuffer più volte, ma una sola volta per ogni tipo di buffer DXVA. Se la si chiama due volte con lo stesso tipo di buffer, si sovrascriveranno i dati.

Usare il callback dal metodo SetAllocator (passaggio 3) per tenere traccia dei campioni attualmente disponibili e usati.

Accelerazione video DirectX 2.0

Trasformazioni di Media Foundation