Bagikan melalui


Sampel dan Alokator

[Fitur yang terkait dengan halaman ini, DirectShow, adalah fitur warisan. Ini telah digantikan oleh MediaPlayer, IMFMediaEngine, dan Tangkapan 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 Audio/Video Capture 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, ini memberikan penunjuk 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::Receive 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 untuk memblokir dalam metode Terima , jika perlu menunggu sumber daya.

Objek COM lain, yang disebut alokator, bertanggung jawab untuk membuat dan mengelola sampel media. Alokator mengekspos 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 detailnya, lihat Cara Filter Menyambungkan dan Menegosiasikan Alokator.)

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

sampel media dan alokator

Jumlah Referensi Sampel Media

Alokator membuat kumpulan sampel terbatas. Kapan saja, beberapa sampel mungkin 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, tempat sampel 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, misalkan pin input menerima sampel. Jika memproses sampel secara sinkron, di dalam metode Terima , sampel tidak akan menaikkan jumlah referensi. Setelah Terima kembali, pin output merilis sampel, jumlah referensi masuk ke nol, dan sampel kembali ke kumpulan alokator. Di sisi lain, jika pin input memproses sampel pada utas pekerja, itu 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, alur tersebut memanggil Rilis untuk membebaskan sampel. Sekarang sampel kembali ke kumpulan.

Saat pin menerima sampel, pin dapat menyalin data ke sampel lain, atau dapat mengubah sampel asli dan mengirimkannya ke filter berikutnya. Kemungkinan, sampel dapat melakukan perjalanan 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 dilakukan jika memperluas data input (misalnya, dengan mendekompresinya). Jika output tidak lebih besar dari input, filter mungkin memproses data di tempatnya, 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 memesan buffer memori apa pun. Pada titik ini, setiap panggilan ke metode GetBuffer akan gagal. Saat streaming dimulai, pin output memanggil IMemAllocator::Commit, yang menerapkan alokator, menyebabkannya mengalokasikan memori. Pin sekarang dapat memanggil GetBuffer.

Saat streaming berhenti, pin memanggil IMemAllocator::D ecommit, yang menonaktifkan alokator. Semua panggilan berikutnya ke GetBuffer gagal sampai alokator diterapkan lagi. Selain itu, jika ada panggilan ke GetBuffer yang saat ini diblokir menunggu sampel, mereka segera mengembalikan kode kegagalan. Metode Decommit mungkin atau mungkin tidak membebaskan memori, tergantung pada implementasinya. Misalnya, kelas CMemAllocator menunggu sampai metode destruktornya untuk membebaskan memori.

Aliran Data di Grafik Filter