Sampel dan Alokator

[Fitur yang terkait dengan halaman ini, DirectShow, adalah fitur warisan. Ini telah digantikan oleh MediaPlayer, IMFMediaEngine, dan Pengambilan Audio /Video di Media Foundation. Fitur-fitur tersebut telah dioptimalkan untuk Windows 10 dan Windows 11. Microsoft sangat menyarankan agar kode baru menggunakan MediaPlayer, IMFMediaEngine dan Pengambilan Audio/Video di Media Foundation alih-alih DirectShow, jika memungkinkan. Microsoft menyarankan agar kode yang ada yang menggunakan API warisan ditulis ulang untuk menggunakan API baru jika memungkinkan.]

Saat pin mengirimkan data media ke pin lain, pin tidak meneruskan penunjuk langsung ke buffer memori. Sebaliknya, ia mengirimkan pointer ke objek COM yang mengelola memori. Objek ini, yang disebut sampel media, mengekspos antarmuka IMediaSample. Pin penerima mengakses buffer memori dengan memanggil metode IMediaSample, seperti IMediaSample::GetPointer, IMediaSample::GetSize, dan IMediaSample::GetActualDataLength.

Sampel selalu melakukan perjalanan hilir, dari pin output hingga pin input. Dalam model pendorongan, pin output memberikan sampel dengan memanggil IMemInputPin::Terima pada pin input. Pin input akan memproses data secara sinkron (yaitu, sepenuhnya di dalam metode Terima), atau memprosesnya secara asinkron pada utas pekerja. Pin input diizinkan memblokir dalam metode Terima , jika perlu menunggu ketersediaan sumber daya.

Objek COM lain, yang disebut alokator , bertanggung jawab untuk membuat dan mengelola sampel media. Alokator menyediakan antarmuka IMemAllocator. Setiap kali filter membutuhkan sampel media dengan buffer kosong, filter memanggil metode IMemAllocator::GetBuffer, yang mengembalikan pointer ke sampel. Setiap koneksi pin berbagi satu alokator. Ketika dua pin terhubung, mereka memutuskan filter mana yang akan menyediakan alokator. Pin juga mengatur properti pada alokator, seperti jumlah buffer dan ukuran setiap buffer. (Untuk informasi lebih lanjut, lihat Bagaimana Filter Terhubung dan Bernegosiasi tentang Alokator.)

Ilustrasi berikut menunjukkan hubungan di antara alokator, sampel media, dan filter.

sampel media dan pengalokasi

Jumlah Referensi Sampel Media

Alokator membuat kumpulan sampel terbatas. Pada kapan saja, beberapa sampel mungkin sedang digunakan, sementara yang lain tersedia untuk panggilan GetBuffer. Alokator menggunakan penghitungan referensi untuk melacak sampel. Metode GetBuffer mengembalikan sampel dengan jumlah referensi 1. Jika jumlah referensi masuk ke nol, sampel kembali ke kumpulan alokator, di mana dapat digunakan dalam panggilan GetBuffer berikutnya. Selama jumlah referensi tetap di atas nol, sampel tidak tersedia untuk GetBuffer. Jika setiap sampel milik alokator sedang digunakan, metode GetBuffer memblokir hingga sampel tersedia.

Misalnya, pin input menerima sampel. Jika memproses sampel secara sinkron, di dalam fungsi Terima, tidak menaikkan jumlah referensi. Setelah menerima pengembalian, pin keluaran melepaskan sampel, hitungan referensi menjadi nol, dan sampel kembali ke kolam alokator. Di sisi lain, jika pin input memproses sampel pada utas pekerja, ia akan menaikkan jumlah referensi sebelum meninggalkan metode Terima. Jumlah referensi sekarang 2. Saat pin output merilis sampel, jumlahnya masuk ke 1; sampel belum kembali ke kumpulan. Setelah utas pekerja selesai dengan sampel, ia memanggil Release untuk membebaskan sampel. Sekarang sampel kembali ke kolam.

Saat pin menerima sampel, pin dapat menyalin data ke sampel lain, atau dapat memodifikasi sampel asli dan mengirimkannya ke filter berikutnya. Berpotensi, sampel dapat menelusuri seluruh panjang grafik, setiap filter memanggil AddRef dan Rilis secara bergantian. Oleh karena itu, pin output tidak boleh menggunakan kembali sampel setelah memanggil Terima, karena filter hilir mungkin menggunakan sampel. Pin output harus selalu memanggil GetBuffer untuk mendapatkan sampel baru.

Mekanisme ini mengurangi jumlah alokasi memori, karena filter menggunakan kembali buffer yang sama. Ini juga mencegah filter secara tidak sengaja menulis melalui data yang belum diproses, karena alokator mempertahankan daftar sampel yang tersedia.

Filter dapat menggunakan alokator terpisah untuk input dan output. Ini mungkin melakukan ini jika memperluas data input (misalnya, dengan mendekompresinya). Jika output tidak lebih besar dari input, filter mungkin memproses data di tempat, tanpa menyalinnya ke sampel baru. Dalam hal ini, dua atau beberapa koneksi pin dapat berbagi satu alokator.

Menerapkan dan Menonaktifkan Alokator

Ketika filter pertama kali membuat alokator, alokator belum menyediakan buffer memori apa pun. Pada titik ini, setiap panggilan ke metode GetBuffer akan gagal. Saat streaming dimulai, pin output memanggil IMemAllocator::Commit, yang menginisiasi alokator, menyebabkannya mengalokasikan memori. Pin sekarang dapat memanggil GetBuffer.

Saat streaming berhenti, pin memanggil IMemAllocator::Decommit, yang melepaskan alokator. Semua panggilan berikutnya ke GetBuffer gagal hingga alokator dikomitmenkan lagi. Selain itu, jika ada panggilan ke GetBuffer yang saat ini diblokir karena menunggu sampel, panggilan tersebut segera menghasilkan kode kesalahan. Metode Decommit dapat atau mungkin tidak membebaskan memori, tergantung pada implementasinya. Misalnya, kelas CMemAllocator menunggu hingga menjalankan metode destruktornya untuk membebaskan memori.

Aliran Data di Grafik Filter