📄 capvbi.c
字号:
// Set the (local) discontinuity flag
// This will cause the next packet processed to have the
// KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY flag set.
pStrmEx->fDiscontinuity = TRUE;
}
// Figure out when to capture the next frame
pStrmEx->QST_NextFrame += pStrmEx->pVBIStreamFormat->ConfigCaps.MinFrameInterval;
} // endif time to capture a frame
} // endif we're running
}
/*
** VBITimerRoutine()
**
** A timer has been created based on the requested capture interval.
** This is the callback routine for this timer event.
**
** Note: Devices capable of using interrupts should always
** trigger capture on a VSYNC interrupt, and not use a timer.
**
** Arguments:
**
** Context - pointer to the stream extension
**
** Returns: nothing
**
** Side Effects: none
*/
VOID
STREAMAPI
VBITimerRoutine(
PVOID Context
)
{
PSTREAMEX pStrmEx = ((PSTREAMEX)Context);
PHW_DEVICE_EXTENSION pHwDevExt = pStrmEx->pHwDevExt;
int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
ULONG interval;
// If we're stopped and the timer is still running, just return.
// This will stop the timer.
if (pStrmEx->KSState == KSSTATE_STOP)
return;
// Calculate next interval
interval = (ULONG)(pStrmEx->pVBIStreamFormat->ConfigCaps.MinFrameInterval / 10);
interval /= 2; // Run at 2x noted rate for accuracy
// Capture a frame if it's time and we have a buffer
switch (StreamNumber) {
case STREAM_NABTS:
VBIhwCaptureRoutine(pStrmEx);
break;
case STREAM_CC:
VBIhwCaptureRoutine(pStrmEx);
break;
default:
case STREAM_VBI:
VBICaptureRoutine(pStrmEx);
break;
}
// Schedule the next timer event
StreamClassScheduleTimer (
pStrmEx->pStreamObject, // StreamObject
pHwDevExt, // HwDeviceExtension
interval, // Microseconds
VBITimerRoutine, // TimerRoutine
pStrmEx); // Context
}
/*
** VBISetState()
**
** Sets the current state for a given stream
**
** Arguments:
**
** pSrb - pointer to the stream request block for properties
**
** Returns:
**
** Side Effects: none
*/
VOID
STREAMAPI
VBISetState(PHW_STREAM_REQUEST_BLOCK pSrb)
{
PHW_DEVICE_EXTENSION pHwDevExt = pSrb->HwDeviceExtension;
PSTREAMEX pStrmEx = pSrb->StreamObject->HwStreamExtension;
int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
KSSTATE PreviousState;
//
// Remember the state we're transitioning away from
//
PreviousState = pStrmEx->KSState;
//
// Set the new state
//
pStrmEx->KSState = pSrb->CommandData.StreamState;
switch (pSrb->CommandData.StreamState)
{
case KSSTATE_STOP:
//
// The stream class will cancel all outstanding IRPs for us
// (but only if it is maintaining the queue ie. using Stream Class synchronization)
// Since Testcap is not using Stream Class synchronization, we must clear the queue here
VideoQueueCancelAllSRBs (pStrmEx);
pStrmEx->SentVBIInfoHeader = 0; // Send out a fresh one next RUN
DbgLogInfo(("TestCap: STATE Stopped, Stream=%d\n", StreamNumber));
break;
case KSSTATE_ACQUIRE:
//
// This is a KS only state, that has no correspondence in DirectShow
//
DbgLogInfo(("TestCap: STATE Acquire, Stream=%d\n", StreamNumber));
break;
case KSSTATE_PAUSE:
//
// On a transition to pause from acquire or stop, start our timer running.
//
if (PreviousState == KSSTATE_ACQUIRE || PreviousState == KSSTATE_STOP) {
// Zero the frame counters
pStrmEx->VBIFrameInfo.PictureNumber = 0;
pStrmEx->VBIFrameInfo.DropCount = 0;
pStrmEx->VBIFrameInfo.dwFrameFlags = 0;
// Setup the next timer callback
VBITimerRoutine(pStrmEx);
}
DbgLogInfo(("TestCap: STATE Pause, Stream=%d\n", StreamNumber));
break;
case KSSTATE_RUN:
//
// Begin Streaming.
//
// Reset the discontinuity flag
pStrmEx->fDiscontinuity = FALSE;
// Setting the NextFrame time to zero will cause the value to be
// reset from the stream time
pStrmEx->QST_NextFrame = 0;
DbgLogInfo(("TestCap: STATE Run, Stream=%d\n", StreamNumber));
break;
} // end switch (pSrb->CommandData.StreamState)
}
/*
** VBIReceiveCtrlPacket()
**
** Receives packet commands that control all the VBI (VBI/NABTS/CC) streams
**
** Arguments:
**
** pSrb - The stream request block for the VBI stream
**
** Returns: nothing
**
** Side Effects: none
*/
VOID
STREAMAPI
VBIReceiveCtrlPacket(
IN PHW_STREAM_REQUEST_BLOCK pSrb
)
{
PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
BOOL Busy;
//
// make sure we have a device extension and are at passive level
//
DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DEBUG_ASSERT(pHwDevExt != 0);
DbgLogInfo(("TestCap: Receiving %s Stream Control SRB %p, %x\n",
(StreamNumber == STREAM_VBI)? "VBI"
: (StreamNumber == STREAM_NABTS)? "NABTS"
: (StreamNumber == STREAM_CC)? "CC"
: "???",
pSrb,
pSrb->Command));
//
// If we're already processing an SRB, add it to the queue
//
Busy = AddToListIfBusy (
pSrb,
&pHwDevExt->AdapterSpinLock,
&pHwDevExt->ProcessingControlSRB [StreamNumber],
&pHwDevExt->StreamControlSRBList[StreamNumber]);
if (Busy) {
return;
}
do {
//
// Default to success
//
pSrb->Status = STATUS_SUCCESS;
//
// determine the type of packet.
//
switch (pSrb->Command)
{
case SRB_PROPOSE_DATA_FORMAT:
DbgLogInfo(("TestCap: Receiving SRB_PROPOSE_DATA_FORMAT SRB %p, StreamNumber= %d\n", pSrb, StreamNumber));
if (!(AdapterVerifyFormat (
pSrb->CommandData.OpenFormat,
pSrb->StreamObject->StreamNumber)))
{
pSrb->Status = STATUS_NO_MATCH;
}
break;
case SRB_SET_DATA_FORMAT:
DbgLogInfo(("TestCap: SRB_SET_DATA_FORMAT"));
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
case SRB_GET_DATA_FORMAT:
DbgLogInfo(("TestCap: SRB_GET_DATA_FORMAT"));
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
case SRB_SET_STREAM_STATE:
VBISetState(pSrb);
break;
case SRB_GET_STREAM_STATE:
VideoGetState(pSrb);
break;
case SRB_GET_STREAM_PROPERTY:
VideoGetProperty(pSrb);
break;
case SRB_INDICATE_MASTER_CLOCK:
VideoIndicateMasterClock(pSrb);
break;
default:
//
// invalid / unsupported command. Fail it as such
//
TRAP;
pSrb->Status = STATUS_NOT_IMPLEMENTED;
}
CompleteStreamSRB (pSrb);
//
// See if there's anything else on the queue
//
Busy = RemoveFromListIfAvailable (
&pSrb,
&pHwDevExt->AdapterSpinLock,
&pHwDevExt->ProcessingControlSRB [StreamNumber],
&pHwDevExt->StreamControlSRBList[StreamNumber]);
} while (Busy);
}
/*
** VBIReceiveDataPacket()
**
** Receives VBI data packet commands on the output streams
**
** Arguments:
**
** pSrb - Stream request block for the VBI stream
**
** Returns: nothing
**
** Side Effects: none
*/
VOID
STREAMAPI
VBIReceiveDataPacket(
IN PHW_STREAM_REQUEST_BLOCK pSrb
)
{
PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
int StreamNumber = pSrb->StreamObject->StreamNumber;
//
// make sure we have a device extension and are at passive level
//
DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DEBUG_ASSERT(pHwDevExt != 0);
DbgLogTrace(("'TestCap: Receiving VBI Stream Data SRB %p, %x\n", pSrb, pSrb->Command));
//
// Default to success
//
pSrb->Status = STATUS_SUCCESS;
//
// determine the type of packet.
//
switch (pSrb->Command){
case SRB_READ_DATA:
// Rule:
// Only accept read requests when in either the Pause or Run
// States. If Stopped, immediately return the SRB.
if (pStrmEx->KSState == KSSTATE_STOP) {
CompleteStreamSRB (pSrb);
break;
}
//
// Put this read request on the pending queue
//
VideoQueueAddSRB (pSrb);
// Since another thread COULD HAVE MODIFIED THE STREAM STATE
// in the midst of adding it to the queue, check the stream
// state again, and cancel the SRB if necessary. Note that
// this race condition was NOT handled in the original DDK
// release of testcap!
if (pStrmEx->KSState == KSSTATE_STOP) {
VideoQueueCancelOneSRB (
pStrmEx,
pSrb);
}
break;
default:
//
// invalid / unsupported command. Fail it as such
//
TRAP;
pSrb->Status = STATUS_NOT_IMPLEMENTED;
CompleteStreamSRB (pSrb);
} // switch (pSrb->Command)
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -