KS相机驱动
+ -

KsStreamPointerClone

2025-02-27 33 0
  1. 多个流指针可以引用单个帧。要复制流指针,请调用KsStreamPointerClone。
  2. 流指针的最终副本称为流指针克隆。克隆是一个与父级完全相同的新流指针。最初,克隆引用相同的帧并具有相同的锁定状态。创建克隆后,克隆将独立于其父流指针。
  3. 您可以克隆前缘、后缘或当前的克隆流指针。
  4. 添加克隆流指针会增加该特定帧的引用计数。有关引用计数的更多信息,请参阅流指针简介。
  5. 使用KsPinGetFirstCloneStreamPointer和KsStreamPointerGetNextClone枚举克隆流指针。
  6. 克隆一直存在,直到您通过调用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
未处理数据时:
095703490546

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!