📄 filter.cpp
字号:
Return Value:
None
--*/
{
PAGED_CODE();
//
// Initialize any variables used by the timer DPC.
//
m_Tick = 0;
m_TimerInterval = TimerInterval;
KeQuerySystemTime (&m_StartTime);
//
// Schedule the DPC to happen one frame time from now.
//
LARGE_INTEGER NextTime;
NextTime.QuadPart = m_StartTime.QuadPart + m_TimerInterval;
KeSetTimer (&m_Timer, NextTime, &m_TimerDpc);
}
/*************************************************/
void
CCaptureFilter::
StopDPC (
)
/*++
Routine Description:
Stop the timer DPC from firing. After this routine returns, there is
a guarantee that no more timer DPC's will fire and no more processing
attempts will occur. Note that this routine does block.
Arguments:
None
Return Value:
None
--*/
{
PAGED_CODE();
m_StoppingDPC = TRUE;
KeWaitForSingleObject (
&m_StopDPCEvent,
Suspended,
KernelMode,
FALSE,
NULL
);
ASSERT (m_StoppingDPC == FALSE);
}
/**************************************************************************
LOCKED CODE
**************************************************************************/
#ifdef ALLOC_PRAGMA
#pragma code_seg()
#endif // ALLOC_PRAGMA
LONGLONG
CCaptureFilter::
GetTimerInterval (
)
/*++
Routine Description:
Return the timer interval being used to fire DPC's.
Arguments:
None
Return Value:
The timer interval being used to fire DPC's.
--*/
{
return m_TimerInterval;
}
/*************************************************/
NTSTATUS
CCaptureFilter::
Process (
IN PKSPROCESSPIN_INDEXENTRY ProcessPinsIndex
)
/*++
Routine Description:
This is the processing function for the capture filter. It is responsible
for copying synthesized image data into the image buffers. The timer DPC
will attempt to trigger processing (and hence indirectly call this routine)
to trigger a capture.
Arguments:
ProcessPinsIndex -
Contains a pointer to an array of process pin index entries. This
array is indexed by pin ID. An index entry indicates the number
of pin instances for the corresponding filter type and points to the
first corresponding process pin structure in the ProcessPins array.
This allows the process pin structure to be quickly accessed by pin ID
when the number of instances per type is not known in advance.
Return Value:
Indication of whether more processing should be done if frames are
available. A value of STATUS_PENDING indicates that processing should not
continue even if frames are available on all required queues.
STATUS_SUCCESS indicates processing should continue if frames are available
on all required queues.
--*/
{
//
// The audio and video pins do not necessarily need to exist (one could
// be capturing video w/o audio or vice-versa). Do not assume the
// existence by checking Index[ID].Pins[0]. Always check the Count
// field first.
//
PKSPROCESSPIN VideoPin = NULL;
CCapturePin *VidCapPin = NULL;
PKSPROCESSPIN AudioPin = NULL;
CCapturePin *AudCapPin = NULL;
ULONG VidCapDrop = 0;
ULONG AudCapDrop = (ULONG)-1;
if (ProcessPinsIndex [VIDEO_PIN_ID].Count != 0) {
//
// There can be at most one instance via the possible instances field,
// so the below is safe.
//
VideoPin = ProcessPinsIndex [VIDEO_PIN_ID].Pins [0];
VidCapPin =
reinterpret_cast <CCapturePin *> (VideoPin -> Pin -> Context);
}
//
// The audio pin only exists on the filter if the wave object does.
// They're tied together at filter create time.
//
if (m_WaveObject && ProcessPinsIndex [m_AudioPinId].Count != 0) {
//
// There can be at most one instance via the possible instances field,
// so the below is safe.
//
AudioPin = ProcessPinsIndex [m_AudioPinId].Pins [0];
AudCapPin =
reinterpret_cast <CCapturePin *> (AudioPin -> Pin -> Context);
}
if (VidCapPin) {
VidCapDrop = VidCapPin -> QueryFrameDrop ();
}
if (AudCapPin) {
AudCapDrop = AudCapPin -> QueryFrameDrop ();
}
//
// If there's a video pin around, trigger capture on it. We call the
// pin object to actually synthesize the frame; however, we could just
// as easily have done that here.
//
if (VidCapPin) {
//
// This is used to notify the pin how many frames have been dropped
// on each pin to allow that to be rendered.
//
VidCapPin -> NotifyDrops (VidCapDrop, AudCapDrop);
VidCapPin -> CaptureFrame (VideoPin, m_Tick);
}
//
// If there's an audio pin around, trigger capture on it. Since the
// audio capture pin isn't necessary for capture, there might be an
// instance which is connected and is in the stop state when we get
// called [there will never be one in acquire or pause since we specify
// KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY]. Don't bother triggering capture
// on the pin unless it's actually running.
//
// On DX8.x platforms, the Pin -> ClientState field does not exist.
// Hence, we check the state we maintain ourselves. DeviceState is not
// the right thing to check here.
//
if (AudioPin && AudCapPin -> GetState () == KSSTATE_RUN) {
AudCapPin -> CaptureFrame (AudioPin, m_Tick);
}
//
// STATUS_PENDING indicates that we do not want to be called back if
// there is more data available. We only want to trigger processing
// (and hence capture) on the timer ticks.
//
return STATUS_PENDING;
}
/*************************************************/
void
CCaptureFilter::
TimerDpc (
)
/*++
Routine Description:
This is the timer function for our timer (bridged to from TimerRoutine
in the context of the appropriate CCaptureFilter). It is called every
1/Nth of a second as specified in StartDpc() to trigger capture of a video
frame.
Arguments:
None
Return Value:
None
--*/
{
//
// Increment the tick counter. This keeps track of the number of ticks
// that have happened since the timer DPC started running. Note that the
// timer DPC starts running before the pins go into run state and this
// variable gets incremented from the original start point.
//
m_Tick++;
//
// Trigger processing on the filter. Since the filter is prepared to
// run at DPC, we do not request asynchronous processing. Thus, if
// possible, processing will occur in the context of this DPC.
//
KsFilterAttemptProcessing (m_Filter, FALSE);
//
// Reschedule the timer if the hardware isn't being stopped.
//
if (!m_StoppingDPC) {
LARGE_INTEGER NextTime;
NextTime.QuadPart = m_StartTime.QuadPart +
(m_TimerInterval * (m_Tick + 1));
KeSetTimer (&m_Timer, NextTime, &m_TimerDpc);
} else {
//
// If another thread is waiting on the DPC to stop running, raise
// the stop event and clear the flag.
//
m_StoppingDPC = FALSE;
KeSetEvent (&m_StopDPCEvent, IO_NO_INCREMENT, FALSE);
}
}
/**************************************************************************
DESCRIPTOR AND DISPATCH LAYOUT
**************************************************************************/
GUID g_PINNAME_VIDEO_CAPTURE = {STATIC_PINNAME_VIDEO_CAPTURE};
//
// CaptureFilterCategories:
//
// The list of category GUIDs for the capture filter.
//
const
GUID
CaptureFilterCategories [CAPTURE_FILTER_CATEGORIES_COUNT] = {
STATICGUIDOF (KSCATEGORY_VIDEO),
STATICGUIDOF (KSCATEGORY_CAPTURE)
};
//
// CaptureFilterPinDescriptors:
//
// The list of pin descriptors on the capture filter.
//
const
KSPIN_DESCRIPTOR_EX
CaptureFilterPinDescriptors [CAPTURE_FILTER_PIN_COUNT] = {
//
// Video Capture Pin
//
{
&VideoCapturePinDispatch,
NULL,
{
NULL, // Interfaces (NULL, 0 == default)
0,
NULL, // Mediums (NULL, 0 == default)
0,
SIZEOF_ARRAY (VideoCapturePinDataRanges), // Range Count
VideoCapturePinDataRanges, // Ranges
KSPIN_DATAFLOW_OUT, // Dataflow
KSPIN_COMMUNICATION_BOTH, // Communication
&KSCATEGORY_VIDEO, // Category
&g_PINNAME_VIDEO_CAPTURE, // Name
0 // Reserved
},
KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING | // Flags
KSPIN_FLAG_DO_NOT_INITIATE_PROCESSING |
KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY,
1, // Instances Possible
1, // Instances Necessary
&VideoCapturePinAllocatorFraming, // Allocator Framing
reinterpret_cast <PFNKSINTERSECTHANDLEREX>
(CVideoCapturePin::IntersectHandler)
}
};
//
// CaptureFilterDispatch:
//
// This is the dispatch table for the capture filter. It provides notification
// of creation, closure, processing, and resets.
//
const
KSFILTER_DISPATCH
CaptureFilterDispatch = {
CCaptureFilter::DispatchCreate, // Filter Create
NULL, // Filter Close
CCaptureFilter::DispatchProcess, // Filter Process
NULL // Filter Reset
};
//
// CaptureFilterDescription:
//
// The descriptor for the capture filter. We don't specify any topology
// since there's only one pin on the filter. Realistically, there would
// be some topological relationships here because there would be input
// pins from crossbars and the like.
//
const
KSFILTER_DESCRIPTOR
CaptureFilterDescriptor = {
&CaptureFilterDispatch, // Dispatch Table
NULL, // Automation Table
KSFILTER_DESCRIPTOR_VERSION, // Version
KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING,// Flags
&KSNAME_Filter, // Reference GUID
DEFINE_KSFILTER_PIN_DESCRIPTORS (CaptureFilterPinDescriptors),
DEFINE_KSFILTER_CATEGORIES (CaptureFilterCategories),
DEFINE_KSFILTER_NODE_DESCRIPTORS_NULL,
DEFINE_KSFILTER_DEFAULT_CONNECTIONS,
NULL // Component ID
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -