次の方法で共有


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

こちらもご覧ください