Supporto della decodifica video direct3D 11 in Media Foundation
Questo argomento descrive come supportare Microsoft Direct3D 11 in un decodificatore di Microsoft Media Foundation. In particolare, descrive la comunicazione tra il decodificatore e il renderer video. In questo argomento non viene descritto come implementare le operazioni di decodifica.
- Panoramica
- Aprire un handle di dispositivo
- Trovare una configurazione del decodificatore
- Fallback alla decodifica software
- Allocazione di buffer non compressi
- Decodifica
- Argomenti correlati
Panoramica
Nella parte restante di questo argomento vengono usati i termini seguenti:
- Decodificatore software. Il decodificatore software è la trasformazione Media Foundation (MFT) che riceve campioni video compressi e restituisce fotogrammi video non compressi.
- Dispositivo decodificatore. Il dispositivo decodificatore è l'acceleratore video e viene implementato dal driver grafico. Il dispositivo decodificatore esegue operazioni di decodifica accelerata.
- Pipeline. La pipeline ospita il decodificatore software e distribuisce buffer da e verso il decodificatore software. A seconda dell'applicazione, la pipeline potrebbe essere la sessione multimediale, il lettore di origine o il codice dell'applicazione che chiama direttamente in MFT.
Per eseguire la decodifica tramite Direct3D 11, il decodificatore software deve avere un puntatore a un dispositivo Direct3D 11. Il dispositivo Direct3D 11 viene creato esternamente al decodificatore software. In uno scenario di sessione multimediale, il renderer video crea il dispositivo Direct3D 11. In uno scenario di lettura origine, in genere l'applicazione crea il dispositivo Direct3D 11.
Il Gestione dispositivi DXGI viene usato per condividere Direct3D 11 tra i componenti. Il Gestione dispositivi DXGI espone l'interfaccia IMFDXGIDeviceManager. La pipeline imposta il puntatore IMFDXGIDeviceManager sul decodificatore software inviando il messaggio di MFT_MESSAGE_edizione StandardT_D3D_MANAGER.
Il diagramma seguente illustra la relazione tra il decodificatore software, Direct3D 11 e la pipeline.
Ecco i passaggi di base che un decodificatore software deve eseguire per supportare Direct3D 11 in Media Foundation:
- Aprire un handle per il dispositivo Direct3D 11.
- Trovare una configurazione del decodificatore.
- Allocare buffer non compressi.
- Decodificare i fotogrammi.
Questi passaggi sono descritti in modo più dettagliato nella parte restante di questo argomento.
Aprire un handle di dispositivo
Il decodificatore MFT usa la gestione dispositivi DXGI per ottenere un handle per il dispositivo Direct3D 11. Per aprire l'handle del dispositivo, seguire questa procedura:
- Il decodificatore MFT deve esporre l'attributo MF_SA_D3D11_AWARE con il valore TRUE.
- Il caricatore della topologia esegue una query su questo attributo chiamando IMFTransform::GetAttributes. Il valore TRUE indica che MFT supporta Direct3D 11.
- Il caricatore della topologia chiama IMFTransform::P rocessMessage con il messaggio MFT_MESSAGE_edizione StandardT_D3D_MANAGER. Il parametro ulParam è un puntatore IUnknown alla gestione dispositivi DXGI. Eseguire una query su questo puntatore per l'interfaccia IMFDXGIDeviceManager .
- Chiama IMFDXGIDeviceManager::OpenDeviceHandle per ottenere un handle per il dispositivo Direct3D 11.
- Per ottenere un puntatore al dispositivo Direct3D 11, chiama IMFDXGIDeviceManager::GetVideoService. Passare l'handle del dispositivo e il valore IID_ID3D11Device. Il metodo restituisce un puntatore all'interfaccia ID3D11Device .
- Per ottenere un puntatore all'acceleratore video, chiama di nuovo IMFDXGIDeviceManager::GetVideoService. Questa volta, passare l'handle del dispositivo e il valore IID_ID3D11VideoDevice. Il metodo restituisce un puntatore all'interfaccia ID3D11VideoDevice .
- Chiama ID3D11Device::GetImmediateContext per ottenere un puntatore ID3D11DeviceContext.
- Chiama QueryInterface sull'ID3D11DeviceContext per ottenere un puntatore ID3D11VideoContext.
- È consigliabile usare la protezione multithread nel contesto del dispositivo per evitare problemi di deadlock che possono verificarsi a volte quando si chiama ID3D11VideoContext::GetDecoderBuffer o ID3D11VideoContext::ReleaseDecoderBuffer. Per impostare la protezione multithread, chiamare prima QueryInterface su ID3D11Device per ottenere un puntatore ID3D10Multithread. Chiamare quindi ID3D10Multithread::SetMultithreadProtected, passando true per bMTProtect.
Trovare una configurazione del decodificatore
Per eseguire la decodifica, il decodificatore software deve trovare una configurazione compatibile supportata dal dispositivo decodificatore, incluso un formato di destinazione di rendering. Questo passaggio si verifica all'interno del metodo IMFTransform::SetInputType , come indicato di seguito.
- Convalidare il tipo di supporto di input. Se il tipo viene rifiutato, ignorare i passaggi rimanenti e restituire un codice di errore.
- Chiama ID3D11VideoDevice::GetVideoDecoderProfileCount per ottenere il numero di profili supportati.
- Chiama ID3D11VideoDevice::GetVideoDecoderProfile per enumerare i profili e ottenere i GUID del profilo.
- Cercare un GUID del profilo corrispondente al formato video e alle funzionalità del decodificatore software. Ad esempio, un decodificatore MPEG-2 cercherebbe D3D11_DECODER_PROFILE_MPEG2_MOCOMP, D3D11_DECODER_PROFILE_MPEG2_IDCT e D3D11_DECODER_PROFILE_MPEG2_VLD.
- Se viene trovato un GUID del decodificatore appropriato, controllare il formato di output chiamando il metodo ID3D11VideoDevice::CheckVideoDecoderFormat. Passare il GUID del decodificatore e un valore DXGI_FORMAT che specifica il formato di destinazione di rendering.
- Trovare quindi una configurazione adatta per il decodificatore.
- Chiama ID3D11VideoDevice::GetVideoDecoderConfigCount per ottenere il numero di configurazioni del decodificatore. Passare lo stesso GUID del dispositivo decodificatore, insieme a una struttura D3D11_VIDEO_DECODER_DESC che descrive il formato di destinazione di rendering proposto.
- Chiamare ID3D11VideoDevice::GetVideoDecoderConfig per enumerare le configurazioni del decodificatore.
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
Il MFT potrebbe non essere in grado di trovare una configurazione. Ad esempio, il driver di grafica potrebbe non supportare le funzionalità corrette. In tal caso, il MFT deve eseguire il fallback alla decodifica software, come indicato di seguito.
- I metodi SetInputType e SetOutputType devono restituire entrambi MF_E_UNSUPPORTED_D3D_TYPE.
- In risposta, il caricatore della topologia invierà il messaggio MFT_MESSAGE_edizione StandardT_D3D_MANAGER con il valore NULL per il parametro ulParam.
- MFT rilascia il puntatore all'interfaccia IMFDXGIDeviceManager .
- Il caricatore della topologia rinegozia il tipo di supporto.
A questo punto, MFT può usare la decodifica software.
Allocazione di buffer non compressi
Il decodificatore è responsabile dell'allocazione di trame Direct3D 11 da usare come buffer video non compressi. L'attributo MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT negli attributi del flusso di output (vedereIMFTransform::GetOutputStreamAttributes) viene usato per determinare il numero di superfici che il decodificatore deve allocare per il renderer video da usare per la denterlacing . Un decodificatore deve usare questo valore delimitato per alcuni limiti superiori e inferiori ragionevoli, ad esempio 3-32. Per il contenuto progressivo, vedere MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE.
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 campioni di output. Per allocare gli esempi di output, MFT esegue i passaggi seguenti:
Creare una matrice di trame 2D chiamando ID3D11Device::CreateTexture2D. Nella struttura D3D11_TEXTURE2D_DESC impostare ArraySize uguale al numero di superfici necessarie per il decodificatore. Valuta gli ambiti seguenti:
- Superfici per i frame di riferimento.
- Superfici per la disincantazione (tre superfici).
- Superfici necessarie per il buffering del decodificatore.
I flag di associazione (BindFlags) devono includere il flag D3D11_BIND_DECODER ed eventuali flag di binding impostati tramite l'attributo MF_SA_D3D11_BINDFLAGS negli attributi del flusso di output.
Per ogni superficie nella matrice di trame, chiama ID3D11VideoDevice::CreateVideoDecoderOutputView per creare una visualizzazione di output del decodificatore video. Durante la decodifica, queste visualizzazioni di output verranno passate al metodo ID3D11VideoContext::D ecoderBeginFrame.
Per ogni superficie nella matrice di trame, creare un esempio multimediale come segue:
- Creare un buffer multimediale DXGI chiamando la funzione MFCreateDXGISurfaceBuffer. Passare il puntatore ID3D11Texture2D e l'offset per ogni elemento nella matrice di trame. La funzione restituisce un puntatore IMFMediaBuffer.
- Creare un esempio multimediale vuoto chiamando la funzione MFCreateVideoSampleFromSurface. Impostare il parametro pUnkSurface su NULL. La funzione restituisce un puntatore IMFSample.
- Chiamare IMFSample::AddBuffer per aggiungere il buffer multimediale all'esempio.
È consigliabile distruggere tutte le trame create contemporaneamente, invece di distruggere solo alcuni e continuare a usare il promemoria.
Decodifica
Per creare il dispositivo decodificatore, chiama ID3D11VideoDevice::CreateVideoDecoder. Il metodo restituisce un puntatore all'interfaccia ID3D11VideoDecoder . La decodifica deve essere eseguita all'interno del metodo IMFTransform::P rocessOutput. In ogni fotogramma chiamare IMFDXGIDeviceManager::TestDevice per testare la disponibilità di DXGI. Se il dispositivo è stato modificato, il decodificatore software deve ricreare il dispositivo decodificatore, come indicato di seguito:
- Chiudere l'handle del dispositivo chiamando IMFDXGIDeviceManager::CloseDeviceHandle.
- Rilasciare tutte le risorse associate al dispositivo Direct3D 11 precedente, incluse le interfacce ID3D11VideoDecoder, ID3D11VideoContext, ID3D11Texture2D e ID3D11VideoDecoderOutputView.
- Aprire un nuovo handle di dispositivo.
- Negoziare una nuova configurazione del decodificatore, come descritto in precedenza in Trovare una configurazione decodificatore. Questo passaggio è necessario perché le funzionalità del dispositivo potrebbero essere state modificate.
- Creare un nuovo dispositivo decodificatore.
Supponendo che l'handle del dispositivo sia valido, il processo di decodifica funziona come segue:
- Ottenere una superficie disponibile che non è attualmente in uso. Inizialmente, tutte le superfici sono disponibili.
- Eseguire una query sull'esempio multimediale per l'interfaccia IMFTrackedSample .
- Chiamare IMFTrackedSample::SetAllocator e fornire un puntatore all'interfaccia IMFAsyncCallback. Il decodificatore software deve implementare questa interfaccia. Quando il renderer video rilascia l'esempio, verrà richiamato il callback. Usare questo callback per tenere traccia di quali esempi sono attualmente disponibili e che sono in uso.
- Chiamare ID3D11VideoContext::D ecoderBeginFrame. Passare i puntatori all'interfaccia ID3D11VideoDecoder per il dispositivo decodificatore e l'interfaccia ID3D11VideoDecoderOutputView per la visualizzazione di output.
- Eseguire le operazioni seguenti una o più volte:
- Chiamare ID3D11VideoContext::GetDecoderBuffer per ottenere un buffer.
- Riempire il buffer.
- Chiamare ID3D11VideoContext::ReleaseDecoderBuffer.
- Chiamare ID3D11VideoContext::SubmitDecoderBuffer. Questo metodo indica al dispositivo decodificatore di eseguire le operazioni di decodifica sul frame.
- Chiamare ID3D11VideoContext::D ecoderEndFrame per segnalare la fine della decodifica per il frame corrente.
Direct3D 11 usa le stesse strutture di dati di DXVA 2.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 DecoderBeginFrame e SubmitDecoderBuffer, è possibile chiamare GetDecoderBuffer più volte, ma solo una volta per ogni tipo di buffer. Se si usa lo stesso tipo di buffer due volte senza chiamare SubmitDecoderBuffer, si sovrascriveranno i dati nel buffer.
Argomenti correlati