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입니다. 이벤트 기반 스트림은 두 개의 패킷을 사용하고 타이머 기반 스트림은 하나의 패킷을 사용합니다.
PacketSize
바이트로 측정된 패킷 크기입니다.
Packets
패킷의 위치와 크기를 설명하는 ACX_RTPACKET 구조 체 배열에 대한 포인터를 수신하는 포인터입니다.
초기 ACX 버전은 ACX_RTPACKET RtPacketBuffer 멤버에 대한 WdfMemoryDescriptorTypeMdl 버퍼만 지원합니다. RtPacketBuffer는 페이지 정렬이어야 하며 페이지 정렬 바이트 수가 있어야 합니다.
반환 값
호출에 성공하면 를 반환합니다 STATUS_SUCCESS
. 그렇지 않으면 적절한 오류 코드를 반환합니다. 자세한 내용은 NTSTATUS 값 사용을 참조하세요.
설명
초기 ACX 버전은 StreamModel이 AcxStreamModelRtPacket인 경우 PacketCount = 1 또는 PacketCount = 2를 사용하여 를 호출합니다. PacketCount = 2를 사용하면 드라이버가 두 패킷 간에 공유되는 단일 버퍼를 할당하거나 드라이버가 두 개의 별도 버퍼를 할당할 수 있습니다.
드라이버가 두 패킷에서 공유할 단일 버퍼를 할당하는 경우 두 번째 ACX_RTPACKET 구조에는 WDF_MEMORY_DESCRIPTOR_TYPE = WdfMemoryDescriptorTypeInvalid가 있어야 합니다. 두 번째 ACX_RTPACKET 구조체에 대한 RtPacketOffset은 첫 번째 ACX_RTPACKET 구조체의 RtPacketBuffer에 대한 유효한 오프셋이어야 하며 첫 번째 ACX_RTPACKET 구조체의 RtPacketOffset + RtPacketSize와 일치해야 합니다.
EvtAcxStreamAllocateRtPackets는 EvtAcxStreamPrepareHardware 이전에 RT 패킷 할당이 발생할 수 있도록 EvtAcxStreamPrepareHardware 전에 호출됩니다.
버퍼 할당에는 일반적으로 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 버전 개요를 참조하세요.
요구 사항
요구 사항 | 값 |
---|---|
헤더 | acxstreams.h |
IRQL | PASSIVE_LEVEL |