EVT_ACX_STREAM_ALLOCATE_RTPACKETS fungsi panggilan balik (acxstreams.h)

Peristiwa EvtAcxStreamAllocateRtPackets memberi tahu driver untuk mengalokasikan RtPackets untuk streaming.

Sintaks

EVT_ACX_STREAM_ALLOCATE_RTPACKETS EvtAcxStreamAllocateRtpackets;

NTSTATUS EvtAcxStreamAllocateRtpackets(
  ACXSTREAM Stream,
  ULONG PacketCount,
  ULONG PacketSize,
  PACX_RTPACKET *Packets
)
{...}

Parameter

Stream

Objek ACXSTREAM mewakili aliran audio yang dibuat oleh sirkuit. Aliran terdiri dari daftar elemen yang dibuat berdasarkan elemen sirkuit induk. Untuk informasi selengkapnya, lihat ACX - Ringkasan Objek ACX.

PacketCount

Menentukan jumlah paket yang akan dialokasikan. Nilai yang valid adalah 1 atau 2. Aliran berbasis peristiwa akan menggunakan dua paket sementara aliran berbasis timer akan menggunakan satu paket.

PacketSize

Ukuran paket, diukur dalam byte.

Packets

Penunjuk yang menerima penunjuk ke array struktur ACX_RTPACKET yang menjelaskan lokasi dan ukuran paket.

Versi ACX awal hanya mendukung buffer WdfMemoryDescriptorTypeMdl untuk anggota ACX_RTPACKET RtPacketBuffer. RtPacketBuffer harus diratakan halaman dan memiliki jumlah byte yang selaras dengan halaman.

Menampilkan nilai

Mengembalikan STATUS_SUCCESS jika panggilan berhasil. Jika tidak, kode kesalahan akan menampilkan kode kesalahan yang sesuai. Untuk informasi selengkapnya, lihat Menggunakan Nilai NTSTATUS.

Keterangan

Versi ACX awal akan memanggil dengan PacketCount = 1 atau PacketCount = 2 ketika StreamModel adalah AcxStreamModelRtPacket. Dengan PacketCount = 2, driver dapat mengalokasikan satu buffer yang dibagikan antara dua paket atau driver dapat mengalokasikan dua buffer terpisah.

Jika driver mengalokasikan satu buffer untuk dibagikan di dua paket, struktur ACX_RTPACKET kedua harus memiliki WDF_MEMORY_DESCRIPTOR_TYPE = WdfMemoryDescriptorTypeInvalid. RtPacketOffset untuk struktur ACX_RTPACKET kedua harus menjadi offset yang valid ke dalam RtPacketBuffer dari struktur ACX_RTPACKET pertama dan harus selaras dengan RtPacketOffset + RtPacketSize struktur ACX_RTPACKET pertama.

EvtAcxStreamAllocateRtPackets dipanggil sebelum EvtAcxStreamPrepareHardware untuk memungkinkan alokasi paket RT terjadi sebelum EvtAcxStreamPrepareHardware.

Alokasi buffer biasanya hanya melibatkan alokasi memori sistem sedemikian rupa sehingga dapat digunakan dengan perangkat keras DMA. Biasanya, alokasi buffer tidak akan berpengaruh pada perangkat keras streaming. Fase siapkan perangkat keras digunakan karena driver siap menjalankan streaming, dengan menyelesaikan tugas seperti memesan bandwidth, memprogram DMA, dan menyelesaikan persiapan untuk permintaan menjalankan aliran. Biasanya, menyiapkan kode perangkat keras akan menggunakan buffer yang dialokasikan untuk menyiapkan DMA dan aktivitas terkait agar siap memulai streaming.

Contoh

Contoh penggunaan ditunjukkan di bawah ini.

    //
    // Init RT streaming callbacks.
    //
    ACX_RT_STREAM_CALLBACKS_INIT(&rtCallbacks);
    rtCallbacks.EvtAcxStreamAllocateRtPackets       = Codec_EvtStreamAllocateRtPackets;

...

#pragma code_seg("PAGE")
NTSTATUS
Codec_EvtStreamAllocateRtPackets(
    _In_ ACXSTREAM Stream,
    _In_ ULONG PacketCount,
    _In_ ULONG PacketSize,
    _Out_ PACX_RTPACKET *Packets
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PCODEC_STREAM_CONTEXT ctx;
    PACX_RTPACKET packets = NULL;
    PVOID packetBuffer = NULL;
    ULONG i;
    ULONG packetAllocSizeInPages = 0;
    ULONG packetAllocSizeInBytes = 0;
    ULONG firstPacketOffset = 0;
    size_t packetsSize = 0;

    PAGED_CODE();

    ctx = GetCodecStreamContext(Stream);

    if (PacketCount > 2)
    {
        status = STATUS_INVALID_PARAMETER;
        goto exit;
    }

    status = RtlSizeTMult(PacketCount, sizeof(ACX_RTPACKET), &packetsSize);
    if (!NT_SUCCESS(status)) {
        goto exit;
    }

    packets = (PACX_RTPACKET)ExAllocatePool2(POOL_FLAG_NON_PAGED, packetsSize, DRIVER_TAG);
    if (!packets) {
        status = STATUS_NO_MEMORY;
        goto exit;
    }

    // We need to allocate page-aligned buffers, to ensure no kernel memory leaks
    // to user space. Round up the packet size to page aligned, then calculate
    // the first packet's buffer offset so packet 0 ends on a page boundary and
    // packet 1 begins on a page boundary.
    status = RtlULongAdd(PacketSize, PAGE_SIZE - 1, &packetAllocSizeInPages);
    if (!NT_SUCCESS(status)) {
        goto exit;
    }
    packetAllocSizeInPages = packetAllocSizeInPages / PAGE_SIZE;
    packetAllocSizeInBytes = PAGE_SIZE * packetAllocSizeInPages;
    firstPacketOffset = packetAllocSizeInBytes - PacketSize;

    for (i = 0; i < PacketCount; ++i)
    {
        PMDL pMdl = NULL;

        ACX_RTPACKET_INIT(&packets[i]);

        packetBuffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, packetAllocSizeInBytes, DRIVER_TAG);
        if (packetBuffer == NULL) {
            status = STATUS_NO_MEMORY;
            goto exit;
        }

        pMdl = IoAllocateMdl(packetBuffer, packetAllocSizeInBytes, FALSE, TRUE, NULL);
        if (pMdl == NULL) {
            status = STATUS_NO_MEMORY;
            goto exit;
        }

        MmBuildMdlForNonPagedPool(pMdl);

        WDF_MEMORY_DESCRIPTOR_INIT_MDL(
            &((packets)[i].RtPacketBuffer),
            pMdl,
            packetAllocSizeInBytes);

        packets[i].RtPacketSize = PacketSize;
        if (i == 0)
        {
            packets[i].RtPacketOffset = firstPacketOffset;
        }
        else
        {
            packets[i].RtPacketOffset = 0;
        }
        m_Packets[i] = packetBuffer;

        packetBuffer = NULL;
    }

    *Packets = packets;
    packets = NULL;
    ctx->PacketsCount = PacketCount;
    ctx->PacketSize = PacketSize;
    ctx->FirstPacketOffset = firstPacketOffset;

exit:
    if (packetBuffer)
    {
        ExFreePoolWithTag(packetBuffer, DRIVER_TAG);
    }
    if (packets)
    {
        FreeRtPackets(packets, PacketCount);
    }
    return status;
}

Persyaratan ACX

Versi ACX minimum: 1.0

Untuk informasi selengkapnya tentang versi ACX, lihat Gambaran umum versi ACX.

Persyaratan

Persyaratan Nilai
Header acxstreams.h
IRQL PASSIVE_LEVEL

Lihat juga