📄 capture.cpp
字号:
SPContext = reinterpret_cast <PSTREAM_POINTER_CONTEXT>
(ClonePointer -> Context);
SPContext -> BufferVirtual =
reinterpret_cast <PUCHAR> (
ClonePointer -> StreamHeader -> Data
);
}
} else {
ClonePointer = m_PreviousStreamPointer;
SPContext = reinterpret_cast <PSTREAM_POINTER_CONTEXT>
(ClonePointer -> Context);
Status = STATUS_SUCCESS;
}
//
// If the clone failed, likely we're out of resources. Break out
// of the loop for now. We may end up starving DMA.
//
if (!NT_SUCCESS (Status)) {
KsStreamPointerUnlock (Leading, FALSE);
break;
}
//
// Program the fake hardware. I would use Clone -> OffsetOut.*, but
// because of the optimization of one stream pointer per frame, it
// doesn't make complete sense.
//
ULONG MappingsUsed =
m_Device -> ProgramScatterGatherMappings (
&(SPContext -> BufferVirtual),
Leading -> OffsetOut.Mappings,
Leading -> OffsetOut.Remaining
);
//
// In order to keep one clone per frame and simplify the fake DMA
// 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -