Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Artikel ini menjelaskan streaming dan buffering ACX, yang sangat penting untuk pengalaman audio bebas kesalahan. Ini menjelaskan bagaimana driver mengkomunikasikan status aliran dan mengelola buffer aliran. Untuk daftar istilah audio ACX umum dan pengenalan ACX, lihat Ringkasan ekstensi kelas audio ACX.
Jenis streaming ACX
AcxStream mewakili aliran audio pada perangkat keras sirkuit tertentu. AcxStream dapat menggabungkan satu atau beberapa objek seperti AcxElements.
ACX mendukung dua jenis aliran. Jenis streaming pertama, RT Packet Stream, memungkinkan Anda mengalokasikan paket RT dan menggunakannya untuk mentransfer data audio ke atau dari perangkat keras perangkat keras, bersama dengan transisi status aliran. Jenis aliran kedua, aliran dasar, hanya mendukung transisi status aliran.
Pada satu ujung sirkuit, sirkuit tersebut adalah sirkuit streaming yang membentuk Aliran Paket RT. Jika dua sirkuit atau lebih terhubung untuk membuat titik akhir, sirkuit pertama di titik akhir adalah sirkuit streaming dan membuat Aliran Paket RT. Sirkuit yang terhubung membuat Aliran Dasar untuk menerima peristiwa yang terkait dengan transisi status streaming.
Untuk informasi selengkapnya, lihat Acx Stream di Ringkasan Objek ACX. DDI untuk aliran didefinisikan dalam header acxstreams.h .
Tumpukan komunikasi streaming ACX
Ada dua jenis komunikasi untuk streaming ACX. Satu jalur komunikasi mengontrol perilaku streaming. Misalnya, perintah seperti Mulai, Buat, dan Alokasikan, yang menggunakan komunikasi ACX standar. Kerangka kerja ACX menggunakan antrean IO dan menyalurkan permintaan WDF melalui antrean. Perilaku antrean disembunyikan dari kode driver sebenarnya dengan menggunakan panggilan balik peristiwa dan fungsi ACX. Driver juga diberi kesempatan untuk melakukan praprosem semua permintaan WDF.
Jalur komunikasi kedua dan yang lebih menarik menangani sinyal streaming audio. Sinyal melibatkan memberi tahu driver ketika paket siap dan menerima data dan ketika driver selesai memproses paket.
Persyaratan utama untuk sinyal streaming:
- Mendukung pemutaran lancar
- Latensi rendah
- Kunci yang diperlukan terbatas pada aliran yang bersangkutan
- Kemudahan penggunaan untuk pengembang driver
Untuk berkomunikasi dengan penggerak guna memberi sinyal status streaming, ACX menggunakan event dengan buffer bersama dan panggilan IRP langsung. Teknik-teknik ini dijelaskan selanjutnya.
Buffer berbagi
Buffer dan peristiwa bersama berkomunikasi dari driver ke klien. Buffer peristiwa dan bersama memastikan klien tidak perlu menunggu atau melakukan polling. Klien dapat menentukan semua yang diperlukan untuk melanjutkan streaming sambil mengurangi atau menghilangkan kebutuhan akan panggilan IRP langsung.
Driver perangkat menggunakan buffer bersama untuk berkomunikasi kepada klien mengenai paket mana yang sedang dirender atau diambil. Buffer bersama ini mencakup jumlah paket (berbasis satu) dari paket terakhir yang diselesaikan bersama dengan nilai QPC (QueryPerformanceCounter) dari waktu penyelesaian. Untuk driver perangkat, ini harus menunjukkan informasi ini dengan memanggil AcxRtStreamNotifyPacketComplete. Ketika driver perangkat memanggil AcxRtStreamNotifyPacketComplete, kerangka kerja ACX memperbarui buffer bersama dengan jumlah paket baru dan QPC dan memberi sinyal peristiwa yang dibagikan dengan klien untuk menunjukkan bahwa klien dapat membaca jumlah paket baru.
Panggilan IRP langsung
Panggilan IRP langsung berkomunikasi dari klien ke driver.
Klien dapat meminta jumlah paket saat ini, atau menunjukkan jumlah paket saat ini ke driver perangkat kapan saja. Permintaan ini memanggil penanganan aktivitas driver perangkat EvtAcxStreamGetCurrentPacket dan EvtAcxStreamSetRenderPacket . Klien juga dapat meminta paket pengambilan saat ini, yang memanggil penanganan aktivitas driver perangkat EvtAcxStreamGetCapturePacket .
Kesamaan dengan PortCls
Kombinasi panggilan IRP langsung dan buffer bersama yang digunakan ACX mirip dengan cara PortCls berkomunikasi penanganan penyelesaian buffer.
Untuk mencegah kesalahan, driver harus memastikan tidak melakukan apa pun yang memerlukan akses ke kunci yang juga digunakan di jalur kontrol aliran.
Dukungan buffer besar untuk pemutaran daya rendah
Untuk mengurangi konsumsi daya selama pemutaran, kurangi waktu yang dihabiskan APU dalam keadaan daya tinggi. Karena pemutaran audio normal menggunakan buffer 10 ms, APU tetap aktif. Driver ACX dapat mengiklankan dukungan untuk buffer yang lebih besar, dalam rentang 1–2 detik, untuk membiarkan APU memasuki status daya yang lebih rendah.
Dalam model streaming yang ada, pemutaran offload mendukung pemutaran daya rendah. Driver audio mengiklankan dukungan untuk pemutaran offload dengan mengekspos simpul AudioEngine pada filter gelombang untuk titik akhir. Komponen AudioEngine menyediakan cara untuk mengontrol prosesor sinyal digital (DSP) yang digunakan driver untuk memroses audio dari buffer besar sesuai dengan pemrosesan yang diinginkan.
Simpul AudioEngine menyediakan fitur-fitur ini:
- Deskripsi Mesin Pemrosesan Audio memberi tahu tumpukan audio tentang pin pada filter gelombang yang menyediakan dukungan offload, loopback, dan pemutaran host.
- Rentang Ukuran Buffer menginformasikan tumpukan audio mengenai ukuran buffer minimum dan maksimum yang dapat didukung untuk offload. Pemutaran. Rentang Ukuran Buffer dapat berubah secara dinamis berdasarkan aktivitas sistem.
- Dukungan format, termasuk format yang didukung, format campuran pada perangkat saat ini, dan format perangkat.
- Volume, termasuk dukungan peningkatan bertahap, karena dengan penyangga yang lebih besar, volume perangkat lunak tidak akan responsif.
- Perlindungan Loopback Audio, yang memberi tahu driver untuk menonaktifkan pin loopback pada AudioEngine jika satu atau beberapa aliran yang dialihkan berisi konten yang dilindungi.
- Status FX global, untuk mengaktifkan atau menonaktifkan GFX pada AudioEngine.
Saat Anda membuat stream pada pin offload, stream tersebut mendukung volume, efek lokal, dan perlindungan loopback.
Pemutaran berdaya rendah dengan ACX
Kerangka kerja ACX menggunakan model yang sama untuk pemutaran daya rendah. Driver membuat tiga objek ACXPIN terpisah untuk host, offload, dan loopback streaming, bersama dengan elemen ACXAUDIOENGINE yang menjelaskan pin mana yang digunakan untuk host, offload, dan loopback. Driver menambahkan pin dan elemen ACXAUDIOENGINE ke ACXCIRCUIT selama pembuatan sirkuit.
Pembuatan aliran yang didelegasikan
Driver juga menambahkan elemen ACXAUDIOENGINE ke aliran yang dibuat untuk offload untuk memungkinkan kontrol atas volume, bisu, dan pengukur puncak suara.
Diagram aliran
Diagram ini menunjukkan driver ACX berlapis-ganda.
Setiap driver ACX mengontrol bagian terpisah dari perangkat keras audio, yang mungkin berasal dari vendor yang berbeda. ACX menyediakan antarmuka streaming kernel yang kompatibel sehingga aplikasi berjalan tanpa perubahan.
Pin aliran
Setiap ACXCIRCUIT memiliki setidaknya satu Pin Sink dan satu Pin Sumber. Pin ini digunakan oleh kerangka ACX untuk memperlihatkan koneksi sirkuit ke tumpukan audio. Untuk sirkuit Render, Pin Sumber digunakan untuk mengontrol perilaku render aliran apa pun yang dibuat dari sirkuit. Untuk sirkuit capture, Sink Pin digunakan untuk mengontrol perilaku penangkapan aliran apapun yang dihasilkan dari sirkuit.
ACXPIN adalah objek yang digunakan untuk mengontrol streaming di Jalur Audio. ACXCIRCUIT streaming bertanggung jawab untuk membuat objek ACXPIN yang sesuai untuk Jalur Audio Titik Akhir pada waktu pembuatan sirkuit dan mendaftarkan ACXPIN dengan ACX. ACXCIRCUIT hanya membuat pin render atau pin penangkapan untuk sirkuit. Kerangka kerja ACX membuat pin lain yang diperlukan untuk terhubung dan berkomunikasi dengan sirkuit.
Rangkaian streaming
Ketika titik akhir terdiri dari satu sirkuit, sirkuit itu adalah sirkuit streaming.
Ketika titik akhir terdiri dari lebih dari satu sirkuit yang dibuat oleh satu atau beberapa driver perangkat, ACXCOMPOSITETEMPLATE yang menjelaskan titik akhir gabungan menentukan urutan spesifik penghubung antar sirkuit. Sirkuit pertama di titik akhir adalah sirkuit streaming untuk titik akhir.
Sirkuit streaming harus menggunakan AcxRtStreamCreate untuk membuat Aliran Paket RT sebagai respons terhadap EvtAcxCircuitCreateStream. ACXSTREAM yang dibuat dengan AcxRtStreamCreate memungkinkan driver sirkuit streaming untuk mengalokasikan buffer yang digunakan untuk streaming dan mengontrol aliran streaming sebagai respons terhadap kebutuhan klien dan perangkat keras.
Sirkuit berikut di titik akhir harus menggunakan AcxStreamCreate untuk membuat Aliran Dasar sebagai respons terhadap EvtAcxCircuitCreateStream. Objek ACXSTREAM yang dibuat dengan AcxStreamCreate oleh sirkuit berikut memungkinkan driver mengonfigurasi perangkat keras sebagai respons terhadap perubahan status aliran seperti Jeda atau Jalankan.
ACXCIRCUIT streaming menerima permintaan pertama untuk membuat streaming. Permintaan mencakup perangkat, pin, dan format data (termasuk mode).
Setiap ACXCIRCUIT di Jalur Audio membuat objek ACXSTREAM yang mewakili instans aliran sirkuit. Kerangka kerja ACX menautkan objek ACXSTREAM bersama-sama, mirip dengan cara menautkan objek ACXCIRCUIT.
Sirkuit hulu dan hilir
Proses pembuatan aliran dimulai di sirkuit streaming dan diteruskan ke setiap sirkuit hilir sesuai urutan sirkuit terhubung. Koneksi dibuat di antara pin jembatan yang dibuat dengan Komunikasi yang sama dengan AcxPinCommunicationNone. Kerangka kerja ACX membuat satu atau beberapa pin jembatan untuk sirkuit jika driver tidak menambahkannya pada waktu pembuatan sirkuit.
Untuk setiap sirkuit yang dimulai dengan sirkuit streaming, pin jembatan AcxPinTypeSource akan terhubung ke sirkuit selanjutnya di hilir. Sirkuit terakhir memiliki pin endpoint yang menggambarkan perangkat keras endpoint audio (seperti apakah endpoint tersebut adalah Mikrofon atau Speaker dan apakah Jack terpasang).
Untuk setiap rangkaian setelah rangkaian streaming, pin jembatan AcxPinTypeSink terhubung ke rangkaian upstream berikutnya.
Negosiasi format aliran
Driver mengiklankan format yang didukung untuk pembuatan streaming dengan menambahkan format yang didukung per mode ke ACXPIN yang digunakan untuk pembuatan streaming dengan AcxPinAssignModeDataFormatList dan AcxPinGetRawDataFormatList. Untuk titik akhir multi sirkuit, ACXSTREAMBRIDGE dapat digunakan untuk mengoordinasikan mode dan memformat dukungan antara Sirkuit ACX. ACXPIN streaming yang dibuat oleh sirkuit streaming menentukan format aliran yang didukung untuk titik akhir. Format yang digunakan oleh sirkuit berikut ditentukan oleh pin jembatan sirkuit sebelumnya di titik akhir.
Secara default, kerangka kerja ACX membuat ACXSTREAMBRIDGE di antara setiap sirkuit di titik akhir multi sirkuit. ACXSTREAMBRIDGE default menggunakan format bawaan mode RAW dari pin jembatan sirkuit hulu ketika mengirimkan permintaan pembuatan aliran ke sirkuit hilir. Jika pin jembatan sirkuit upstream tidak memiliki format, format aliran asli digunakan. Jika pin yang terhubung dari sirkuit hilir tidak mendukung format yang digunakan, pembuatan aliran gagal.
Jika sirkuit perangkat melakukan perubahan format aliran, driver perangkat harus menambahkan format hilir pada pin jembatan hilir.
Pembuatan aliran
Langkah pertama dalam Pembuatan Aliran adalah membuat instans ACXSTREAM untuk setiap ACXCIRCUIT di Jalur Audio Titik Akhir. ACX memanggil EvtAcxCircuitCreateStream setiap sirkuit. ACX dimulai dengan sirkuit pertama dan memanggil EvtAcxCircuitCreateStream dari setiap sirkuit secara berurutan, diakhiri dengan sirkuit terakhir. Urutan dapat dibalik dengan menentukan bendera AcxStreamBridgeInvertChangeStateSequence (ditentukan dalam ACX_STREAM_BRIDGE_CONFIG_FLAGS) untuk Stream Bridge. Setelah semua sirkuit membuat objek stream, objek stream menangani logika streaming.
Permintaan Pembuatan Stream dikirim ke PIN yang sesuai yang dihasilkan sebagai bagian dari pembuatan topologi sirkuit kepala dengan memanggil EvtAcxCircuitCreateStream yang telah ditentukan saat pembuatan sirkuit kepala.
Sirkuit streaming adalah sirkuit upstream yang awalnya menangani permintaan pembuatan aliran.
- Pembaruan dilakukan pada struktur ACXSTREAM_INIT dengan menetapkan AcxStreamCallbacks dan AcxRtStreamCallbacks.
- Ini membuat objek ACXSTREAM menggunakan AcxRtStreamCreate
- Ini membuat elemen spesifik untuk aliran tertentu (misalnya, ACXVOLUME atau ACXAUDIOENGINE)
- Ini menambahkan elemen ke objek ACXSTREAM
- Ini mengembalikan objek ACXSTREAM yang dibuat ke kerangka kerja ACX
ACX kemudian meneruskan pembuatan aliran ke sirkuit hilir berikutnya.
- Ini memperbarui struktur ACXSTREAM_INIT, menetapkan AcxStreamCallbacks
- Ini membuat objek ACXSTREAM menggunakan AcxStreamCreate
- Ini membuat elemen spesifik untuk aliran
- Ini menambahkan elemen ke objek ACXSTREAM
- Ini mengembalikan objek ACXSTREAM yang dibuat ke kerangka kerja ACX
Saluran komunikasi antar sirkuit dalam jalur audio menggunakan objek ACXTARGETSTREAM. Setiap sirkuit memiliki akses ke Antrean IO untuk sirkuit di depannya dan sirkuit di belakangnya di Jalur Audio Titik Akhir. Jalur Audio Titik Akhir bersifat linier dan dua arah. Kerangka kerja ACX menangani pemrosesan Antrean IO yang sebenarnya.
Saat membuat objek ACXSTREAM, setiap sirkuit dapat menambahkan informasi Konteks ke objek ACXSTREAM untuk menyimpan dan melacak data privat untuk aliran.
Contoh render stream
Membuat aliran render pada Jalur Audio Titik Akhir yang terdiri dari tiga sirkuit: DSP, CODEC, dan AMP. Sirkuit DSP berfungsi sebagai sirkuit streaming, dan telah menyediakan handler EvtAcxPinCreateStream. Sirkuit DSP juga berfungsi sebagai sirkuit filter: tergantung pada mode streaming dan konfigurasi, sirkuit tersebut dapat menerapkan pemrosesan sinyal ke data audio. Sirkuit CODEC mewakili DAC, menyediakan fungsionalitas sink audio. Sirkuit AMP mewakili perangkat keras analog antara DAC dan speaker. Sirkuit AMP mungkin menangani deteksi jack atau detail perangkat keras titik akhir lainnya.
- AudioKSE memanggil NtCreateFile untuk membuat aliran.
- Ini memfilter melalui ACX dan diakhiri dengan memanggil sirkuit DSP EvtAcxPinCreateStream dengan pin, dataformat (termasuk mode), dan informasi perangkat.
- Sirkuit DSP memvalidasi informasi format data untuk memastikannya dapat menangani aliran yang dibuat.
- Sirkuit DSP membuat objek ACXSTREAM untuk mewakili aliran.
- Sirkuit DSP mengalokasikan struktur konteks privat dan mengaitkannya dengan ACXSTREAM.
- Sirkuit DSP mengembalikan alur eksekusi ke kerangka kerja ACX, yang kemudian memanggil ke sirkuit berikutnya di Jalur Audio Titik Akhir, sirkuit CODEC.
- Sirkuit CODEC memvalidasi informasi format data untuk mengonfirmasi dapat menangani penyajian data.
- Sirkuit CODEC mengalokasikan struktur konteks privat dan mengaitkannya dengan ACXSTREAM.
- Sirkuit CODEC menambahkan dirinya sebagai Stream Sink ke ACXSTREAM.
- Sirkuit CODEC mengembalikan alur eksekusi ke kerangka kerja ACX, yang kemudian memanggil ke sirkuit berikutnya di Jalur Audio Titik Akhir, sirkuit AMP.
- Sirkuit AMP mengalokasikan struktur konteks privat dan mengaitkannya dengan ACXSTREAM.
- Sirkuit AMP mengembalikan alur eksekusi ke kerangka kerja ACX. Pada titik ini, pembuatan aliran telah selesai.
Aliran buffer besar
Aliran buffer besar dibuat pada ACXPIN yang ditunjuk untuk Offload oleh elemen ACXCIRCUIT ACXAUDIOENGINE.
Untuk mendukung aliran offload, driver perangkat harus melakukan tindakan berikut selama pembuatan sirkuit streaming:
- Buat objek ACXPIN Host, Offload, dan Loopback dan tambahkan ke ACXCIRCUIT.
- Buat elemen ACXVOLUME, ACXMUTE, dan ACXPEAKMETER. Ini tidak akan ditambahkan langsung ke ACXCIRCUIT.
- Menginisialisasi struktur ACX_AUDIOENGINE_CONFIG, menetapkan objek HostPin, OffloadPin, LoopbackPin, VolumeElement, MuteElement, dan PeakMeterElement.
- Buat elemen ACXAUDIOENGINE.
Driver perlu melakukan langkah serupa untuk menambahkan elemen ACXSTREAMAUDIOENGINE saat membuat aliran pada pin Offload.
Pengalokasian sumber daya secara streaming
Model streaming untuk ACX berbasis paket, dengan dukungan untuk satu atau dua paket untuk streaming. Render atau Capture ACXPIN untuk sirkuit streaming diberikan permintaan untuk mengalokasikan paket memori yang digunakan dalam streaming. Untuk mendukung Penyeimbangan Ulang, memori yang dialokasikan harus memori sistem alih-alih memori perangkat yang dipetakan ke dalam sistem. Driver dapat menggunakan fungsi WDF yang ada untuk melakukan alokasi, dan mengembalikan array pointer ke alokasi buffer. Jika driver memerlukan satu blok yang berdampingan, driver dapat mengalokasikan kedua paket sebagai buffer tunggal. Paket kedua memiliki WdfMemoryDescriptorTypeInvalid dan offset paket kedua adalah ke dalam buffer yang dijelaskan oleh paket pertama.
Jika satu paket dialokasikan, driver harus mengalokasikan buffer yang selaras dengan halaman dengan panjang yang dapat dibagi halaman. Offset untuk paket tunggal juga harus 0. Kerangka kerja ACX memetakan paket ini ke mode pengguna dua kali, berturut-turut.
| paket 0 | paket 0 |
Ini memungkinkan GetBuffer mengembalikan penunjuk ke satu buffer memori berdampingan yang dapat mencakup dari akhir buffer ke awal tanpa memerlukan aplikasi untuk menangani pembungkusan akses memori.
Jika dua paket dialokasikan, paket tersebut dipetakan ke dalam mode pengguna:
| paket 0 | paket 1 |
Dengan streaming paket ACX awal, hanya ada dua paket yang dialokasikan di awal. Setelah alokasi dan pemetaan dilakukan, pemetaan memori virtual klien tetap valid, tanpa mengubah masa pakai aliran. Ada satu peristiwa terkait dengan aliran yang menunjukkan penyelesaian kedua paket. Ada juga buffer bersama yang digunakan kerangka kerja ACX untuk mengomunikasikan paket mana yang telah selesai dengan peristiwa tersebut.
Untuk PacketCount=1, jika aplikasi meminta 10 ms data, tumpukan audio mengirimkan permintaan untuk buffer 10 ms tunggal ke driver (tidak menggandakan ukuran buffer yang dikirim ke driver).
Driver mengalokasikan penyangga yang sejajar dengan halaman yang panjangnya setidaknya 10 milidetik. Untuk aliran 48k 2ch 2 byte per sampel, buffer terkecil yang digerakkan timer yang dapat dialokasikan adalah 1.024 sampel (satu halaman memori), yaitu 21.333 milidetik. Untuk stream 48k 8ch 2 byte per sampel, buffer terkecil yang dikendalikan oleh timer dan dapat dialokasikan adalah 512 sampel (satu halaman memori) atau 10,667 ms. Untuk aliran 48k 6ch dengan 2 byte per sampel, buffer terkecil yang digerakkan oleh timer tetap memiliki 1.024 sampel (tiga halaman memori, untuk memastikan akhir sampel selaras dengan akhir buffer), yaitu 21,333 ms.
Kerangka kerja ACX memetakan buffer yang selaras dengan halaman ini ke dalam proses mode pengguna dua kali, berturut-turut. Proses mode pengguna kemudian bisa menulis sejumlah data setara dengan ukuran buffer ke dalam pemetaan mode pengguna mulai dari mana saja di buffer tanpa harus melakukan pembungkusan.
Driver memanggil NotifyPacketComplete setelah membaca seluruh paket dari memori sistem, sehingga sistem tahu dapat menulis paket data audio berikutnya ke buffer paket.
Ada penundaan antara NotifyPacketComplete dan ketika sampel terakhir paket tersebut dirender. Penundaan ini dinyatakan sebagai hasil dari EvtAcxStreamGetHwLatency.
Ping-pong buffer
Buffer ping-pong dapat digunakan, di mana satu buffer sedang dibaca (ping), sementara yang lain sedang diisi (pong). Ini memungkinkan satu buffer diproses sementara yang lain mengumpulkan kumpulan data berikutnya. Di ACX, driver secara internal mengurus peralihan ketika buffer diisi. Setelah buffer ping terisi, akan diberitahukan dengan panggilan balik yang terdaftar. Dalam panggilan balik, alamat buffer yang diproses diperoleh, dan buffer dikirim ulang. Sementara, pong buffer mengumpulkan data di latar belakang. Mekanisme ini memastikan pemrosesan data berkelanjutan tanpa gangguan.
Untuk buffer ping-pong, ukuran paket yang diminta adalah untuk satu buffer (baik ping atau pong), dan jumlah paket adalah dua.
Saat berbagi buffer tunggal antara dua paket, konfigurasikan paket kedua seperti yang dijelaskan dalam fungsi panggilan balik EVT_ACX_STREAM_ALLOCATE_RTPACKETS. Bagian dari buffer yang dijelaskan oleh paket pertama (memori, offset, dan panjang) adalah buffer ping, sementara bagian yang dijelaskan oleh paket kedua (tidak ada memori untuk menunjukkan buffer dibagikan dengan paket pertama, ditambah offset yang menunjuk ke buffer tepat setelah paket pertama) adalah buffer pong.
Menambahkan informasi tambahan ke header paket
Anda hanya dapat menambahkan informasi tambahan ke informasi header paket, misalnya untuk pengelogan atau pembukuan, di awal paket untuk aliran berbasis peristiwa ping/pong (di mana jumlah paket = 2). Untuk stream berbasis timer dengan hanya satu paket, paket tersebut harus memiliki penjajaran halaman penuh (dimulai dan diakhiri pada batas halaman) karena paket dipetakan ke dalam mode pengguna dua kali.
Dalam kasus ini, aplikasi dapat menulis melewati batas akhir pemetaan pertama ke dalam pemetaan kedua, yang berarti menulis pada akhir buffer sistem, kemudian melanjutkan ke awal buffer sistem yang sama.
Buffer yang dialokasikan secara tunggal harus selaras halaman karena pemetaan memori virtual ke dalam mode pengguna dilakukan per halaman.
Buffer berbasis timer
Buffer berbasis timer di ACX dapat digunakan untuk memastikan pengalaman audio bebas glitch dengan mempertahankan waktu dan sinkronisasi yang tepat. Untuk buffer berbasis timer di ACX:
- Klien menggunakan nilai dari EvtAcxStreamGetPresentationPosition untuk menentukan berapa banyak bingkai yang dapat ditulis.
- Posisi presentasi perlu diperbarui lebih dari sekali setiap kali melewati buffer. Klien menulis ke buffer mulai dari posisi terakhir yang ditulis hingga posisi yang dilaporkan oleh driver (yang seharusnya adalah data yang telah digunakan oleh perangkat keras sejak terakhir kali posisi tersebut dikueri).
- Semakin terperinci posisinya, semakin kecil kemungkinan Anda mengalami gangguan.
- Dalam buffer berbasis timer, DSP tidak dapat hanya mengonsumsi seluruh buffer sebelum memperbarui posisi.
- Dalam mode yang digerakkan oleh timer, driver berpotensi membagi satu buffer yang digerakkan oleh timer menjadi beberapa buffer DSP, memperbarui posisi saat DSP memproses setiap buffer (misalnya, buffer berbasis timer 20 ms dibagi menjadi 10 buffer 2 ms akan berfungsi dengan baik dalam mode yang digerakkan oleh timer).
Ukuran paket dalam aliran buffer yang besar
Saat mengekspos dukungan untuk Buffer Besar, driver juga akan menyediakan panggilan balik yang digunakan untuk menentukan ukuran paket minimum dan maksimum untuk pemutaran Buffer Besar.
Ukuran paket untuk alokasi buffer aliran ditentukan berdasarkan minimum dan maksimum.
Karena ukuran buffer minimum dan maksimum dapat volatil, driver dapat gagal panggilan alokasi paket jika ada perubahan pada ukuran buffer minimum dan maksimum.
Menentukan batasan buffer ACX
Untuk menentukan batasan buffer ACX, driver ACX dapat menggunakan pengaturan properti KS/PortCls - KSAUDIO_PACKETSIZE_CONSTRAINTS2 dan struktur KSAUDIO_PACKETSIZE_PROCESSINGMODE_CONSTRAINT.
Sampel kode berikut menunjukkan cara mengatur batasan ukuran buffer untuk buffer WaveRT untuk mode pemrosesan sinyal yang berbeda.
//
// Describe buffer size constraints for WaveRT buffers
// Note: 10msec for each of the Modes is the default system behavior.
//
static struct
{
KSAUDIO_PACKETSIZE_CONSTRAINTS2 TransportPacketConstraints; // 1
KSAUDIO_PACKETSIZE_PROCESSINGMODE_CONSTRAINT AdditionalProcessingConstraints[4]; // + 4 = 5
} DspR_RtPacketSizeConstraints =
{
{
10 * HNSTIME_PER_MILLISECOND, // 10 ms minimum processing interval
FILE_BYTE_ALIGNMENT, // 1 byte packet size alignment
0, // no maximum packet size constraint
5, // 5 processing constraints follow
{
STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW, // constraint for raw processing mode
0, // NA samples per processing frame
10 * HNSTIME_PER_MILLISECOND, // 100000 hns (10ms) per processing frame
},
},
{
{
STATIC_AUDIO_SIGNALPROCESSINGMODE_DEFAULT, // constraint for default processing mode
0, // NA samples per processing frame
10 * HNSTIME_PER_MILLISECOND, // 100000 hns (10ms) per processing frame
},
{
STATIC_AUDIO_SIGNALPROCESSINGMODE_COMMUNICATIONS, // constraint for movie communications mode
0, // NA samples per processing frame
10 * HNSTIME_PER_MILLISECOND, // 100000 hns (10ms) per processing frame
},
{
STATIC_AUDIO_SIGNALPROCESSINGMODE_MEDIA, // constraint for default media mode
0, // NA samples per processing frame
10 * HNSTIME_PER_MILLISECOND, // 100000 hns (10ms) per processing frame
},
{
STATIC_AUDIO_SIGNALPROCESSINGMODE_MOVIE, // constraint for movie movie mode
0, // NA samples per processing frame
10 * HNSTIME_PER_MILLISECOND, // 100000 hns (10ms) per processing frame
},
}
};
Struktur DSP_DEVPROPERTY digunakan untuk menyimpan batasan.
typedef struct _DSP_DEVPROPERTY {
const DEVPROPKEY *PropertyKey;
DEVPROPTYPE Type;
ULONG BufferSize;
__field_bcount_opt(BufferSize) PVOID Buffer;
} DSP_DEVPROPERTY, PDSP_DEVPROPERTY;
Dan sebuah array dari struktur-struktur tersebut dibuat.
const DSP_DEVPROPERTY DspR_InterfaceProperties[] =
{
{
&DEVPKEY_KsAudio_PacketSize_Constraints2, // Key
DEVPROP_TYPE_BINARY, // Type
sizeof(DspR_RtPacketSizeConstraints), // BufferSize
&DspR_RtPacketSizeConstraints, // Buffer
},
};
Kemudian dalam fungsi EvtCircuitCompositeCircuitInitialize, fungsi pembantu AddPropertyToCircuitInterface digunakan untuk menambahkan array properti antarmuka ke sirkuit.
// Set RT buffer constraints.
//
status = AddPropertyToCircuitInterface(Circuit, ARRAYSIZE(DspC_InterfaceProperties), DspC_InterfaceProperties);
Fungsi pembantu AddPropertyToCircuitInterface mengambil AcxCircuitGetSymbolicLinkName untuk sirkuit dan kemudian memanggil IoGetDeviceInterfaceAlias untuk menemukan antarmuka audio yang digunakan oleh sirkuit.
Kemudian fungsi SetDeviceInterfacePropertyDataMultiple memanggil fungsi IoSetDeviceInterfacePropertyData untuk memodifikasi nilai properti antarmuka perangkat saat ini - nilai properti audio KS pada antarmuka audio untuk ACXCIRCUIT.
PAGED_CODE_SEG
NTSTATUS AddPropertyToCircuitInterface(
_In_ ACXCIRCUIT Circuit,
_In_ ULONG PropertyCount,
_In_reads_opt_(PropertyCount) const DSP_DEVPROPERTY * Properties
)
{
PAGED_CODE();
NTSTATUS status = STATUS_UNSUCCESSFUL;
UNICODE_STRING acxLink = {0};
UNICODE_STRING audioLink = {0};
WDFSTRING wdfLink = AcxCircuitGetSymbolicLinkName(Circuit);
bool freeStr = false;
// Get the underline unicode string.
WdfStringGetUnicodeString(wdfLink, &acxLink);
// Make sure there is a string.
if (!acxLink.Length || !acxLink.Buffer)
{
status = STATUS_INVALID_DEVICE_STATE;
DrvLogError(g_BthLeVDspLog, FLAG_INIT,
L"AcxCircuitGetSymbolicLinkName failed, Circuit: %p, %!STATUS!",
Circuit, status);
goto exit;
}
// Get the audio interface.
status = IoGetDeviceInterfaceAlias(&acxLink, &KSCATEGORY_AUDIO, &audioLink);
if (!NT_SUCCESS(status))
{
DrvLogError(g_BthLeVDspLog, FLAG_INIT,
L"IoGetDeviceInterfaceAlias failed, Circuit: %p, symbolic link name: %wZ, %!STATUS!",
Circuit, &acxLink, status);
goto exit;
}
freeStr = true;
// Set specified properties on the audio interface for the ACXCIRCUIT.
status = SetDeviceInterfacePropertyDataMultiple(&audioLink, PropertyCount, Properties);
if (!NT_SUCCESS(status))
{
DrvLogError(g_BthLeVDspLog, FLAG_INIT,
L"SetDeviceInterfacePropertyDataMultiple failed, Circuit: %p, symbolic link name: %wZ, %!STATUS!",
Circuit, &audioLink, status);
goto exit;
}
status = STATUS_SUCCESS;
exit:
if (freeStr)
{
RtlFreeUnicodeString(&audioLink);
freeStr = false;
}
return status;
}
Perubahan status aliran
Saat perubahan status aliran terjadi, setiap objek streaming di Jalur Audio Titik Akhir untuk aliran menerima peristiwa pemberitahuan dari kerangka kerja ACX. Urutan di mana ini terjadi tergantung pada perubahan status dan alur aliran.
Untuk streaming render dari status kurang aktif ke status yang lebih aktif, sirkuit streaming (yang mendaftarkan SINK) menerima peristiwa terlebih dahulu. Setelah sirkuit menangani peristiwa, sirkuit berikutnya di Jalur Audio Titik Akhir menerima peristiwa tersebut.
Untuk streaming render yang berpindah dari status yang lebih aktif ke status kurang aktif, sirkuit streaming menerima peristiwa terakhir.
Untuk stream capture yang beralih dari keadaan kurang aktif ke lebih aktif, sirkuit streaming menerima acara terakhir.
Untuk stream pengambilan yang berubah dari status lebih aktif ke status kurang aktif, sirkuit streaming terlebih dahulu menerima peristiwa tersebut.
Pemesanan adalah default yang disediakan oleh kerangka kerja ACX. Driver dapat meminta perilaku yang berlawanan dengan mengatur AcxStreamBridgeInvertChangeStateSequence (ditentukan dalam ACX_STREAM_BRIDGE_CONFIG_FLAGS) saat membuat ACXSTREAMBRIDGE yang ditambahkan driver ke sirkuit streaming.
Streaming data audio
Setelah Anda membuat aliran dan mengalokasikan buffer yang sesuai, aliran berada dalam status Jeda dan menunggu streaming dimulai. Ketika klien menempatkan aliran ke status Play, kerangka kerja ACX memanggil semua objek ACXSTREAM yang terkait dengan aliran untuk menunjukkan status aliran berada di Play. ACXPIN kemudian ditempatkan dalam mode Putar, dan data mulai mengalir.
Pemrosesan data audio
Setelah Anda membuat stream dan mengalokasikan sumber daya, aplikasi memanggil Start pada stream untuk memulai pemutaran. Aplikasi harus memanggil GetBuffer/ReleaseBuffer sebelum memulai streaming untuk memastikan paket pertama yang mulai diputar memiliki data audio yang valid.
Klien memulai dengan memuat awal buffer. Ketika klien memanggil ReleaseBuffer, ini mengarah pada panggilan di AudioKSE yang kemudian mengakses lapisan ACX, lalu memanggil EvtAcxStreamSetRenderPacket pada ACXSTREAM yang aktif. Properti mencakup indeks paket (berbasis nol) dan, jika sesuai, penanda EOS dengan offset byte dari akhir aliran dalam paket saat ini.
Setelah sirkuit streaming selesai dengan paket, sirkuit ini memicu pemberitahuan penyelesaian buffer yang membebaskan klien yang menunggu untuk mengisi paket berikutnya dengan data audio render.
Mode streaming yang dikendalikan oleh timer didukung dan ditandai dengan menggunakan nilai PacketCount sebesar 1 saat Anda memanggil EvtAcxStreamAllocateRtPackets callback driver.
Menangkap data audio
Saat aliran berjalan, sirkuit sumber mengisi paket tangkapan dengan data audio. Setelah paket pertama diisi, sirkuit sumber merilis paket ke kerangka kerja ACX. Pada titik ini, kerangka kerja ACX memberi sinyal peristiwa pemberitahuan aliran.
Setelah pemberitahuan streaming diberi sinyal, klien dapat mengirim KSPROPERTY_RTAUDIO_GETREADPACKET untuk mendapatkan indeks (berbasis nol) dari paket yang selesai ditangkap. Ketika klien mengirim GETCAPTUREPACKET, driver dapat mengasumsikan semua paket sebelumnya diproses dan tersedia untuk diisi.
Untuk pengambilan Burst, sirkuit sumber dapat merilis paket baru ke kerangka kerja ACX segera setelah GETREADPACKET dipanggil.
Klien juga dapat menggunakan KSPROPERTY_RTAUDIO_PACKETVREGISTER untuk mendapatkan penunjuk ke struktur RTAUDIO_PACKETVREGISTER untuk aliran. Kerangka kerja ACX memperbarui struktur ini sebelum sinyal paket selesai.
Perilaku lama streaming kernel KS
Terkadang, seperti ketika driver menerapkan pengambilan data secara cepat (seperti pendeteksi kata kunci), Anda perlu menggunakan perilaku penanganan paket streaming inti lama alih-alih PacketVRegister. Untuk menggunakan perilaku berbasis paket sebelumnya, driver mengembalikan STATUS_NOT_SUPPORTED untuk KSPROPERTY_RTAUDIO_PACKETVREGISTER.
Contoh berikut menunjukkan cara melakukan ini di AcxStreamInitAssignAcxRequestPreprocessCallback untuk ACXSTREAM. Untuk informasi selengkapnya, lihat AcxStreamDispatchAcxRequest.
Circuit_EvtStreamRequestPreprocess(
_In_ ACXOBJECT Object,
_In_ ACXCONTEXT DriverContext,
_In_ WDFREQUEST Request)
{
ACX_REQUEST_PARAMETERS params;
PCIRCUIT_STREAM_CONTEXT streamCtx;
streamCtx = GetCircuitStreamContext(Object);
// The driver would define the pin type to track which pin is the keyword pin.
// The driver would add this to the driver-defined context when the stream is created.
// The driver would use AcxStreamInitAssignAcxRequestPreprocessCallback to set
// the Circuit_EvtStreamRequestPreprocess callback for the stream.
if (streamCtx && streamCtx->PinType == CapturePinTypeKeyword)
{
if (IsEqualGUID(params.Parameters.Property.Set, KSPROPSETID_RtAudio) &&
params.Parameters.Property.Id == KSPROPERTY_RTAUDIO_PACKETVREGISTER)
{
status = STATUS_NOT_SUPPORTED;
outDataCb = 0;
WdfRequestCompleteWithInformation(Request, status, outDataCb);
return;
}
}
(VOID)AcxStreamDispatchAcxRequest((ACXSTREAM)Object, Request);
}
Posisi aliran
Kerangka kerja ACX memanggil panggilan balik EvtAcxStreamGetPresentationPosition untuk mendapatkan posisi aliran saat ini. Posisi streaming saat ini mencakup PlayOffset dan WriteOffset.
Model streaming WaveRT memungkinkan driver audio untuk mengekspos register posisi HW ke klien. Model streaming ACX tidak akan mendukung pengeksposan register HW karena ini akan mencegah penyeimbangan ulang terjadi.
Setiap kali sirkuit streaming menyelesaikan paket, sirkuit ini memanggil AcxRtStreamNotifyPacketComplete dengan indeks paket berbasis nol dan nilai QPC yang diambil sedekat mungkin dengan penyelesaian paket (misalnya, Rutinitas Layanan Interupsi dapat menghitung nilai QPC). Klien bisa mendapatkan informasi ini melalui KSPROPERTY_RTAUDIO_PACKETVREGISTER, yang mengembalikan pointer ke struktur yang berisi CompletedPacketCount, CompletedPacketQPC, dan nilai yang menggabungkan keduanya (sehingga klien dapat memeriksa bahwa CompletedPacketCount dan CompletedPacketQPC berasal dari paket yang sama).
Transisi keadaan aliran
Setelah aliran dibuat, ACX akan mengalihkan aliran ke status yang berbeda menggunakan panggilan balik berikut:
- EvtAcxStreamPrepareHardware mengalihkan aliran dari status AcxStreamStateStop ke status AcxStreamStatePause. Driver harus mencadangkan perangkat keras yang diperlukan seperti Mesin DMA ketika menerima EvtAcxStreamPrepareHardware.
- EvtAcxStreamRun mentransisikan aliran dari status AcxStreamStatePause ke status AcxStreamStateRun.
- EvtAcxStreamPause mentransisikan aliran dari status AcxStreamStateRun ke status AcxStreamStatePause.
- EvtAcxStreamReleaseHardware mentransisikan aliran dari status AcxStreamStatePause ke status AcxStreamStateStop. Driver harus merilis perangkat keras yang diperlukan seperti mesin DMA saat menerima EvtAcxStreamReleaseHardware.
Aliran mungkin menerima panggilan balik EvtAcxStreamPrepareHardware setelah menerima panggilan balik EvtAcxStreamReleaseHardware. Ini mentransisikan aliran kembali ke status AcxStreamStatePause.
Alokasi paket dengan EvtAcxStreamAllocateRtPackets biasanya terjadi sebelum panggilan pertama ke EvtAcxStreamPrepareHardware. Paket yang dialokasikan biasanya dibebaskan dengan EvtAcxStreamFreeRtPackets setelah panggilan terakhir ke EvtAcxStreamReleaseHardware. Pemesanan ini tidak dijamin.
Status AcxStreamStateAcquire tidak digunakan. ACX menghapus kebutuhan driver untuk memiliki status akuisisi karena status ini implisit dengan panggilan balik siapkan perangkat keras (EvtAcxStreamPrepareHardware) dan rilis perangkat keras (EvtAcxStreamReleaseHardware).
Aliran buffer besar dan dukungan mesin offload
ACX menggunakan elemen ACXAUDIOENGINE untuk mengidentifikasi ACXPIN yang akan menangani pembuatan aliran offload dan elemen-elemen berbeda yang diperlukan untuk volume, diam, dan status meter puncak pada aliran offload. Ini mirip dengan node mesin audio yang ada di driver WaveRT.
Proses penutupan aliran
Ketika klien menutup aliran, driver menerima EvtAcxStreamPause dan EvtAcxStreamReleaseHardware sebelum objek ACXSTREAM dihapus oleh kerangka kerja ACX. Driver dapat menyediakan entri WDF EvtCleanupCallback standar dalam struktur WDF_OBJECT_ATTRIBUTES saat memanggil AcxStreamCreate untuk melakukan pembersihan akhir untuk ACXSTREAM. WDF memanggil EvtCleanupCallback ketika kerangka kerja mencoba menghapus objek. Jangan gunakan EvtDestroyCallback, yang hanya dipanggil setelah semua referensi ke objek dirilis, yang waktunya tidak dapat ditentukan.
Driver harus membersihkan sumber daya memori sistem yang terkait dengan objek ACXSTREAM di EvtCleanupCallback jika sumber daya belum dibersihkan di EvtAcxStreamReleaseHardware.
Driver tidak boleh membersihkan sumber daya yang mendukung aliran hingga klien memintanya.
Status AcxStreamStateAcquire tidak digunakan. ACX menghilangkan kebutuhan driver untuk mengelola status akuisisi karena status ini secara implisit dikelola oleh fungsi balik persiapan perangkat keras (EvtAcxStreamPrepareHardware) dan pelepasan perangkat keras (EvtAcxStreamReleaseHardware).
Penghapusan kejutan dan pembatalan streaming
Jika driver menentukan aliran tidak valid (misalnya, jack dilepas), sirkuit akan mematikan semua aliran.
Pembersihan memori aliran
Pembuangan sumber daya aliran dapat dilakukan dalam pembersihan konteks aliran driver (tidak dihancurkan). Jangan letakkan pembuangan apa pun yang dibagikan dalam konteks objek menghancurkan panggilan balik. Panduan ini berlaku untuk semua objek ACX.
Panggilan balik hancur dipanggil setelah referensi terakhir hilang, yang tidak ditentukan.
Secara umum, fungsi balik untuk pembersihan aliran dipanggil ketika handle ditutup. Salah satu pengecualian adalah ketika driver membuat aliran dalam panggilan baliknya. Jika ACX gagal menambahkan aliran ini ke jembatan aliran tepat sebelum kembali dari operasi pembuatan aliran, aliran dibatalkan secara asinkron, dan utas saat ini mengembalikan kesalahan ke klien pembuatan aliran. Aliran seharusnya tidak memiliki alokasi memori saat ini. Untuk informasi lebih lanjut, lihat panggilan balik EVT_ACX_STREAM_RELEASE_HARDWARE.
Mengalirkan urutan pembersihan memori
Buffer aliran adalah sumber daya sistem dan Anda harus merilisnya hanya ketika klien dalam mode pengguna menutup handle aliran. Buffer (yang terpisah dari sumber daya perangkat keras perangkat) memiliki masa pakai yang sama dengan penanganan aliran. Saat klien menutup handle, ACX memanggil panggilan balik pembersihan objek aliran, lalu panggilan balik penghapusan objek aliran ketika jumlah referensi pada objek menjadi nol.
ACX dapat menunda penghapusan objek STREAM ke item kerja saat driver membuat objek stream dan kemudian gagal dalam callback create-stream. Untuk mencegah kebuntuan dengan utas WDF yang dimatikan, ACX menunda penghapusan melalui utas yang berbeda. Untuk menghindari kemungkinan efek samping dari perilaku ini (pelepasan sumber daya yang ditangguhkan), driver dapat melepaskan sumber daya aliran yang telah dialokasikan sebelum mengembalikan kesalahan dari pembuatan aliran.
Driver harus membebaskan buffer audio ketika ACX memanggil panggilan balik EVT_ACX_STREAM_FREE_RTPACKETS. Panggilan balik ini terjadi ketika pengguna menutup handle stream.
Karena buffer RT dipetakan dalam mode pengguna, masa pakai buffer sama dengan masa pakai pegangan. Driver tidak boleh merilis atau membebaskan buffer audio sebelum ACX memanggil panggilan balik ini.
EVT_ACX_STREAM_FREE_RTPACKETS callback harus dipanggil setelah EVT_ACX_STREAM_RELEASE_HARDWARE callback dan harus berakhir sebelum EvtDeviceReleaseHardware.
Panggilan balik ini mungkin terjadi setelah driver memproses panggilan balik perangkat keras rilis WDF karena klien mode pengguna dapat memegang handelnya untuk waktu yang lama. Driver seharusnya tidak menunggu handel ini hilang. Tindakan ini membuat pemeriksaan kesalahan 0x9f DRIVER_POWER_STATE_FAILURE. Lihat fungsi panggilan balik EVT_WDF_DEVICE_RELEASE_HARDWARE untuk informasi selengkapnya.
Kode EvtDeviceReleaseHardware ini dari contoh driver ACX menunjukkan contoh panggilan AcxDeviceRemoveCircuit lalu melepaskan memori perangkat keras streaming.
RETURN_NTSTATUS_IF_FAILED(AcxDeviceRemoveCircuit(Device, devCtx->Render));
RETURN_NTSTATUS_IF_FAILED(AcxDeviceRemoveCircuit(Device, devCtx->Capture));
// NOTE: Release streaming h/w resources here.
CSaveData::DestroyWorkItems();
CWaveReader::DestroyWorkItems();
Singkatnya:
- Perangkat WDF melepaskan perangkat keras: melepaskan sumber daya perangkat keras perangkat.
- AcxStreamFreeRtPackets: merilis atau membebaskan buffer audio yang terkait dengan handle.
Untuk informasi selengkapnya tentang mengelola objek WDF dan sirkuit, lihat ACX WDF Driver Lifetime Management.
DDI Streaming
Struktur Streaming
struktur ACX_RTPACKET
Struktur ini mewakili satu paket yang dialokasikan. PacketBuffer dapat menjadi handle WDFMEMORY, MDL, atau Buffer. Ini memiliki fungsi inisialisasi terkait, ACX_RTPACKET_INIT.
ACX_STREAM_CALLBACKS
Struktur ini mengidentifikasi panggilan balik driver untuk streaming ke kerangka kerja ACX. Struktur ini adalah bagian dari struktur ACX_PIN_CONFIG.
Panggilan balik streaming
EvtAcxStreamAllocateRtPackets
Peristiwa EvtAcxStreamAllocateRtPackets memberi tahu driver untuk mengalokasikan RtPackets untuk streaming. AcxRtStream menerima PacketCount = 2 untuk streaming berbasis peristiwa atau PacketCount = 1 untuk streaming berbasis timer. Jika driver menggunakan buffer tunggal untuk kedua paket, RtPacketBuffer kedua harus memiliki WDF_MEMORY_DESCRIPTOR dengan Type = WdfMemoryDescriptorTypeInvalid dengan RtPacketOffset yang selaras dengan akhir paket pertama (paket[2]. RtPacketOffset = paket[1]. RtPacketOffset+packet[1]. RtPacketSize).
EvtAcxStreamFreeRtPackets
Peristiwa EvtAcxStreamFreeRtPackets memberi tahu driver untuk membebaskan RtPackets yang dialokasikan dalam panggilan sebelumnya ke EvtAcxStreamAllocateRtPackets. Paket yang sama dari panggilan tersebut disertakan.
EvtAcxStreamGetHwLatency (Fungsi Mendapatkan Latensi Perangkat Keras)
Peristiwa EvtAcxStreamGetHwLatency memberi tahu driver untuk memberikan latensi aliran untuk sirkuit tertentu dari aliran ini (latensi keseluruhan akan menjadi jumlah latensi sirkuit yang berbeda). FifoSize dalam byte dan Penundaan dalam unit 100 nanodetik.
EvtAcxStreamSetRenderPacket
Peristiwa EvtAcxStreamSetRenderPacket memberi tahu driver paket mana yang baru saja dirilis oleh klien. Jika tidak ada gangguan, paket ini harus (CurrentRenderPacket + 1), di mana CurrentRenderPacket adalah paket tempat driver saat ini streaming.
Bendera dapat 0 atau KSSTREAM_HEADER_OPTIONSF_ENDOFSTREAM = 0x200, menunjukkan Paket adalah paket terakhir dalam aliran, dan EosPacketLength adalah panjang byte yang valid untuk paket. Untuk informasi selengkapnya, lihat OptionsFlags dalam struktur KSSTREAM_HEADER (ks.h).
Driver terus meningkatkan CurrentRenderPacket saat paket dirender alih-alih mengubah CurrentRenderPacket untuk mencocokkan nilai ini.
EvtAcxStreamGetCurrentPacket
EvtAcxStreamGetCurrentPacket memberi tahu driver untuk menunjukkan paket mana (berbasis nol) yang saat ini sedang dirender ke perangkat keras atau saat ini sedang diisi oleh perangkat keras penangkapan.
EvtAcxStreamGetCapturePacket
EvtAcxStreamGetCapturePacket memberi tahu driver untuk menunjukkan paket mana (berbasis nol) yang terakhir diisi, termasuk nilai QPC pada saat driver mulai mengisi paket.
EvtAcxStreamGetPresentationPosition
EvtAcxStreamGetPresentationPosition memberi tahu driver untuk menunjukkan posisi saat ini bersama dengan nilai QPC pada saat posisi saat ini dihitung.
PERISTIWA KEADAAN STREAM
API berikut mengelola status streaming untuk ACXSTREAM.
- EVT_ACX_STREAM_PREPARE_HARDWARE
- EVT_ACX_STREAM_RELEASE_HARDWARE
- EVT_ACX_STREAM_RUN
- EVT_ACX_STREAM_PAUSE
API ACX Streaming
AcxStreamBuat
AcxStreamCreate membuat ACX Stream yang dapat digunakan untuk mengontrol perilaku streaming.
AcxRtStreamBuat
AcxRtStreamCreate membuat ACX Stream yang dapat digunakan untuk mengontrol perilaku streaming dan menangani alokasi paket dan mengomunikasikan status streaming.
AcxRtStreamNotifyPacketComplete
Driver memanggil ACX API ini ketika paket telah selesai. Waktu penyelesaian paket dan indeks Paket berbasis nol disertakan untuk meningkatkan performa klien. Kerangka kerja ACX menetapkan peristiwa pemberitahuan apa pun yang terkait dengan aliran.