MFTs asinkron
Topik ini menjelaskan pemrosesan data asinkron untuk transformasi Media Foundation (MFTs).
Nota
Topik ini berlaku untuk Windows 7 atau yang lebih baru.
- Tentang MFTs Asinkron
- Persyaratan Umum
- Peristiwa
- ProcessInput
- ProcessOutput
- Pengurasan
- Flushing
- Penanda
- Format Perubahan
- Atribut
- Membuka kunci MFT Asinkron
- Mematikan MFT
- Pendaftaran dan Enumerasi
- Topik terkait
Tentang MFTs Asinkron
Ketika MFTs diperkenalkan di Windows Vista, API dirancang untuk pemrosesan data sinkron. Dalam model itu, MFT selalu menunggu untuk mendapatkan input, atau menunggu untuk menghasilkan output.
Pertimbangkan dekoder video biasa. Untuk mendapatkan bingkai yang didekodekan, klien memanggil IMFTransform::P rocessOutput. Jika dekoder memiliki data yang cukup untuk mendekode bingkai, ProcessOutput memblokir saat MFT mendekode bingkai. Jika tidak, ProcessOutput mengembalikan MF_E_TRANSFORM_NEED_MORE_INPUT, yang menunjukkan bahwa klien harus memanggil IMFTransform::P rocessInput.
Model ini berfungsi dengan baik jika dekoder melakukan semua operasi decoding-nya pada satu utas. Tetapi misalkan dekoder menggunakan beberapa utas untuk mendekode bingkai secara paralel. Untuk performa terbaik, dekoder harus menerima input baru setiap kali utas decoding menjadi menganggur. Tetapi tingkat di mana utas menyelesaikan operasi decoding tidak akan selaras dengan panggilan klien untuk ProcessInput dan ProcessOutput, yang mengakibatkan utas menunggu pekerjaan.
Windows 7 memperkenalkan pemrosesan asinkron berbasis peristiwa, untuk MFTs. Dalam model ini, setiap kali MFT membutuhkan input atau memiliki output, MFT mengirimkan peristiwa ke klien.
Persyaratan Umum
Topik ini menjelaskan bagaimana MFT asinkron berbeda dari MFT sinkron. Kecuali jika dicatat dalam topik ini, dua model pemrosesan sama. (Khususnya, negosiasi format sama.)
MFT asinkron harus menerapkan antarmuka berikut:
- IMFTransform
- IMFMediaEventGenerator
- IMFShutdown
Peristiwa
MFT asinkron menggunakan peristiwa berikut untuk memberi sinyal status pemrosesan datanya:
Peristiwa | Deskripsi |
---|---|
METransformNeedInput | Dikirim ketika MFT dapat menerima lebih banyak input. |
METransformHaveOutput | Dikirim ketika MFT memiliki output. |
METransformDrainComplete | Dikirim saat operasi pengurasan selesai. Lihat Pengurasan. |
METransformMarker | Dikirim saat penanda sedang diproses. Lihat Penanda. |
Peristiwa ini dikirim di luar band. Penting untuk memahami perbedaan antara peristiwa dalam band dan out-of-band dalam konteks MFT.
Desain MFT asli mendukung peristiwa dalam band. Peristiwa dalam band berisi informasi tentang aliran data, seperti informasi tentang perubahan format. Klien mengirim peristiwa dalam band ke MFT dengan memanggil IMFTransform::P rocessEvent. MFT dapat mengirim peristiwa dalam band kembali ke klien dalam metodeProcessOutput. (Secara khusus, peristiwa disampaikan dalam pEvents anggota struktur MFT_OUTPUT_DATA_BUFFER.)
MFT mengirimkan peristiwa di luar band melalui antarmukaIMFMediaEventGeneratorsebagai berikut:
- MFT mengimplementasikan antarmukaIMFMediaEventGenerator, seperti yang dijelaskan dalam Media Event Generators.
- Klien memanggil IUnknown::QueryInterface pada MFT untuk antarmukaIMFMediaEventGenerator. MFT asinkron harus mengekspos antarmuka ini. MFTs sinkron tidak boleh mengekspos antarmuka ini.
- Klien memanggil IMFMediaEventGenerator::BeginGetEvent dan IMFMediaEventGenerator::EndGetEvent untuk menerima peristiwa di luar band dari MFT.
ProcessInput
MetodeIMFTransform::P rocessInputdimodifikasi sebagai berikut:
- Saat streaming dimulai, klien mengirim pesan MFT_MESSAGE_NOTIFY_START_OF_STREAM.
- Selama streaming, MFT meminta data dengan mengirim peristiwa METransformNeedInput. Data peristiwa adalah pengidentifikasi aliran.
- Untuk setiap peristiwa METransformNeedInput, klien memanggil ProcessInput untuk aliran yang ditentukan.
- Di akhir streaming, klien dapat memanggil ProcessMessage dengan pesan MFT_MESSAGE_NOTIFY_END_OF_STREAM.
Catatan implementasi:
- MFT tidak boleh mengirim peristiwa METransformNeedInput hingga menerima pesan MFT_MESSAGE_NOTIFY_START_OF_STREAM.
- Selama streaming, MFT dapat mengirim meTransformNeedInput peristiwa kapan saja.
- MFT harus mempertahankan hitungan peristiwa METransformNeedInput yang tertunda. Setiap panggilan keProcessInputyang tidak sesuai dengan peristiwa METransformNeedInput harus mengembalikan MF_E_NOTACCEPTING.
- Saat MFT menerima pesan MFT_MESSAGE_NOTIFY_END_OF_STREAM, MFT mengatur ulang jumlah peristiwa METransformNeedInput yang tertunda menjadi nol.
- MFT tidak boleh mengirim peristiwa METransformNeedInput setelah menerima pesan MFT_MESSAGE_NOTIFY_END_OF_STREAM.
- Jika ProcessInput dipanggil sebelum MFT_MESSAGE_NOTIFY_START_OF_STREAM atau setelah MFT_MESSAGE_NOTIFY_END_OF_STREAM, metode harus mengembalikan MF_E_NOTACCEPTING.
ProcessOutput
Metode IMFTransform::P rocessOutput dimodifikasi sebagai berikut:
- Setiap kali MFT memiliki output, MFT mengirimkan peristiwa METransformHaveOutput.
- Untuk setiap peristiwa METransformHaveOutput, klien memanggil ProcessOutput.
Catatan implementasi:
- Jika klien memanggilProcessOutputdi lain waktu, metode mengembalikan E_UNEXPECTED.
- MFT asinkron tidak boleh mengembalikan MF_E_TRANSFORM_NEED_MORE_INPUT dari metodeProcessOutput. Jika MFT memerlukan lebih banyak input, MFT akan mengirim peristiwa METransformNeedInput.
Pengeringan
Menguras MFT menyebabkan MFT menghasilkan output sebanyak mungkin dari data input apa pun yang telah dikirim. Menguras MFT asinkron berfungsi sebagai berikut:
- Klien mengirim pesan MFT_MESSAGE_COMMAND_DRAIN.
- MFT terus mengirim peristiwa METransformHaveOutput hingga tidak memiliki data lagi untuk diproses. Ini tidak mengirim meTransformNeedInput peristiwa selama waktu ini.
- Setelah MFT mengirimkan peristiwa METransformHaveOutput terakhir, MFT mengirimkan peristiwa METransformDrainComplete.
Setelah pengurasan selesai, MFT tidak mengirim peristiwa METransformNeedInput lain hingga menerima pesan MFT_MESSAGE_NOTIFY_START_OF_STREAM dari klien.
Pembilasan
Klien dapat menghapus MFT dengan mengirim pesan MFT_MESSAGE_COMMAND_FLUSH. MFT menghilangkan semua sampel input dan output yang dipegangnya.
MFT tidak mengirim peristiwa METransformNeedInput lain hingga menerima pesan MFT_MESSAGE_NOTIFY_START_OF_STREAM dari klien.
Spidol
Klien dapat menandai titik dalam aliran dengan mengirim pesan MFT_MESSAGE_COMMAND_MARKER. MFT merespons sebagai berikut:
- MFT menghasilkan sampel output sebanyak mungkin dari data input yang ada, mengirim peristiwa METransformHaveOutput untuk setiap sampel output.
- Setelah semua output dihasilkan, MFT mengirimkan peristiwa METransformMarker. Kejadian ini harus dikirim setelah semua peristiwa METransformHaveOutput.
Misalnya, misalkan dekoder memiliki data input yang cukup untuk menghasilkan empat sampel output. Jika klien mengirim pesan MFT_MESSAGE_COMMAND_MARKER, MFT akan mengantre empat peristiwa METransformHaveOutput (satu per sampel output), diikuti oleh peristiwa METransformMarker.
Pesan penanda mirip dengan pesan pengurasan. Namun, pengosongan dianggap sebagai jeda di aliran, sedangkan penanda tidak. Pengurasan dan penanda memiliki perbedaan berikut.
Pengeringan:
- Saat menguras, MFT tidak mengirim peristiwa METransformNeedInput.
- MFT membuang data input apa pun yang tidak dapat digunakan untuk membuat sampel output.
- Beberapa MFT menghasilkan "ekor" di akhir data. Misalnya, efek audio seperti gaung atau gema menghasilkan data tambahan setelah data input berhenti. MFT yang menghasilkan ekor harus melakukannya di akhir operasi pengurasan.
- Setelah MFT selesai dikuras, MFT menandai sampel output berikutnya dengan atribut MFSampleExtension_Discontinuity, untuk menunjukkan penghentian dalam aliran.
Penanda:
- MFT terus mengirim peristiwa METransformNeedInput sebelum mengirim peristiwa penanda.
- MFT tidak membuang data input apa pun. Jika ada data parsial, data harus diproses setelah titik penanda.
- MFT tidak menghasilkan ekor pada titik penanda.
- MFT tidak mengatur bendera penghentian setelah titik penanda.
Format Perubahan
MFT asinkron harus mendukung perubahan format dinamis, seperti yang dijelaskan dalam Menangani Perubahan Aliran.
Atribut
MFT asinkron harus menerapkan metode IMFTransform::GetAttributes untuk mengembalikan penyimpanan atribut yang valid. Atribut berikut berlaku untuk MFTs asinkron:
Atribut | Deskripsi |
---|---|
MF_TRANSFORM_ASYNC | MFT harus mengatur atribut ini ke TRUE (1). Klien dapat mengkueri atribut ini untuk menemukan apakah MFT tidak sinkron. |
MF_TRANSFORM_ASYNC_UNLOCK | |
MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE | MFT harus mengatur atribut ini ke TRUE (1). Klien dapat mengasumsikan bahwa atribut ini diatur. |
Membuka kunci MFT Asinkron
MFTs asinkron tidak kompatibel dengan model pemrosesan data MFT asli. Untuk mencegah MFTs asinkron merusak aplikasi yang ada, mekanisme berikut didefinisikan:
- Klien memanggil IMFTransform::GetAttributes di MFT.
Klien meminta atribut MF_TRANSFORM_ASYNC ini. Untuk MFT asinkron, nilai atribut ini adalah **TRUE**.
Untuk membuka kunci MFT, klien harus mengatur atribut MF_TRANSFORM_ASYNC_UNLOCK ke **TRUE**.
Hingga klien membuka kunci MFT, semua metode IMFTransform harus mengembalikan MF_E_TRANSFORM_ASYNC_LOCKED, dengan pengecualian berikut:
- IMFTransform::GetAttributes (semua MFTs asinkron)
- IMFTransform::GetInputAvailableType (semua MFTs asinkron)
- IMFTransform::GetOutputCurrentType (hanya encoder)
- IMFTransform::SetOutputType (hanya encoder)
- IMFTransform::GetStreamCount (semua MFTs asinkron)
- IMFTransform::GetStreamIDs (semua MFTs asinkron)
Kode berikut menunjukkan cara membuka kunci MFT asinkron:
HRESULT UnlockAsyncMFT(IMFTransform *pMFT)
{
IMFAttributes *pAttributes = NULL;
HRESULT hr = hr = pMFT->GetAttributes(&pAttributes);
if (SUCCEEDED(hr))
{
hr = pAttributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
pAttributes->Release();
}
return hr;
}
Mematikan MFT
MFTs asinkron harus mengimplementasikan antarmukaIMFShutdown.
- Matikan: MFT harus mematikan antrean peristiwanya. Jika menggunakan antrean peristiwa standar, panggil IMFMediaEventQueue::Shutdown. Secara opsional, MFT dapat merilis sumber daya lain. Klien tidak boleh menggunakan MFT setelah memanggil Matikan.
- GetShutdownStatus: SetelahMatikandipanggil, MFT harus mengembalikan nilai MFSHUTDOWN_COMPLETED dalam parameter pStatus. Ini tidak boleh mengembalikan nilai MFSHUTDOWN_INITIATED.
Pendaftaran dan Enumerasi
Untuk mendaftarkan MFT asinkron, panggil fungsiMFTRegister dan atur bendera MFT_ENUM_FLAG_ASYNCMFT di parameter Bendera. (Sebelumnya bendera ini dicadangkan.)
Untuk menghitung MFT asinkron, panggil fungsiMFTEnumExdan atur bendera MFT_ENUM_FLAG_ASYNCMFT di parameter Bendera. Untuk kompatibilitas mundur, fungsi MFTEnum tidak menghitung MFT asinkron. Jika tidak, menginstal MFT asinkron di komputer pengguna dapat merusak aplikasi yang ada.
Topik terkait