EVT_ACX_STREAM_ALLOCATE_RTPACKETS コールバック関数 (acxstreams.h)
EvtAcxStreamAllocateRtPackets イベントは、ストリーミング用に RtPackets を割り当てるようドライバーに指示します。
構文
EVT_ACX_STREAM_ALLOCATE_RTPACKETS EvtAcxStreamAllocateRtpackets;
NTSTATUS EvtAcxStreamAllocateRtpackets(
ACXSTREAM Stream,
ULONG PacketCount,
ULONG PacketSize,
PACX_RTPACKET *Packets
)
{...}
パラメーター
Stream
ACXSTREAM オブジェクトは、回線によって作成されたオーディオ ストリームを表します。 ストリームは、親回線の要素に基づいて作成された要素の一覧で構成されます。 詳細については、「 ACX - ACX オブジェクトの概要」を参照してください。
PacketCount
割り当てるパケットの数を指定します。 有効な値は 1 または 2 です。 イベント ドリブン ストリームでは 2 つのパケットが使用され、タイマードリブン ストリームでは 1 つのパケットが使用されます。
PacketSize
パケット サイズ (バイト単位)。
Packets
パケットの場所とサイズを記述する ACX_RTPACKET構造体 の配列へのポインターを受け取るポインター。
最初の ACX バージョンでは、ACX_RTPACKET RtPacketBuffer メンバーの WdfMemoryDescriptorTypeMdl バッファーのみがサポートされています。 RtPacketBuffer はページアラインされ、ページアラインバイト数が必要です。
戻り値
STATUS_SUCCESS
呼び出しが成功した場合は を返します。 それ以外の場合は、適切なエラー コードを返します。 詳細については、「 NTSTATUS 値の使用」を参照してください。
注釈
StreamModel が AcxStreamModelRtPacket の場合、最初の ACX バージョンは PacketCount = 1 または PacketCount = 2 で呼び出されます。 PacketCount = 2 を使用すると、ドライバーは 2 つのパケット間で共有される 1 つのバッファーを割り当てることができます。または、ドライバーは 2 つの個別のバッファーを割り当てることができます。
ドライバーが 2 つのパケット間で共有する 1 つのバッファーを割り当てる場合、2 番目のACX_RTPACKET構造体には、WDF_MEMORY_DESCRIPTOR_TYPE = WdfMemoryDescriptorTypeInvalid が必要です。 2 番目のACX_RTPACKET構造体の RtPacketOffset は、最初のACX_RTPACKET構造体の RtPacketBuffer への有効なオフセットであり、最初のACX_RTPACKET構造体の RtPacketOffset + RtPacketSize に合わせる必要があります。
EvtAcxStreamAllocateRtPackets は EvtAcxStreamPrepareHardware の前に呼び出され、EvtAcxStreamPrepareHardware の前に RT パケット割り当てが行われるのを許可します。
通常、バッファー割り当てには、DMA ハードウェアで使用できるようにシステム メモリを割り当てる必要があります。 通常、バッファー割り当てはストリーミング ハードウェアには影響しません。 ハードウェア準備フェーズは、帯域幅の予約、DMA のプログラミング、ストリームを実行する要求の準備の完了などのタスクを完了することで、ドライバーがストリームを実行する準備を行う際に使用されます。 通常、準備ハードウェア コードでは、割り当てられたバッファーを使用して DMA と関連アクティビティを準備し、ストリームを開始する準備をします。
例
使用例を次に示します。
//
// 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 の要件
最小 ACX バージョン: 1.0
ACX バージョンの詳細については、「 ACX バージョンの概要」を参照してください。
要件
要件 | 値 |
---|---|
Header | acxstreams.h |
IRQL | PASSIVE_LEVEL |