📄 capture.cpp
字号:
// logic, make a check to see if we completely used the mappings in
// the leading edge. Set a flag.
//
if (MappingsUsed == Leading -> OffsetOut.Remaining) {
m_PreviousStreamPointer = NULL;
} else {
m_PreviousStreamPointer = ClonePointer;
}
if (MappingsUsed) {
//
// If any mappings were added to scatter / gather queues,
// advance the leading edge by that number of mappings. If
// we run off the end of the queue, Status will be
// STATUS_DEVICE_NOT_READY. Otherwise, the leading edge will
// point to a new frame. The previous one will not have been
// dismissed (unless "DMA" completed) since there's a clone
// pointer referencing the frames.
//
Status =
KsStreamPointerAdvanceOffsets (
Leading,
0,
MappingsUsed,
FALSE
);
} else {
//
// The hardware was incapable of adding more entries. The S/G
// table is full.
//
Status = STATUS_PENDING;
break;
}
}
//
// If the leading edge failed to lock (this is always possible, remember
// that locking CAN occassionally fail), don't blow up passing NULL
// into KsStreamPointerUnlock. Also, set m_PendIo to kick us later...
//
if (!Leading) {
m_PendIo = TRUE;
//
// If the lock failed, there's no point in getting called back
// immediately. The lock could fail due to insufficient memory,
// etc... In this case, we don't want to get called back immediately.
// Return pending. The m_PendIo flag will cause us to get kicked
// later.
//
Status = STATUS_PENDING;
}
//
// If we didn't run the leading edge off the end of the queue, unlock it.
//
if (NT_SUCCESS (Status) && Leading) {
KsStreamPointerUnlock (Leading, FALSE);
} else {
//
// DEVICE_NOT_READY indicates that the advancement ran off the end
// of the queue. We couldn't lock the leading edge.
//
if (Status == STATUS_DEVICE_NOT_READY) Status = STATUS_SUCCESS;
}
//
// If we failed with something that requires pending, set the pending I/O
// flag so we know we need to start it again in a completion DPC.
//
if (!NT_SUCCESS (Status) || Status == STATUS_PENDING) {
m_PendIo = TRUE;
}
return Status;
}
/*************************************************/
NTSTATUS
CCapturePin::
CleanupReferences (
)
/*++
Routine Description:
Clean up any references we're holding on frames after we abruptly
stop the hardware.
Arguments:
None
Return Value:
Success / Failure
--*/
{
PAGED_CODE();
PKSSTREAM_POINTER Clone = KsPinGetFirstCloneStreamPointer (m_Pin);
PKSSTREAM_POINTER NextClone = NULL;
//
// Walk through the clones, deleting them, and setting DataUsed to
// zero since we didn't use any data!
//
while (Clone) {
NextClone = KsStreamPointerGetNextClone (Clone);
Clone -> StreamHeader -> DataUsed = 0;
KsStreamPointerDelete (Clone);
Clone = NextClone;
}
return STATUS_SUCCESS;
}
/*************************************************/
NTSTATUS
CCapturePin::
SetState (
IN KSSTATE ToState,
IN KSSTATE FromState
)
/*++
Routine Description:
This is called when the caputre pin transitions state. The routine
attempts to acquire / release any hardware resources and start up
or shut down capture based on the states we are transitioning to
and away from.
Arguments:
ToState -
The state we're transitioning to
FromState -
The state we're transitioning away from
Return Value:
Success / Failure
--*/
{
PAGED_CODE();
NTSTATUS Status = STATUS_SUCCESS;
switch (ToState) {
case KSSTATE_STOP:
//
// First, stop the hardware if we actually did anything to it.
//
if (m_HardwareState != HardwareStopped) {
Status = m_Device -> Stop ();
ASSERT (NT_SUCCESS (Status));
m_HardwareState = HardwareStopped;
}
//
// We've stopped the "fake hardware". It has cleared out
// it's scatter / gather tables and will no longer be
// completing clones. We had locks on some frames that were,
// however, in hardware. This will clean them up. An
// alternative location would be in the reset dispatch.
// Note, however, that the reset dispatch can occur in any
// state and this should be understood.
//
// Some hardware may fill all S/G mappings before stopping...
// in this case, you may not have to do this. The
// "fake hardware" here simply stops filling mappings and
// cleans its scatter / gather tables out on the Stop call.
//
Status = CleanupReferences ();
//
// Release any hardware resources related to this pin.
//
if (m_AcquiredResources) {
//
// If we got an interface to the clock, we must release it.
//
if (m_Clock) {
m_Clock -> Release ();
m_Clock = NULL;
}
m_Device -> ReleaseHardwareResources (
);
m_AcquiredResources = FALSE;
}
break;
case KSSTATE_ACQUIRE:
//
// Acquire any hardware resources related to this pin. We should
// only acquire them here -- **NOT** at filter create time.
// This means we do not fail creation of a filter because of
// limited hardware resources.
//
if (FromState == KSSTATE_STOP) {
Status = m_Device -> AcquireHardwareResources (
this,
m_VideoInfoHeader
);
if (NT_SUCCESS (Status)) {
m_AcquiredResources = TRUE;
//
// Attempt to get an interface to the master clock.
// This will fail if one has not been assigned. Since
// one must be assigned while the pin is still in
// KSSTATE_STOP, this is a guranteed method of getting
// the clock should one be assigned.
//
if (!NT_SUCCESS (
KsPinGetReferenceClockInterface (
m_Pin,
&m_Clock
)
)) {
//
// If we could not get an interface to the clock,
// don't use one.
//
m_Clock = NULL;
}
} else {
m_AcquiredResources = FALSE;
}
} else {
//
// Standard transport pins will always receive transitions in
// +/- 1 manner. This means we'll always see a PAUSE->ACQUIRE
// transition before stopping the pin.
//
// The below is done because on DirectX 8.0, when the pin gets
// a message to stop, the queue is inaccessible. The reset
// which comes on every stop happens after this (at which time
// the queue is inaccessible also). So, for compatibility with
// DirectX 8.0, I am stopping the "fake" hardware at this
// point and cleaning up all references we have on frames. See
// the comments above regarding the CleanupReferences call.
//
// If this sample were targeting XP only, the below code would
// not be here. Again, I only do this so the sample does not
// hang when it is stopped running on a configuration such as
// Win2K + DX8.
//
if (m_HardwareState != HardwareStopped) {
Status = m_Device -> Stop ();
ASSERT (NT_SUCCESS (Status));
m_HardwareState = HardwareStopped;
}
Status = CleanupReferences ();
}
break;
case KSSTATE_PAUSE:
//
// Stop the hardware simulation if we're coming down from run.
//
if (FromState == KSSTATE_RUN) {
Status = m_Device -> Pause (TRUE);
if (NT_SUCCESS (Status)) {
m_HardwareState = HardwarePaused;
}
}
break;
case KSSTATE_RUN:
//
// Start the hardware simulation or unpause it depending on
// whether we're initially running or we've paused and restarted.
//
if (m_HardwareState == HardwarePaused) {
Status = m_Device -> Pause (FALSE);
} else {
Status = m_Device -> Start ();
}
if (NT_SUCCESS (Status)) {
m_HardwareState = HardwareRunning;
}
break;
}
return Status;
}
/*************************************************/
NTSTATUS
CCapturePin::
IntersectHandler (
IN PKSFILTER Filter,
IN PIRP Irp,
IN PKSP_PIN PinInstance,
IN PKSDATARANGE CallerDataRange,
IN PKSDATARANGE DescriptorDataRange,
IN ULONG BufferSize,
OUT PVOID Data OPTIONAL,
OUT PULONG DataSize
)
/*++
Routine Description:
This routine handles video pin intersection queries by determining the
intersection between two data ranges.
Arguments:
Filter -
Contains a void pointer to the filter structure.
Irp -
Contains a pointer to the data intersection property request.
PinInstance -
Contains a pointer to a structure indicating the pin in question.
CallerDataRange -
Contains a pointer to one of the data ranges supplied by the client
in the data intersection request. The format type, subtype and
specifier are compatible with the DescriptorDataRange.
DescriptorDataRange -
Contains a pointer to one of the data ranges from the pin descriptor
for the pin in question. The format type, subtype and specifier are
compatible with the CallerDataRange.
BufferSize -
Contains the size in bytes of the buffer pointed to by the Data
argument. For size queries, this value will be zero.
Data -
Optionally contains a pointer to the buffer to contain the data
format structure representing the best format in the intersection
of the two data ranges. For size queries, this pointer will be
NULL.
DataSize -
Contains a pointer to the location at which to deposit the size
of the data format. This information is supplied by the function
when the format is actually delivered and in response to size
queries.
Return Value:
STATUS_SUCCESS if there is an intersection and it fits in the supplied
buffer, STATUS_BUFFER_OVERFLOW for successful size queries,
STATUS_NO_MATCH if the intersection is empty, or
STATUS_BUFFER_TOO_SMALL if the supplied buffer is too small.
--*/
{
PAGED_CODE();
const GUID VideoInfoSpecifier =
{STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VIDEOINFO)};
ASSERT(Filter);
ASSERT(Irp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -