EVT_ACX_STREAM_ALLOCATE_RTPACKETS fonction de rappel (acxstreams.h)
L’événement EvtAcxStreamAllocateRtPackets indique au pilote d’allouer rtPackets pour la diffusion en continu.
Syntaxe
EVT_ACX_STREAM_ALLOCATE_RTPACKETS EvtAcxStreamAllocateRtpackets;
NTSTATUS EvtAcxStreamAllocateRtpackets(
ACXSTREAM Stream,
ULONG PacketCount,
ULONG PacketSize,
PACX_RTPACKET *Packets
)
{...}
Paramètres
Stream
Un objet ACXSTREAM représente un flux audio créé par un circuit. Le flux est composé d’une liste d’éléments créés en fonction des éléments du circuit parent. Pour plus d’informations, consultez ACX - Résumé des objets ACX.
PacketCount
Spécifie le nombre de paquets à allouer. Les valeurs valides sont 1 ou 2. Les flux pilotés par les événements utilisent deux paquets, tandis que les flux pilotés par le minuteur utilisent un paquet.
PacketSize
Taille du paquet, mesurée en octets.
Packets
Pointeur qui reçoit un pointeur vers un tableau de structures ACX_RTPACKET qui décrit l’emplacement et la taille des paquets.
La version initiale d’ACX prend uniquement en charge les mémoires tampons WdfMemoryDescriptorTypeMdl pour le membre ACX_RTPACKET RtPacketBuffer. Le rtPacketBuffer doit être aligné sur la page et avoir un nombre d’octets aligné sur la page.
Valeur de retour
Retourne STATUS_SUCCESS
si l’appel a réussi. Sinon, elle retourne un code d’erreur approprié. Pour plus d’informations, consultez Using NTSTATUS Values.
Remarques
La version ACX initiale appellera PacketCount = 1 ou PacketCount = 2 lorsque StreamModel est AcxStreamModelRtPacket. Avec PacketCount = 2, le pilote peut allouer une mémoire tampon unique partagée entre les deux paquets ou le pilote peut allouer deux mémoires tampons distinctes.
Si le pilote alloue une mémoire tampon unique à partager sur deux paquets, la deuxième structure ACX_RTPACKET doit avoir un WDF_MEMORY_DESCRIPTOR_TYPE = WdfMemoryDescriptorTypeInvalid. La structure rtPacketOffset pour la deuxième structure de ACX_RTPACKET doit être un décalage valide dans le rtPacketBuffer de la première structure ACX_RTPACKET et doit s’aligner avec le premier ACX_RTPACKET structure RtPacketOffset + RtPacketSize.
EvtAcxStreamAllocateRtPackets est appelé avant EvtAcxStreamPrepareHardware pour autoriser l’allocation de paquets RT à se produire avant EvtAcxStreamPrepareHardware.
L’allocation de mémoire tampon implique généralement uniquement l’allocation de mémoire système de telle sorte qu’elle puisse être utilisée avec le matériel DMA. En règle générale, l’allocation de mémoire tampon n’aura aucun effet sur le matériel de diffusion en continu. La phase de préparation matérielle est utilisée comme pilote pour préparer l’exécution du flux, en effectuant des tâches telles que la réservation de bande passante, la programmation DMA et la préparation de la demande pour exécuter le flux. En règle générale, le code de préparation du matériel utilisera les mémoires tampons allouées pour préparer la DMA et les activités associées pour être prêtes à démarrer le flux.
Exemple
L’exemple d’utilisation est illustré ci-dessous.
//
// 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;
}
Configuration requise pour ACX
version minimale d’ACX : 1.0
Pour plus d’informations sur les versions ACX, consultez vue d’ensemble de la version ACX.
Exigences
Exigence | Valeur |
---|---|
d’en-tête | acxstreams.h |
IRQL | PASSIVE_LEVEL |