📄 filter.cpp
字号:
_DbgPrintF(DEBUGLVL_BLAB,("FilterClose"));
PAGED_CODE();
ASSERT(Filter);
ASSERT(Irp);
CCapFilter *filter = reinterpret_cast<CCapFilter *>(Filter->Context);
ASSERT(filter);
delete filter;
return STATUS_SUCCESS;
}
NTSTATUS
CCapFilter::
CaptureVideoInfoHeader(
IN PKS_VIDEOINFOHEADER VideoInfoHeader
)
/*++
Routine Description:
Retrieve a copy of the Video Header Info
Arguments:
IN PKS_VIDEOINFOHEADER VideoInfoHeader -
Video Info Header copy
Return:
STATUS_SUCCESS
--*/
{
_DbgPrintF(DEBUGLVL_BLAB,("CaptureVideoInfoHeader"));
//
// There could be one of these already if a pin was created and closed.
//
if (m_VideoInfoHeader) {
ExFreePool(m_VideoInfoHeader);
}
m_VideoInfoHeader =
(PKS_VIDEOINFOHEADER)
ExAllocatePoolWithTag(
NonPagedPool,
KS_SIZE_VIDEOHEADER( VideoInfoHeader ),
'fChS' );
NTSTATUS Status;
if (m_VideoInfoHeader) {
RtlCopyMemory(
m_VideoInfoHeader,
VideoInfoHeader,
KS_SIZE_VIDEOHEADER( VideoInfoHeader ) );
Status = STATUS_SUCCESS;
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
return Status;
}
static const WCHAR ClockTypeName[] = KSSTRING_Clock;
NTSTATUS
VideoPinCreate(
IN OUT PKSPIN Pin,
IN PIRP Irp
)
/*++
Routine Description:
Handle specific processing on Video Pin creation
Arguments:
IN OUT PKSPIN Pin -
Pin instance data
IN PIRP Irp -
Creation request
Return:
STATUS_SUCCESS
--*/
{
_DbgPrintF(DEBUGLVL_BLAB,("VideoPinCreate"));
NTSTATUS status = STATUS_SUCCESS;
_DbgPrintF(DEBUGLVL_VERBOSE,("PinCreate filter %d as %s", Pin->Id, (Pin->Communication == KSPIN_COMMUNICATION_SOURCE) ? "SOURCE" : "SINK"));
PAGED_CODE();
ASSERT(Pin);
ASSERT(Irp);
//
// Indicate the extended header size.
//
Pin->StreamHeaderSize = sizeof(KSSTREAM_HEADER) + sizeof(KS_FRAME_INFO);
//
// Use the same context as the filter (the shell copies this for us).
//
CCapFilter *filter = reinterpret_cast<CCapFilter *>(Pin->Context);
status = filter->CaptureVideoInfoHeader(&(PKS_DATAFORMAT_VIDEOINFOHEADER(Pin->ConnectionFormat )->VideoInfoHeader));
if (NT_SUCCESS(status))
{
status = KsEdit(Pin,&Pin->Descriptor,'aChS');
if (NT_SUCCESS(status))
{
status = KsEdit(Pin,&Pin->Descriptor->AllocatorFraming,'aChS');
}
if (NT_SUCCESS(status))
{
PKS_VIDEOINFOHEADER VideoInfoHeader = &(PKS_DATAFORMAT_VIDEOINFOHEADER(Pin->ConnectionFormat)->VideoInfoHeader);
PKSALLOCATOR_FRAMING_EX framing = const_cast<PKSALLOCATOR_FRAMING_EX>(Pin->Descriptor->AllocatorFraming);
framing->FramingItem[0].Frames = 2;
framing->FramingItem[0].PhysicalRange.MinFrameSize = VideoInfoHeader->bmiHeader.biSizeImage;
framing->FramingItem[0].PhysicalRange.MaxFrameSize = VideoInfoHeader->bmiHeader.biSizeImage;
framing->FramingItem[0].PhysicalRange.Stepping = 0;
framing->FramingItem[0].FramingRange.Range.MinFrameSize = VideoInfoHeader->bmiHeader.biSizeImage;
framing->FramingItem[0].FramingRange.Range.MaxFrameSize = VideoInfoHeader->bmiHeader.biSizeImage;
framing->FramingItem[0].FramingRange.Range.Stepping = 0;
}
}
return status;
}
NTSTATUS
AudioPinCreate(
IN OUT PKSPIN Pin,
IN PIRP Irp
)
/*++
Routine Description:
Handle specific processing on Audio Pin creation
Arguments:
IN OUT PKSPIN Pin -
Pin instance data
IN PIRP Irp -
Creation request
Return:
STATUS_SUCCESS
--*/
{
_DbgPrintF(DEBUGLVL_BLAB,("AudioPinCreate filter %d as %s",Pin->Id,(Pin->Communication == KSPIN_COMMUNICATION_SOURCE) ? "SOURCE" : "SINK"));
PAGED_CODE();
ASSERT(Pin);
ASSERT(Irp);
return STATUS_SUCCESS;
}
NTSTATUS
CCapFilter::CancelTimer()
{
//
// let Timer's Dpc we are stopped and cancel the timer
// (REVIEW - we should be sure no Dpc is pending when
// this function exits)
//
InterlockedExchange(&m_Active,FALSE);
if (InterlockedExchange(&m_TimerScheduled,FALSE))
{
_DbgPrintF(DEBUGLVL_TERSE,("cancelling timer"));
KeCancelTimer(&m_TimerObject);
_DbgPrintF(DEBUGLVL_TERSE,("timer cancelled"));
return(STATUS_SUCCESS);
}
return(!STATUS_SUCCESS);
}
NTSTATUS
CCapFilter::Run(
IN PKSPIN Pin,
IN KSSTATE FromState
)
/*++
Routine Description:
Handle pin statetransition to Run state
Arguments:
IN PKSPIN Pin -
Pin instance data
IN KSSTATE FromState -
Current pin state
Return:
STATUS_SUCCESS
--*/
{
_DbgPrintF(DEBUGLVL_BLAB,("filter to KSSTATE_RUN Pin->Id:%d From:%d", Pin->Id, FromState));
#if 0
//
// initialize timer to drive transfer
//
InterlockedExchange(&m_Active, TRUE);
//
// comput transfer time points and start timer for first transfer
//
LARGE_INTEGER NextTime;
KeQuerySystemTime(&NextTime);
//
// Fix the System time against the Physical time on the clock.
//
////KsPinSetPinClockState(Pin,KSSTATE_RUN,NextTime.QuadPart);
//
// Determine how long the filter was not running in order to
// update the start time, and therefore what the next frame
// timestamp should be. The start and stop times are initially
// zeroed, which means the start time initially is set to the
// current system time.
//
m_llStartTime = NextTime.QuadPart - (m_iTick * m_VideoInfoHeader->AvgTimePerFrame);
//
// Set the offset to production of the first frame. This is produced
// at the end of the period for which the frame is stamped, though it
// could be produced earlier of course, even at the beginning of the
// period.
//
NextTime.QuadPart = m_llStartTime + m_VideoInfoHeader->AvgTimePerFrame;
KeSetTimer(&m_TimerObject,NextTime,&m_TimerDpc);
#endif
return STATUS_SUCCESS;
}
NTSTATUS
CCapFilter::Pause(
IN PKSPIN Pin,
IN KSSTATE FromState
)
/*++
Routine Description:
Handle pin statetransition to Run state
Arguments:
IN PKSPIN Pin -
Pin instance data
IN KSSTATE FromState -
Current pin state
Return:
STATUS_SUCCESS
--*/
{
ASSERT(Pin);
_DbgPrintF(DEBUGLVL_BLAB,("filter to KSSTATE_PAUSE Pin->Id:%d From:%d", Pin->Id, FromState));
if (FromState == KSSTATE_RUN)
{
CancelTimer();
//
// Unfix the System time from the Physical time on the clock.
// Ignores partial frame times.
//
// KsPinSetPinClockState(
// Pin,
// KSSTATE_PAUSE,
// m_iTick * m_VideoInfoHeader->AvgTimePerFrame);
}
else
{
//
// initialize timer to drive transfer
//
InterlockedExchange(&m_Active, TRUE);
//
// comput transfer time points and start timer for first transfer
//
LARGE_INTEGER NextTime;
KeQuerySystemTime(&NextTime);
//
// Fix the System time against the Physical time on the clock.
//
////KsPinSetPinClockState(Pin,KSSTATE_RUN,NextTime.QuadPart);
//
// Determine how long the filter was not running in order to
// update the start time, and therefore what the next frame
// timestamp should be. The start and stop times are initially
// zeroed, which means the start time initially is set to the
// current system time.
//
m_llStartTime = NextTime.QuadPart - (m_iTick * m_VideoInfoHeader->AvgTimePerFrame);
//
// Set the offset to production of the first frame. This is produced
// at the end of the period for which the frame is stamped, though it
// could be produced earlier of course, even at the beginning of the
// period.
//
NextTime.QuadPart = m_llStartTime + m_VideoInfoHeader->AvgTimePerFrame;
KeSetTimer(&m_TimerObject,NextTime,&m_TimerDpc);
_DbgPrintF(DEBUGLVL_BLAB,("CCapFilter::Pause KeSetTimer(%x, %d, %x)", &m_TimerObject, NextTime, &m_TimerDpc));
}
return STATUS_SUCCESS;
}
NTSTATUS
CCapFilter::Stop(
IN PKSPIN Pin,
IN KSSTATE FromState
)
/*++
Routine Description:
Handle pin state transition to Stop
Arguments:
IN PKSPIN Pin -
Pin instance data
IN KSSTATE FromState -
Current pin state
Return:
STATUS_SUCCESS
--*/
{
_DbgPrintF(DEBUGLVL_BLAB,("filter to KSSTATE_STOP Pin->Id:%d From:%d", Pin->Id, FromState));
CancelTimer();
//
// reinitialize transfer counters
//
m_iTick = 0;
m_ullNextAudioPos = 0;
m_ulAudioBufferOffset = 0;
m_FrameInfo.PictureNumber = 0;
m_FrameInfo.DropCount = 0;
m_ulAudioDroppedFrames = 0;
m_ulVideoDroppedFrames = 0;
//
// dump debug timestamps
//
for (ULONG iTs = 0; iTs < m_iTimestamp; iTs++) {
DbgPrint(
"TS[%lu] = %I64d, %I64d, %I64d\n",
iTs,
m_rgTimestamps[iTs].Abs,
m_rgTimestamps[iTs].Rel,
m_rgTimestamps[iTs].Int);
}
m_iTimestamp = 0;
return STATUS_SUCCESS;
}
NTSTATUS
PinSetDeviceState(
IN PKSPIN Pin,
IN KSSTATE ToState,
IN KSSTATE FromState
)
/*++
Routine Description:
Handle pin state transitions
Arguments:
IN PKSPIN Pin -
Pin instance data
IN KSSTATE ToState -
State to be set on pin
IN KSSTATE FromState -
Current pin state
Return:
STATUS_SUCCESS
--*/
{
NTSTATUS Status;
_DbgPrintF(DEBUGLVL_BLAB,("PinSetDeviceState Pin->Id:%d From:%d To:%d",Pin->Id, FromState, ToState));
PAGED_CODE();
ASSERT(Pin);
CCapFilter *filter = reinterpret_cast<CCapFilter *>(Pin->Context);
Status = STATUS_SUCCESS;
switch (ToState)
{
case KSSTATE_STOP:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -