Bagikan melalui


Mendukung Dekode Video Direct3D 11 di Media Foundation

Topik ini menjelaskan cara mendukung Microsoft Direct3D 11 dalam dekoder Microsoft Media Foundation. Secara khusus, ini menjelaskan komunikasi antara dekoder dan perender video. Topik ini tidak menjelaskan cara menerapkan operasi decoding.

Gambaran Umum

Di sisa topik ini, istilah berikut digunakan:

  • Dekoder perangkat lunak. Dekoder perangkat lunak adalah transformasi Media Foundation (MFT) yang menerima sampel video terkompresi dan menghasilkan bingkai video yang tidak dikompresi.
  • Perangkat dekoder. Perangkat decoder adalah akselerator video, dan diimplementasikan oleh driver grafis. Perangkat dekoder melakukan operasi decoding yang dipercepat.
  • Alur. Alur menghosting dekoder perangkat lunak dan memberikan buffer ke dan dari dekoder perangkat lunak. Tergantung pada aplikasi, alur mungkin adalah Sesi Media, Pembaca Sumber, atau kode aplikasi yang langsung memanggil MFT.

Untuk melakukan decoding menggunakan Direct3D 11, dekoder perangkat lunak harus memiliki pointer ke perangkat Direct3D 11. Perangkat Direct3D 11 dibuat secara eksternal ke dekoder perangkat lunak. Dalam skenario Sesi Media, perender video membuat perangkat Direct3D 11. Dalam skenario Pembaca Sumber, biasanya aplikasi membuat perangkat Direct3D 11.

DXGI Device Manager digunakan untuk berbagi Direct3D 11 antar komponen. Manajer Perangkat DXGI mengekspos antarmuka IMFDXGIDeviceManager . Alur mengatur penunjuk IMFDXGIDeviceManager pada dekoder perangkat lunak dengan mengirim pesan MFT_MESSAGE_SET_D3D_MANAGER .

Diagram berikut menunjukkan hubungan antara dekoder perangkat lunak, Direct3D 11, dan alur.

a diagram that shows the software decoder and the dxgi device manager.

Berikut adalah langkah-langkah dasar yang harus dilakukan dekoder perangkat lunak untuk mendukung Direct3D 11 di Media Foundation:

  1. Buka handel ke perangkat Direct3D 11.
  2. Temukan konfigurasi dekoder.
  3. Alokasikan buffer yang tidak dikompresi.
  4. Dekode bingkai.

Langkah-langkah ini dijelaskan secara lebih rinci di sisa topik ini.

Buka Handel Perangkat

Decoder MFT menggunakan manajer perangkat DXGI untuk mendapatkan handel ke perangkat Direct3D 11. Untuk membuka handel perangkat, lakukan langkah-langkah berikut:

  1. MFT decoder harus mengekspos atribut MF_SA_D3D11_AWARE dengan nilai TRUE.
  2. Topology Loader mengkueri atribut ini dengan memanggil IMFTransform::GetAttributes. Nilai TRUE menunjukkan bahwa MFT mendukung Direct3D 11.
  3. Topology Loader memanggil IMFTransform::P rocessMessage dengan pesan MFT_MESSAGE_SET_D3D_MANAGER. Parameter ulParam adalah pointer IUnknown ke manajer perangkat DXGI. Kueri pointer ini untuk antarmuka IMFDXGIDeviceManager.
  4. Panggil IMFDXGIDeviceManager::OpenDeviceHandle untuk mendapatkan handel ke perangkat Direct3D 11.
  5. Untuk mendapatkan pointer ke perangkat Direct3D 11, panggil IMFDXGIDeviceManager::GetVideoService. Teruskan handel perangkat dan nilai IID_ID3D11Device. Metode mengembalikan penunjuk ke antarmuka ID3D11Device.
  6. Untuk mendapatkan pointer ke akselerator video, hubungi IMFDXGIDeviceManager::GetVideoService lagi. Kali ini, berikan handel perangkat dan nilai IID_ID3D11VideoDevice. Metode mengembalikan penunjuk ke antarmuka ID3D11VideoDevice.
  7. Hubungi ID3D11Device::GetImmediateContext untuk mendapatkan pointer ID3D11DeviceContext.
  8. Panggil QueryInterface di ID3D11DeviceContext untuk mendapatkan pointer ID3D11VideoContext.
  9. Disarankan agar Anda menggunakan perlindungan multi-utas pada konteks perangkat untuk mencegah masalah kebuntuan yang terkadang dapat terjadi saat Anda memanggil ID3D11VideoContext::GetDecoderBuffer atau ID3D11VideoContext::ReleaseDecoderBuffer. Untuk mengatur perlindungan multi-utas, pertama-tama panggil QueryInterface di ID3D11Device untuk mendapatkan pointer ID3D10Multithread. Kemudian panggil ID3D10Multithread::SetMultithreadProtected, meneruskan true untuk bMTProtect.

Menemukan Konfigurasi Decoder

Untuk melakukan decoding, dekoder perangkat lunak harus menemukan konfigurasi yang kompatibel yang didukung oleh perangkat dekoder, termasuk format target render. Langkah ini terjadi di dalam metode IMFTransform::SetInputType , sebagai berikut.

  1. Validasi jenis media input. Jika jenis ditolak, lewati langkah-langkah yang tersisa dan kembalikan kode kesalahan.
  2. Hubungi ID3D11VideoDevice::GetVideoDecoderProfileCount untuk mendapatkan jumlah profil yang didukung.
  3. Panggil ID3D11VideoDevice::GetVideoDecoderProfile untuk menghitung profil dan mendapatkan GUID profil.
  4. Cari GUID profil yang cocok dengan format video dan kemampuan dekoder perangkat lunak. Misalnya, dekoder MPEG-2 akan mencari D3D11_DECODER_PROFILE_MPEG2_MOCOMP, D3D11_DECODER_PROFILE_MPEG2_IDCT, dan D3D11_DECODER_PROFILE_MPEG2_VLD.
  5. Jika GUID decoder yang sesuai ditemukan, periksa format output dengan memanggil metode ID3D11VideoDevice::CheckVideoDecoderFormat. Teruskan GUID decoder dan nilai DXGI_FORMAT yang menentukan format target render.
  6. Selanjutnya, temukan konfigurasi yang sesuai untuk dekoder.
    1. Panggil ID3D11VideoDevice::GetVideoDecoderConfigCount untuk mendapatkan jumlah konfigurasi dekoder. Teruskan GUID perangkat decoder yang sama, bersama dengan struktur D3D11_VIDEO_DECODER_DESC yang menjelaskan format target render yang diusulkan.
    2. Panggil ID3D11VideoDevice::GetVideoDecoderConfig untuk menghitung konfigurasi dekoder.

Dalam metode IMFTransform::GetOutputAvailableType, kembalikan format video yang tidak dikompresi berdasarkan format target render yang diusulkan.

Dalam metode IMFTransform::SetOutputType, periksa jenis media terhadap format target render.

Fallback ke Decoding Perangkat Lunak

MFT mungkin tidak dapat menemukan konfigurasi. Misalnya, driver grafis mungkin tidak mendukung kemampuan yang tepat. Dalam hal ini, MFT harus kembali ke decoding perangkat lunak, sebagai berikut.

  1. Metode SetInputType dan SetOutputType harus mengembalikan MF_E_UNSUPPORTED_D3D_TYPE.
  2. Sebagai respons, Topology Loader akan mengirim pesan MFT_MESSAGE_SET_D3D_MANAGER dengan nilai NULL untuk parameter ulParam .
  3. MFT merilis penunjuknya ke antarmuka IMFDXGIDeviceManager.
  4. Topology Loader menegosiasikan ulang jenis media.

Pada titik ini, MFT dapat menggunakan decoding perangkat lunak.

Mengalokasikan Buffer yang Tidak Dikompresi

Decoder bertanggung jawab untuk mengalokasikan tekstur Direct3D 11 untuk digunakan sebagai buffer video yang tidak dikompresi. Atribut MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT dalam atribut aliran output (lihatIMFTransform::GetOutputStreamAttributes) digunakan untuk menentukan berapa banyak permukaan dekoder yang harus dialokasikan untuk perender video yang digunakan untuk mendeinterlacing . Dekoder harus menggunakan nilai ini yang membatasinya untuk beberapa batas atas dan bawah yang wajar, misalnya 3-32. Untuk konten progresif, lihat MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE.

Dalam metode IMFTransform::GetOutputStreamInfo, atur bendera MFT_OUTPUT_STREAM_PROVIDES_SAMPLES dalam struktur MFT_OUTPUT_STREAM_INFO. Bendera ini memberi tahu Sesi Media bahwa MFT mengalokasikan sampel outputnya sendiri. Untuk mengalokasikan sampel output, MFT melakukan langkah-langkah berikut:

  1. Buat array tekstur 2D dengan memanggil ID3D11Device::CreateTexture2D. Dalam struktur D3D11_TEXTURE2D_DESC, atur ArraySize sama dengan jumlah permukaan yang dibutuhkan dekoder. Drive ini termasuk:

    • Permukaan untuk bingkai referensi.
    • Permukaan untuk deinterlacing (tiga permukaan).
    • Permukaan yang dibutuhkan dekoder untuk buffering.

    Bendera pengikatan (BindFlags) harus menyertakan bendera D3D11_BIND_DECODER dan bendera ikat apa pun yang diatur melalui atribut MF_SA_D3D11_BINDFLAGS dalam atribut aliran output.

  2. Untuk setiap permukaan dalam array tekstur, panggil ID3D11VideoDevice::CreateVideoDecoderOutputView untuk membuat tampilan output dekoder video. Selama decoding, tampilan output ini akan diteruskan ke metode ID3D11VideoContext::D ecoderBeginFrame.

  3. Untuk setiap permukaan dalam array tekstur, buat sampel media sebagai berikut:

    1. Buat buffer media DXGI dengan memanggil fungsi MFCreateDXGISurfaceBuffer. Teruskan penunjuk ID3D11Texture2D dan offset untuk setiap elemen dalam array tekstur. Fungsi mengembalikan penunjuk IMFMediaBuffer .
    2. Buat sampel media kosong dengan memanggil fungsi MFCreateVideoSampleFromSurface. Atur parameter pUnkSurface sama dengan NULL. Fungsi mengembalikan penunjuk IMFSample .
    3. Panggil IMFSample::AddBuffer untuk menambahkan buffer media ke sampel.

Anda harus menghancurkan semua tekstur yang Anda buat pada saat yang sama, daripada menghancurkan hanya beberapa dan terus menggunakan pengingat.

Decoding

Untuk membuat perangkat dekoder, panggil ID3D11VideoDevice::CreateVideoDecoder. Metode mengembalikan penunjuk ke antarmuka ID3D11VideoDecoder. Decoding harus terjadi di dalam metode IMFTransform::P rocessOutput. Pada setiap bingkai, panggil IMFDXGIDeviceManager::TestDevice untuk menguji ketersediaan DXGI. Jika perangkat telah berubah, dekoder perangkat lunak harus membuat ulang perangkat decoder, sebagai berikut:

  1. Tutup handel perangkat dengan memanggil IMFDXGIDeviceManager::CloseDeviceHandle.
  2. Rilis semua sumber daya yang terkait dengan perangkat Direct3D 11 sebelumnya, termasuk antarmuka ID3D11VideoDecoder, ID3D11VideoContext, ID3D11Texture2D, dan ID3D11VideoDecoderOutputView.
  3. Buka handel perangkat baru.
  4. Negosiasikan konfigurasi dekoder baru, seperti yang dijelaskan sebelumnya di Temukan Konfigurasi Decoder. Langkah ini diperlukan karena kemampuan perangkat mungkin telah berubah.
  5. Buat perangkat dekoder baru.

Dengan asumsi bahwa handel perangkat valid, proses decoding berfungsi sebagai berikut:

  1. Dapatkan permukaan yang tersedia yang saat ini tidak digunakan. Awalnya, semua permukaan tersedia.
  2. Kueri sampel media untuk antarmuka IMFTrackedSample.
  3. Panggil IMFTrackedSample::SetAllocator dan berikan penunjuk ke antarmuka IMFAsyncCallback. (Dekoder perangkat lunak harus mengimplementasikan antarmuka ini.) Ketika perender video merilis sampel, panggilan balik akan dipanggil. Gunakan panggilan balik ini untuk melacak sampel mana yang saat ini tersedia dan yang sedang digunakan.
  4. Panggil ID3D11VideoContext::D ecoderBeginFrame. Teruskan penunjuk ke antarmuka ID3D11VideoDecoder untuk perangkat decoder dan antarmuka ID3D11VideoDecoderOutputView untuk tampilan output.
  5. Lakukan hal berikut ini satu atau beberapa kali:
    1. Panggil ID3D11VideoContext::GetDecoderBuffer untuk mendapatkan buffer.
    2. Isi buffer.
    3. Panggil ID3D11VideoContext::ReleaseDecoderBuffer.
    4. Panggil ID3D11VideoContext::SubmitDecoderBuffer. Metode ini menginstruksikan perangkat decoder untuk melakukan operasi decoding pada bingkai.
  6. Panggil ID3D11VideoContext::D ecoderEndFrame untuk memberi sinyal akhir decoding untuk bingkai saat ini.

Direct3D 11 menggunakan struktur data yang sama dengan DXVA 2.0 untuk operasi decoding. Untuk kumpulan profil DXVA asli (untuk H.261, H.263, dan MPEG-2), struktur data ini dijelaskan dalam spesifikasi DXVA 1.0.

Dalam setiap pasangan panggilan DecoderBeginFrame dan SubmitDecoderBuffer , Anda dapat memanggil GetDecoderBuffer beberapa kali, tetapi hanya sekali untuk setiap jenis buffer. Jika Anda menggunakan jenis buffer yang sama dua kali tanpa memanggil SubmitDecoderBuffer, Anda akan menimpa data di buffer.

API Video Direct3D 11

Akselerasi Video DirectX 2.0