📄 capvideo.c
字号:
DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DEBUG_ASSERT(pHwDevExt!=NULL);
DbgLogInfo(("TestCap: Receiving Tuner packet SRB %p, %x\n", pSrb, pSrb->Command));
//
// Default to success
//
pSrb->Status = STATUS_SUCCESS;
//
// determine the type of packet.
//
switch (pSrb->Command){
case SRB_WRITE_DATA:
//
// This data packet contains the channel change information
// passed on the AnalogVideoIn stream. Devices which support
// VBI data streams need to pass this info on their output pins.
//
if (pDataPacket->FrameExtent == sizeof (KS_TVTUNER_CHANGE_INFO)) {
RtlCopyMemory(
&pHwDevExt->TVTunerChangeInfo,
pDataPacket->Data,
sizeof (KS_TVTUNER_CHANGE_INFO));
}
CompleteStreamSRB (pSrb);
break;
default:
//
// invalid / unsupported command. Fail it as such
//
TRAP;
pSrb->Status = STATUS_NOT_IMPLEMENTED;
CompleteStreamSRB (pSrb);
} // switch (pSrb->Command)
}
/*
** AnalogVideoReceiveCtrlPacket()
**
** Receives packet commands that control the Analog Video stream
**
** Arguments:
**
** pSrb - The stream request block for the Video stream
**
** Returns: nothing
**
** Side Effects: none
*/
VOID
STREAMAPI
AnalogVideoReceiveCtrlPacket(
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 we are at passive level
//
DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DEBUG_ASSERT(pHwDevExt!=NULL);
DbgLogTrace(("TestCap: Receiving Analog Stream Control SRB %p, %x\n", 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_STREAM_STATE:
//
// Don't use VideoSetState, since we don't want to start another
// timer running
//
pStrmEx->KSState = pSrb->CommandData.StreamState;
DbgLogInfo(("TestCap: STATE=%d, Stream=%d\n", pStrmEx->KSState, StreamNumber));
break;
case SRB_GET_STREAM_STATE:
VideoGetState(pSrb);
break;
case SRB_GET_STREAM_PROPERTY:
VideoGetProperty(pSrb);
break;
case SRB_INDICATE_MASTER_CLOCK:
//
// Assigns a clock to a stream
//
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 );
}
/*
** CompleteStreamSRB ()
**
** This routine is called when a packet is being completed.
**
** Arguments:
**
** pSrb - pointer to the request packet to be completed
**
** Returns:
**
** Side Effects: none
*/
VOID
STREAMAPI
CompleteStreamSRB (
IN PHW_STREAM_REQUEST_BLOCK pSrb
)
{
DbgLogTrace(("TestCap: Completing Stream SRB %p\n", pSrb));
StreamClassStreamNotification(
StreamRequestComplete,
pSrb->StreamObject,
pSrb);
}
/*
** VideoGetProperty()
**
** Routine to process video property requests
**
** Arguments:
**
** pSrb - pointer to the stream request block for properties
**
** Returns:
**
** Side Effects: none
*/
VOID
STREAMAPI
VideoGetProperty(
PHW_STREAM_REQUEST_BLOCK pSrb
)
{
PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
if (IsEqualGUID (&KSPROPSETID_Connection, &pSPD->Property->Set)) {
VideoStreamGetConnectionProperty (pSrb);
}
else if (IsEqualGUID (&PROPSETID_VIDCAP_DROPPEDFRAMES, &pSPD->Property->Set)) {
VideoStreamGetDroppedFramesProperty (pSrb);
}
else {
pSrb->Status = STATUS_NOT_IMPLEMENTED;
}
}
/*
** VideoSetProperty()
**
** Routine to process video property requests
**
** Arguments:
**
** pSrb - pointer to the stream request block for properties
**
** Returns:
**
** Side Effects: none
*/
VOID
STREAMAPI
VideoSetProperty(
PHW_STREAM_REQUEST_BLOCK pSrb
)
{
// PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
pSrb->Status = STATUS_NOT_IMPLEMENTED;
}
/*
** VideoTimerRoutine()
**
** 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
VideoTimerRoutine(
PVOID Context
)
{
PSTREAMEX pStrmEx = ((PSTREAMEX)Context);
PHW_DEVICE_EXTENSION pHwDevExt = pStrmEx->pHwDevExt;
int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
// If we're stopped and the timer is still running, just return.
// This will stop the timer.
if (pStrmEx->KSState == KSSTATE_STOP) {
return;
}
// Capture a frame if it's time and we have a buffer
VideoCaptureRoutine(pStrmEx);
// Schedule the next timer event
// Make it run at 2x the requested capture rate (which is in 100nS units)
StreamClassScheduleTimer (
pStrmEx->pStreamObject, // StreamObject
pHwDevExt, // HwDeviceExtension
(ULONG) (pStrmEx->AvgTimePerFrame / 20), // Microseconds
VideoTimerRoutine, // TimerRoutine
pStrmEx); // Context
}
/*
** VideoCaptureRoutine()
**
** Routine to capture video frames based on a timer.
**
** Note: Devices capable of using interrupts should always
** trigger capture on a VSYNC interrupt, and not use a timer.
**
** Arguments:
**
** Returns: nothing
**
** Side Effects: none
*/
VOID
STREAMAPI
VideoCaptureRoutine(
IN PSTREAMEX pStrmEx
)
{
PHW_DEVICE_EXTENSION pHwDevExt = pStrmEx->pHwDevExt;
int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
PKSSTREAM_HEADER pDataPacket;
PKS_FRAME_INFO pFrameInfo;
// If we're stopped and the timer is still running, just return.
// This will stop the timer.
if (pStrmEx->KSState == KSSTATE_STOP) {
return;
}
// Find out what time it is, if we're using a clock
if (pStrmEx->hMasterClock ) {
HW_TIME_CONTEXT TimeContext;
TimeContext.HwDeviceExtension = pHwDevExt;
TimeContext.HwStreamObject = pStrmEx->pStreamObject;
TimeContext.Function = TIME_GET_STREAM_TIME;
StreamClassQueryMasterClockSync (
pStrmEx->hMasterClock,
&TimeContext);
pStrmEx->QST_StreamTime = TimeContext.Time;
pStrmEx->QST_Now = TimeContext.SystemTime;
if (pStrmEx->QST_NextFrame == 0) {
pStrmEx->QST_NextFrame = pStrmEx->QST_StreamTime + pStrmEx->AvgTimePerFrame;
}
#ifdef CREATE_A_FLURRY_OF_TIMING_SPEW
DbgLogTrace(("TestCap: Time=%6d mS at SystemTime=%I64d\n",
(LONG) ((LONGLONG) TimeContext.Time / 10000),
TimeContext.SystemTime));
#endif
}
// Only capture in the RUN state
if (pStrmEx->KSState == KSSTATE_RUN) {
//
// Determine if it is time to capture a frame based on
// how much time has elapsed since capture started.
// If there isn't a clock available, then capture immediately.
//
if ((!pStrmEx->hMasterClock) ||
(pStrmEx->QST_StreamTime >= pStrmEx->QST_NextFrame)) {
PHW_STREAM_REQUEST_BLOCK pSrb;
// Increment the picture count (usually this is VSYNC count)
pStrmEx->FrameInfo.PictureNumber++;
//
// Get the next queue SRB (if any)
//
pSrb = VideoQueueRemoveSRB (
pHwDevExt,
StreamNumber);
if (pSrb) {
pDataPacket = pSrb->CommandData.DataBufferArray;
pFrameInfo = (PKS_FRAME_INFO) (pDataPacket + 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -