Condividi tramite


EVT_ACX_STREAM_ALLOCATE_RTPACKETS funzione di callback (acxstreams.h)

L'evento EvtAcxStreamAllocateRtPackets indica al driver di allocare RtPackets per lo streaming.

Sintassi

EVT_ACX_STREAM_ALLOCATE_RTPACKETS EvtAcxStreamAllocateRtpackets;

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

Parametri

Stream

Un oggetto ACXSTREAM rappresenta un flusso audio creato da un circuito. Il flusso è costituito da un elenco di elementi creati in base agli elementi del circuito padre. Per altre informazioni, vedere ACX - Riepilogo degli oggetti ACX.

PacketCount

Specifica il numero di pacchetti da allocare. I valori validi sono 1 o 2. I flussi basati su eventi useranno due pacchetti mentre i flussi basati su timer useranno un pacchetto.

PacketSize

Dimensioni dei pacchetti, misurate in byte.

Packets

Puntatore che riceve un puntatore a una matrice di strutture ACX_RTPACKET che descrive la posizione e le dimensioni dei pacchetti.

La versione iniziale di ACX supporta solo i buffer WdfMemoryDescriptorTypeMdl per il membro rtPacketBuffer ACX_RTPACKET. RtPacketBuffer deve essere allineato a pagina e avere un conteggio di byte allineato alla pagina.

Valore restituito

Restituisce STATUS_SUCCESS se la chiamata ha avuto esito positivo. In caso contrario, restituisce un codice di errore appropriato. Per altre informazioni, vedere Uso dei valori NTSTATUS.

Commenti

La versione iniziale di ACX chiamerà con PacketCount = 1 o PacketCount = 2 quando StreamModel è AcxStreamModelRtPacket. Con PacketCount = 2, il driver può allocare un singolo buffer condiviso tra i due pacchetti o il driver può allocare due buffer separati.

Se il driver alloca un singolo buffer da condividere tra due pacchetti, la seconda struttura ACX_RTPACKET deve avere un WDF_MEMORY_DESCRIPTOR_TYPE = WdfMemoryDescriptorTypeInvalid. La struttura RtPacketOffset per la seconda struttura ACX_RTPACKET deve essere un offset valido nella struttura RtPacketBuffer della prima struttura ACX_RTPACKET e deve essere allineata alla prima struttura di ACX_RTPACKET RtPacketOffset + RtPacketSize.

EvtAcxStreamAllocateRtPackets viene chiamato prima di EvtAcxStreamPrepareHardware per consentire l'allocazione dei pacchetti RT prima di EvtAcxStreamPrepareHardware .

L'allocazione del buffer comporta in genere l'allocazione della memoria di sistema in modo che possa essere usata con l'hardware DMA. In genere, l'allocazione del buffer non avrà alcun effetto sull'hardware di streaming. La fase di preparazione dell'hardware viene usata come driver per l'esecuzione del flusso, completando attività come la prenotazione della larghezza di banda, la programmazione DMA e il completamento della preparazione della richiesta per l'esecuzione del flusso. In genere, il codice hardware di preparazione userà i buffer allocati per preparare la DMA e le attività correlate per essere pronti per avviare il flusso.

Esempio

Di seguito è riportato l'esempio di utilizzo.

    //
    // 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;
}

Requisiti ACX

Versione minima DI ACX: 1.0

Per altre informazioni sulle versioni ACX, vedere Panoramica della versione di ACX.

Requisiti

Requisito Valore
Intestazione acxstreams.h
IRQL PASSIVE_LEVEL

Vedi anche