EVT_ACX_STREAM_ALLOCATE_RTPACKETS Rückruffunktion (acxstreams.h)
Das EvtAcxStreamAllocateRtPackets Ereignis teilt dem Treiber mit, RtPackets für Streaming zuzuweisen.
Syntax
EVT_ACX_STREAM_ALLOCATE_RTPACKETS EvtAcxStreamAllocateRtpackets;
NTSTATUS EvtAcxStreamAllocateRtpackets(
ACXSTREAM Stream,
ULONG PacketCount,
ULONG PacketSize,
PACX_RTPACKET *Packets
)
{...}
Parameter
Stream
Ein ACXSTREAM-Objekt stellt einen von einem Schaltkreis erstellten Audiodatenstrom dar. Der Datenstrom besteht aus einer Liste von Elementen, die basierend auf den Elementen des übergeordneten Schaltkreises erstellt wurden. Weitere Informationen finden Sie unter ACX – Zusammenfassung von ACX Objects.
PacketCount
Gibt die Anzahl der pakete an, die zugewiesen werden sollen. Gültige Werte sind 1 oder 2. Ereignisgesteuerte Datenströme verwenden zwei Pakete, während zeitgesteuerte Datenströme ein Paket verwenden.
PacketSize
Die Paketgröße, gemessen in Byte.
Packets
Ein Zeiger, der einen Zeiger auf ein Array von ACX_RTPACKET Strukturen empfängt,, die den Speicherort und die Größe der Pakete beschreibt.
Die ursprüngliche ACX-Version unterstützt nur WdfMemoryDescriptorTypeMdl-Puffer für das ACX_RTPACKET RtPacketBuffer-Element. Der RtPacketBuffer muss seitenbündig ausgerichtet sein und eine seitenausgeglichene Byteanzahl aufweisen.
Rückgabewert
Gibt STATUS_SUCCESS
zurück, wenn der Anruf erfolgreich war. Andernfalls wird ein entsprechender Fehlercode zurückgegeben. Weitere Informationen finden Sie unter Verwenden von NTSTATUS-Werten.
Bemerkungen
Die ursprüngliche ACX-Version ruft mit PacketCount = 1 oder PacketCount = 2 auf, wenn StreamModel AcxStreamModelRtPacket ist. Mit PacketCount = 2 kann der Treiber einen einzelnen Puffer zuordnen, der zwischen den beiden Paketen gemeinsam genutzt wird, oder der Treiber kann zwei separate Puffer zuordnen.
Wenn der Treiber einen einzelnen Puffer zuweist, der für zwei Pakete freigegeben werden soll, sollte die zweite ACX_RTPACKET-Struktur eine WDF_MEMORY_DESCRIPTOR_TYPE = WdfMemoryDescriptorTypeInvalid aufweisen. Das RtPacketOffset für die zweite ACX_RTPACKET Struktur sollte ein gültiger Offset in den RtPacketBuffer der ersten ACX_RTPACKET Struktur sein und sollte mit der ersten ACX_RTPACKET Struktur RtPacketOffset + RtPacketSize ausgerichtet werden.
EvtAcxStreamAllocateRtPackets wird vor EvtAcxStreamPrepareHardware- aufgerufen, damit die RT-Paketzuordnung vor EvtAcxStreamPrepareHardware erfolgen kann.
Die Pufferzuweisung umfasst in der Regel nur das Zuweisen des Systemspeichers so, dass sie mit der DMA-Hardware verwendet werden kann. In der Regel wirkt sich die Pufferzuweisung nicht auf die Streaminghardware aus. Die Vorbereitungshardwarephase wird verwendet, wenn der Treiber den Datenstrom für die Ausführung vorbereitet, indem Aufgaben wie das Reservieren der Bandbreite, die Programmierung von DMA und das Abschließen der Vorbereitung für die Anforderung zum Ausführen des Datenstroms ausgeführt werden. In der Regel verwendet der vorbereitende Hardwarecode die zugeordneten Puffer für die Vorbereitung des DMA und zugehöriger Aktivitäten, um den Datenstrom zu starten.
Beispiel
Die Beispielverwendung wird unten gezeigt.
//
// 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;
}
ACX-Anforderungen
Mindestens ACX-Version: 1.0
Weitere Informationen zu ACX-Versionen finden Sie unter ACX-Versionsübersicht.
Anforderungen
Anforderung | Wert |
---|---|
Header- | acxstreams.h |
IRQL- | PASSIVE_LEVEL |