Model Pemrosesan MFT Dasar

Topik ini menjelaskan bagaimana klien menggunakan transformasi Media Foundation (MFT) untuk memproses data. Klien adalah apa pun yang secara langsung memanggil metode pada MFT. Ini mungkin aplikasi atau alur Media Foundation.

Baca topik ini jika Anda:

  • Menulis aplikasi yang melakukan panggilan langsung ke satu atau beberapa MFTs.
  • Menulis MFT kustom dan ingin memahami perilaku MFT yang diharapkan.

Topik ini menjelaskan model pemrosesan sinkron . Dalam model ini, semua metode pemrosesan data memblokir hingga selesai. MFTs juga dapat mendukung model asinkron , yang dijelaskan dalam topik MFTs Asinkron.

Model Pemrosesan Dasar

Membuat MFT

Ada beberapa cara untuk membuat MFT:

  • Panggil fungsi MFTEnum .
  • Panggil fungsi MFTEnumEx .
  • Jika Anda sudah mengetahui CLSID MFT, cukup panggil CoCreateInstance.

Beberapa MFT mungkin menyediakan opsi lain, seperti fungsi pembuatan khusus.

Dapatkan Pengidentifikasi Aliran

MFT memiliki satu atau beberapa aliran. Aliran input menerima data input, dan aliran output menghasilkan data output. Aliran tidak direpresentasikan sebagai objek yang berbeda. Sebagai gantinya, berbagai metode MFT mengambil pengidentifikasi aliran sebagai parameter.

Beberapa MFT memungkinkan klien untuk menambahkan atau menghapus aliran input. Selama streaming, MFT dapat menambahkan atau menghapus aliran output. (Klien tidak dapat menambahkan atau menghapus aliran output.)

  1. (Opsional.) Panggil IMFTransform::GetStreamLimits untuk mendapatkan jumlah aliran minimum dan maksimum yang dapat didukung MFT. Jika minimum dan maksimum sama, MFT memiliki jumlah aliran tetap.
  2. Panggil IMFTransform::GetStreamCount untuk mendapatkan jumlah awal aliran.
  3. Panggil IMFTransform::GetStreamIDs untuk mendapatkan pengidentifikasi aliran. Jika metode ini mengembalikan E_NOTIMPL, itu berarti MFT memiliki jumlah aliran tetap, dan pengidentifikasi aliran berturut-turut mulai dari nol.
  4. (Opsional.) Jika MFT tidak memiliki jumlah aliran tetap, panggil IMFTransform::AddInputStreams untuk menambahkan lebih banyak aliran input, atau IMFTransform::D eleteInputStream untuk menghapus aliran input. (Anda tidak dapat menambahkan atau menghapus aliran output.)

Setel Tipe Media

Sebelum MFT dapat memproses data, klien harus mengatur jenis media untuk setiap aliran MFT. MFT mungkin mengharuskan klien mengatur jenis input sebelum mengatur jenis output, atau mungkin memerlukan urutan yang berlawanan (jenis output terlebih dahulu). Beberapa MFTs tidak memiliki persyaratan pada pesanan.

MFT dapat menyediakan daftar jenis media pilihan untuk aliran. Selain itu, MFTs dapat menunjukkan format umum yang didukungnya dengan menambahkan informasi ini ke registri.

Untuk mengatur jenis media, lakukan hal berikut:

  1. (Opsional.) Untuk setiap aliran input, panggil IMFTransform::GetInputAvailableType untuk mendapatkan daftar jenis pilihan untuk aliran tersebut.
    • Jika metode ini mengembalikan MF_E_TRANSFORM_TYPE_NOT_SET, Anda harus mengatur jenis output terlebih dahulu; lewati ke langkah 3.
    • Jika metode mengembalikan E_NOTIMPL, MFT tidak memiliki daftar jenis input pilihan; lewati ke langkah 2.
  2. Untuk setiap aliran input, panggil IMFTransform::SetInputType untuk mengatur jenis input. Anda dapat menggunakan jenis media dari langkah 1, atau jenis yang menjelaskan data input Anda. Jika ada aliran yang mengembalikan MF_E_TRANSFORM_TYPE_NOT_SET, lewati ke langkah 3.
  3. (Opsional.) Untuk setiap aliran output, panggil IMFTransform::GetOutputAvailableType untuk mendapatkan daftar jenis pilihan untuk aliran tersebut.
    • Jika metode ini mengembalikan MF_E_TRANSFORM_TYPE_NOT_SET, Anda harus mengatur jenis input terlebih dahulu; kembali ke langkah 1.
    • Jika ada aliran yang mengembalikan E_NOTIMPL, MFT tidak memiliki daftar jenis output pilihan; lewati ke langkah 4.
  4. Untuk setiap aliran output, panggil IMFTransform::SetOutputType untuk mengatur jenis output. Anda dapat menggunakan jenis media dari langkah 3, atau jenis yang menjelaskan format output yang diperlukan.
  5. Jika ada aliran input yang tidak memiliki jenis media, kembali ke langkah 1.

Mendapatkan Persyaratan Buffer

Setelah klien menetapkan jenis media, klien harus mendapatkan persyaratan buffer untuk setiap aliran:

Memproses Data

MFT dirancang untuk menjadi mesin status yang andal. Ini tidak melakukan panggilan kembali ke klien.

  1. Panggil IMFTransform::P rocessMessage dengan pesan MFT_MESSAGE_NOTIFY_BEGIN_STREAMING . Pesan ini meminta MFT untuk mengalokasikan sumber daya apa pun yang dibutuhkan selama streaming.
  2. Panggil IMFTransform::P rocessInput pada setidaknya satu aliran input untuk mengirimkan sampel input ke MFT.
  3. (Opsional.) Panggil IMFTransform::GetOutputStatus untuk mengkueri apakah MFT dapat menghasilkan sampel output. Jika metode mengembalikan S_OK, periksa parameter pdwFlags . Jika pdwFlags berisi bendera MFT_OUTPUT_STATUS_SAMPLE_READY , buka langkah 4. Jika pdwFlags nol, kembali ke langkah 2. Jika metode mengembalikan E_NOTIMPL, buka langkah 4.
  4. Panggil IMFTransform::P rocessOutput untuk mendapatkan data output.
    • Jika metode mengembalikan MF_E_TRANSFORM_NEED_MORE_INPUT, itu berarti MFT memerlukan lebih banyak data input; kembali ke langkah 2.
    • Jika metode mengembalikan MF_E_TRANSFORM_STREAM_CHANGE, itu berarti jumlah aliran output telah berubah, atau format output telah berubah. Klien mungkin perlu mengkueri pengidentifikasi aliran baru atau mengatur jenis media baru. Untuk informasi selengkapnya, lihat dokumentasi untuk ProcessOutput.
  5. Jika masih ada data input yang akan diproses, buka langkah 2. Jika MFT telah menggunakan semua data input yang tersedia, lanjutkan ke langkah 6.
  6. Panggil ProcessMessage dengan pesan MFT_MESSAGE_NOTIFY_END_OF_STREAM .
  7. Panggil ProcessMessage dengan pesan MFT_MESSAGE_COMMAND_DRAIN .
  8. Panggil ProcessOutput untuk mendapatkan output yang tersisa. Ulangi langkah ini hingga metode mengembalikan MF_E_TRANSFORM_NEED_MORE_INPUT. Nilai pengembalian ini menandakan bahwa semua output telah dikosongkan dari MFT. (Jangan perlakukan ini sebagai kondisi kesalahan.)

Urutan yang dijelaskan di sini menyimpan data sesedikit mungkin dalam MFT. Setelah setiap panggilan ke ProcessInput, klien mencoba untuk mendapatkan output. Beberapa sampel input mungkin diperlukan untuk menghasilkan satu sampel output, atau satu sampel input mungkin menghasilkan beberapa sampel output. Perilaku optimal untuk klien adalah menarik sampel output dari MFT sampai MFT membutuhkan lebih banyak input.

Namun, MFT harus dapat menangani urutan panggilan metode yang berbeda oleh klien. Misalnya, klien mungkin hanya bergantian antara panggilan ke ProcessInput dan ProcessOutput. MFT harus membatasi jumlah input yang didapatkannya dengan mengembalikan MF_E_NOTACCEPTING dari ProcessInput setiap kali memiliki beberapa output untuk dihasilkan.

Urutan panggilan metode yang dijelaskan di sini bukan satu-satunya urutan peristiwa yang valid. Misalnya, langkah 3 dan 4 mengasumsikan bahwa klien dimulai dengan jenis input lalu mencoba jenis output. Klien juga dapat membalikkan urutan ini dan memulai dengan jenis output. Dalam kedua kasus, jika MFT memerlukan urutan yang berlawanan, MFT harus mengembalikan kode kesalahan MF_E_TRANSFORM_TYPE_NOT_SET.

Klien dapat memanggil metode informasi, seperti GetInputCurrentType dan GetOutputStreamInfo, kapan saja selama streaming. Klien juga dapat mencoba mengubah jenis media kapan saja. MFT harus mengembalikan kode kesalahan jika ini bukan operasi yang valid. Singkatnya, MFTs harus mengasumsikan sangat sedikit tentang urutan operasi, selain apa yang didokumentasikan dalam panggilan itu sendiri.

Diagram berikut ini memperlihatkan bagan alur prosedur yang dijelaskan dalam topik ini.

flow chart that leads from get stream identifiers through loops that set input types, get input, and process output

Ekstensi ke Model Dasar

Secara opsional, MFT dapat mendukung beberapa ekstensi ke model streaming dasar.

  • Lazy-read streams. Jika metode IMFTransform::GetOutputStreamInfo mengembalikan bendera MFT_OUTPUT_STREAM_LAZY_READ untuk aliran output, klien tidak perlu mengumpulkan data dari aliran output tersebut. MFT terus menerima input, dan pada titik tertentu MFT akan membuang data output dari aliran tersebut. Jika semua aliran output memiliki bendera ini, MFT tidak akan pernah gagal menerima input. Contohnya mungkin transformasi visualisasi, di mana klien mendapatkan output hanya ketika memiliki siklus CPU cadangan untuk menggambar visualisasi.
  • Aliran yang dapat dibuang. Jika metode GetOutputStreamInfo mengembalikan bendera MFT_OUTPUT_STREAM_DISCARDABLE untuk aliran output, klien dapat meminta MFT untuk membuang output, tetapi MFT tidak akan membuang output apa pun kecuali diminta. Ketika MFT mencapai buffer input maksimumnya, klien harus mengumpulkan beberapa data output atau meminta MFT untuk membuang output.
  • Aliran opsional. Jika metode GetOutputStreamInfo mengembalikan bendera MFT_OUTPUT_STREAM_OPTIONAL untuk aliran output, atau metode IMFTransform::GetInputStreamInfo mengembalikan bendera MFT_INPUT_STREAM_OPTIONAL untuk aliran input, aliran tersebut bersifat opsional. Klien tidak perlu mengatur jenis media pada aliran. Jika klien tidak mengatur jenisnya, aliran akan dibatalkan pilihannya. Aliran output yang tidak dipilih tidak menghasilkan sampel, dan klien tidak menyediakan buffer untuk aliran saat memanggil ProcessOutput. Aliran input yang tidak dipilih tidak menerima data input. MFT dapat menandai semua aliran input dan outputnya sebagai opsional. Namun, diharapkan setidaknya satu input dan satu output harus dipilih agar MFT berfungsi.
  • Pemrosesan asinkron. Model pemrosesan asinkron diperkenalkan di Windows 7. Ini dijelaskan dalam topik MFTs Asinkron.

IMF2DBuffer

Jika MFT memproses data video yang tidak dikompresi, MFT harus menggunakan antarmuka IMF2DBuffer untuk memanipulasi buffer sampel. Untuk mendapatkan antarmuka ini, kueri antarmuka IMFMediaBuffer pada buffer input atau output apa pun. Tidak menggunakan antarmuka ini ketika tersedia dapat mengakibatkan salinan buffer tambahan. Untuk memanfaatkan antarmuka ini dengan benar, transformasi tidak boleh mengunci buffer menggunakan antarmuka IMFMediaBuffer ketika IMF2DBuffer tersedia.

Untuk informasi selengkapnya tentang memproses data video, lihat Buffer Video Yang Tidak Dikompresi.

Membersihkan MFT

Membersihkan MFT menyebabkan MFT membuang semua data inputnya. Ini dapat menyebabkan jeda dalam aliran output. Klien biasanya akan membersihkan MFT sebelum mencari titik baru dalam aliran input atau beralih ke aliran input baru, ketika klien tidak peduli tentang kehilangan data.

Untuk menghapus MFT, panggil IMFTransform::P rocessMessage dengan pesan MFT_MESSAGE_COMMAND_FLUSH .

Menguras MFT

Menguras MFT menyebabkan MFT menghasilkan output sebanyak mungkin dari data input apa pun yang telah dikirim. Jika MFT tidak dapat menghasilkan sampel output lengkap dari input yang tersedia, MFT akan menghilangkan data input. Klien biasanya akan menguras MFT ketika mencapai akhir aliran sumber, atau segera sebelum perubahan format di aliran sumber. Untuk menguras MFT, lakukan hal berikut:

  1. Panggil ProcessMessage dengan pesan MFT_MESSAGE_COMMAND_DRAIN . Pesan ini memberi tahu MFT bahwa MFT harus mengirimkan data output sebanyak mungkin dari data input yang telah dikirim.
  2. Panggil ProcessOutput untuk mendapatkan data output, hingga metode mengembalikan MF_E_TRANSFORM_NEED_MORE_INPUT.

Saat MFT sedang dikosongkan, MFT tidak akan menerima input lagi.

Atribut Sampel

Sampel input mungkin memiliki atribut yang harus disalin ke sampel output yang sesuai.

Untuk MFT dengan satu input dan satu output, Anda dapat menggunakan aturan umum berikut:

  • Jika setiap sampel input menghasilkan tepat satu sampel output, Anda dapat membiarkan klien menyalin atribut. Biarkan properti MFPKEY_EXATTRIBUTE_SUPPORTED tidak diatur.
  • Jika tidak ada korespondensi satu-ke-satu antara sampel input dan sampel output, MFT harus menentukan atribut yang benar untuk sampel output. Atur properti MFPKEY_EXATTRIBUTE_SUPPORTED ke VARIANT_TRUE.

Diskontinuitas

Penghentian adalah jeda dalam aliran audio atau video. Penghentian dapat disebabkan oleh paket yang terputus pada koneksi jaringan, data file yang rusak, sakelar dari satu aliran sumber ke aliran lain, atau berbagai penyebab lainnya. Penghentian disinyalkan dengan mengatur atribut MFSampleExtension_Discontinuity pada sampel pertama setelah penghentian. Tidak dimungkinkan untuk memberi sinyal penghentian di tengah sampel. Oleh karena itu, setiap data yang dihentikan harus dikirim dalam sampel terpisah.

Beberapa transformasi, terutama yang menangani data yang tidak dikompresi, seperti efek audio dan video, harus mengabaikan penghentian saat memproses data input. MFTs ini umumnya dirancang untuk menangani data berkelanjutan, dan harus memperlakukan data apa pun yang mereka terima sebagai berkelanjutan, bahkan setelah penghentian.

Jika MFT mengabaikan penghentian pada data input, MFT masih harus mengatur bendera penghentian pada sampel output, jika sampel output memiliki stempel waktu yang sama dengan sampel input. Namun, jika sampel output memiliki stempel waktu yang berbeda, MFT tidak boleh menyebarluaskan penghentian. (Ini akan terjadi di beberapa resampler audio, misalnya.) Penghentian di tempat yang salah di aliran lebih buruk daripada tidak ada penghentian.

Sebagian besar dekode tidak dapat mengabaikan penghentian, karena penghentian memengaruhi interpretasi sampel berikutnya. Teknologi pengodean apa pun yang menggunakan kompresi antar bingkai, seperti MPEG-2, termasuk dalam kategori ini. Beberapa skema pengodean hanya menggunakan kompresi intra-frame, seperti DV dan MJPEG. Dekode ini dapat dengan aman mengabaikan penghentian.

Transformasi yang merespons penghentian umumnya harus menghasilkan sebanyak data sebelum penghentian seperti yang mereka bisa, dan membuang sisanya. Sampel input dengan bendera penghentian harus diproses seolah-olah itu adalah sampel pertama dalam aliran. (Perilaku ini cocok dengan apa yang ditentukan untuk pesan MFT_MESSAGE_COMMAND_DRAIN .) Namun, detail yang tepat akan bergantung pada format media.

Jika dekoder tidak melakukan apa pun untuk mengurangi penghentian, dekoder harus menyalin bendera penghentian ke data output. Demultiplexers dan MFTs lainnya yang bekerja sepenuhnya dengan data terkompresi harus menyalin penghentian apa pun ke aliran output mereka. Jika tidak, komponen hilir mungkin tidak dapat mendekode data terkompresi dengan benar. Secara umum, hampir selalu benar untuk melewati penghentian di hilir, kecuali MFT berisi kode eksplisit untuk memuluskan penghentian.

Perubahan Format Dinamis

Format dapat berubah selama streaming. Misalnya, rasio aspek dapat berubah di tengah aliran video.

Untuk detail tentang bagaimana perubahan aliran ditangani oleh MFT, lihat Menangani Perubahan Aliran.

Streaming Peristiwa

Untuk mengirim peristiwa ke MFT, panggil IMFTransform::P rocessEvent. Jika metode mengembalikan MF_S_TRANSFORM_DO_NOT_PROPAGATE_EVENT, MFT akan mengembalikan peristiwa ke pemanggil pada panggilan berikutnya ke ProcessOutput. Jika metode mengembalikan nilai HRESULT lainnya, MFT tidak akan mengembalikan peristiwa ke klien di ProcessOutput. Dalam hal ini, klien bertanggung jawab untuk menyebarkan peristiwa di hilir ke komponen berikutnya dalam alur, jika berlaku. Untuk informasi selengkapnya, lihat IMFTransform::P rocessOutput.

Transformasi Media Foundation