KsStreamPointerClone
2025-02-27
33
0
- 多个流指针可以引用单个帧。要复制流指针,请调用KsStreamPointerClone。
- 流指针的最终副本称为流指针克隆。克隆是一个与父级完全相同的新流指针。最初,克隆引用相同的帧并具有相同的锁定状态。创建克隆后,克隆将独立于其父流指针。
- 您可以克隆前缘、后缘或当前的克隆流指针。
- 添加克隆流指针会增加该特定帧的引用计数。有关引用计数的更多信息,请参阅流指针简介。
- 使用KsPinGetFirstCloneStreamPointer和KsStreamPointerGetNextClone枚举克隆流指针。
- 克隆一直存在,直到您通过调用KsStreamPointerDelete将其删除。当微型驱动器删除克隆时,AVStream会减少相应帧的引用计数。
先看两个结构体:
//kernel stream process
struct KSPSTREAM_POINTER {
LIST_ENTRY ListEntry;
LIST_ENTRY TimeoutListEntry;
LONGLONG TimeoutTime;
PFNKSSTREAMPOINTER CancelCallback;
PFNKSSTREAMPOINTER TimeoutCallback;
KSPSTREAM_POINTER_STATE State;
KSPSTREAM_POINTER_TYPE Type;
ULONG Stride;
PIKSQUEUE Queue;
PKSPFRAME_HEADER FrameHeader;
PKSPFRAME_HEADER FrameHeaderStarted;
KSSTREAM_POINTER Public; //KsPinGetLeadingEdgeStreamPointer
};
//kernel stream
struct KSSTREAM_POINTER
{
PVOID Context;
PKSPIN Pin;
PKSSTREAM_HEADER StreamHeader;
PKSSTREAM_POINTER_OFFSET Offset;
KSSTREAM_POINTER_OFFSET OffsetIn;
KSSTREAM_POINTER_OFFSET OffsetOut;
};
KSPSTREAM_POINTER是KS内部的结构体,其成员public是KSSTREAM_POINTER,供驱动开发者使用。当使用KsPinGetLeadingEdgeStreamPointer获取的就其实是public的指针,用于代指KSPSTREAM_POINTER。
KsStreamPointerClone函数的实现其实是通过Public的参数,创建KSPSTREAM_POINTER副本。
首先根据public获取KSPSTREAM_POINTER本体
PKSPSTREAM_POINTER StreamPointerToClone = CONTAINING_RECORD(StreamPointer,KSPSTREAM_POINTER,Public);
创建副本CKsQueue::CloneStreamPointer
PKSPSTREAM_POINTER streamPointer = (PKSPSTREAM_POINTER)
ExAllocatePoolWithTag( NonPagedPool, sizeof(KSPSTREAM_POINTER) + ContextSize, POOLTAG_STREAMPOINTER);
if (streamPointer)
{
RtlCopyMemory(streamPointer, StreamPointerToClone, sizeof(KSPSTREAM_POINTER));
streamPointer->Type = StreamPointerType;
if (m_InputData){
streamPointer->Public.Offset = &streamPointer->Public.OffsetIn;
}
else{
streamPointer->Public.Offset = &streamPointer->Public.OffsetOut;
}
streamPointer->TimeoutListEntry.Flink = NULL;
//申请的额外空间实始化为0
if (ContextSize) {
streamPointer->Public.Context = streamPointer + 1;
RtlZeroMemory(streamPointer->Public.Context,ContextSize);
}
//这里加入链表,在KsPinGetFirstCloneStreamPointer时又通过该链表获取
InsertTailList(&m_StreamPointers,&streamPointer->ListEntry);
}
最后新创建的KSPSTREAM_POINTER 返回其public指针
*CloneStreamPointer = &cloneStreamPointer->Public;
当该请求为输出管脚时(测试例程为相机时),则Offset = &OffsetOut
未处理数据时: