MFTs asinkron
Topik ini menjelaskan pemrosesan data asinkron untuk transformasi Media Foundation (MFTs).
Catatan
Topik ini berlaku untuk Windows 7 atau yang lebih baru.
- Tentang MFTs Asinkron
- Persyaratan umum
- Peristiwa
- ProcessInput
- ProcessOutput
- Pengurasan
- Pembilasan
- Penanda
- Format Perubahan
- Atribut
- Membuka kunci MFT Asinkron
- Mematikan MFT
- Pendaftaran dan Enumerasi
- Topik terkait
Tentang MFTs Asinkron
Ketika MFT 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, menunjukkan bahwa klien harus memanggil IMFTransform::P rocessInput.
Model ini bekerja dengan baik jika dekoder melakukan semua operasi pendekodeannya 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 ke ProcessInput dan ProcessOutput, yang mengakibatkan utas menunggu pekerjaan.
Windows 7 memperkenalkan pemrosesan asinkron berbasis peristiwa untuk MFT. 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, kedua model pemrosesan sama. (Khususnya, negosiasi format sama.)
MFT asinkron harus mengimplementasikan antarmuka berikut:
Acara
MFT asinkron menggunakan peristiwa berikut untuk menandakan status pemrosesan datanya:
Kejadian | Deskripsi |
---|---|
METransformNeedInput | Dikirim ketika MFT dapat menerima lebih banyak input. |
METransformHaveOutput | Dikirim ketika MFT memiliki output. |
METransformDrainComplete | Dikirim ketika 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 in-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 metode ProcessOutput . (Secara khusus, peristiwa disampaikan dalam anggota pEvents dari struktur MFT_OUTPUT_DATA_BUFFER .)
MFT mengirimkan peristiwa out-of-band melalui antarmuka IMFMediaEventGenerator sebagai berikut:
- MFT mengimplementasikan antarmuka IMFMediaEventGenerator , seperti yang dijelaskan dalam Generator Peristiwa Media.
- Klien memanggil IUnknown::QueryInterface pada MFT untuk antarmuka IMFMediaEventGenerator . MFT asinkron harus mengekspos antarmuka ini. MFT sinkron tidak boleh mengekspos antarmuka ini.
- Klien memanggil IMFMediaEventGenerator::BeginGetEvent dan IMFMediaEventGenerator::EndGetEvent untuk menerima peristiwa di luar band dari MFT.
ProcessInput
Metode IMFTransform::P rocessInput dimodifikasi 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 peristiwa METransformNeedInput kapan saja.
- MFT harus mempertahankan hitungan peristiwa METransformNeedInput yang tertunda . Setiap panggilan ke ProcessInput yang tidak sesuai dengan peristiwa METransformNeedInput harus mengembalikan MF_E_NOTACCEPTING.
- Ketika 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 memanggil ProcessOutput di lain waktu, metode akan mengembalikan E_UNEXPECTED.
- MFT asinkron tidak boleh mengembalikan MF_E_TRANSFORM_NEED_MORE_INPUT dari metode ProcessOutput . Jika MFT memerlukan lebih banyak input, MFT akan mengirimkan peristiwa METransformNeedInput .
Pengurasan
Menguras MFT menyebabkan MFT menghasilkan output sebanyak mungkin dari data input apa pun yang telah dikirim. Pengurasan MFT asinkron berfungsi sebagai berikut:
- Klien mengirim pesan MFT_MESSAGE_COMMAND_DRAIN .
- MFT terus mengirim peristiwa METransformHaveOutput sampai tidak memiliki data lagi untuk diproses. Ini tidak mengirim peristiwa METransformNeedInput selama waktu ini.
- Setelah MFT mengirimkan peristiwa METransformHaveOutput terakhir, MFT mengirimkan peristiwa METransformDrainComplete .
Setelah pengurasan selesai, MFT tidak mengirim peristiwa METransformNeedInput lain sampai 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 sampai menerima pesan MFT_MESSAGE_NOTIFY_START_OF_STREAM dari klien.
Penanda
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 dalam 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 menguras, 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 sebagian data, 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 MFTs Asinkron
MFT asinkron tidak kompatibel dengan model pemrosesan data MFT asli. Untuk mencegah MFT asinkron merusak aplikasi yang ada, mekanisme berikut didefinisikan:
- Klien memanggil IMFTransform::GetAttributes pada MFT.
Klien meminta untuk 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
MFT asinkron harus mengimplementasikan antarmuka IMFShutdown .
- 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: Setelah Shutdown dipanggil, MFT harus mengembalikan nilai yang MFSHUTDOWN_COMPLETED dalam parameter pStatus . Ini tidak boleh mengembalikan nilai MFSHUTDOWN_INITIATED.
Pendaftaran dan Enumerasi
Untuk mendaftarkan MFT asinkron, panggil fungsi MFTRegister dan atur bendera MFT_ENUM_FLAG_ASYNCMFT di parameter Bendera . (Sebelumnya bendera ini dicadangkan.)
Untuk menghitung MFTs asinkron, panggil fungsi MFTEnumEx dan atur bendera MFT_ENUM_FLAG_ASYNCMFT di parameter Bendera . Untuk kompatibilitas mundur, fungsi MFTEnum tidak menghitung MFTs asinkron. Jika tidak, menginstal MFT asinkron pada komputer pengguna dapat merusak aplikasi yang ada.
Topik terkait