?? capvideo.c
字號:
//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992 - 1999 Microsoft Corporation. All Rights Reserved.
//
//==========================================================================;
#include "strmini.h"
#include "ksmedia.h"
#include "capmain.h"
#include "capdebug.h"
#include "capxfer.h"
#include "ntstatus.h"
//==========================================================================;
// General queue management routines
//==========================================================================;
/*
** AddToListIfBusy ()
**
** Grabs a spinlock, checks the busy flag, and if set adds an SRB to a queue
**
** Arguments:
**
** pSrb - Stream request block
**
** SpinLock - The spinlock to use when checking the flag
**
** BusyFlag - The flag to check
**
** ListHead - The list onto which the Srb will be added if the busy flag is set
**
** Returns:
**
** The state of the busy flag on entry. This will be TRUE if we're already
** processing an SRB, and FALSE if no SRB is already in progress.
**
** Side Effects: none
*/
BOOL
STREAMAPI
AddToListIfBusy (
IN PHW_STREAM_REQUEST_BLOCK pSrb,
IN KSPIN_LOCK *SpinLock,
IN OUT BOOL *BusyFlag,
IN LIST_ENTRY *ListHead
)
{
KIRQL Irql;
PSRB_EXTENSION pSrbExt = (PSRB_EXTENSION)pSrb->SRBExtension;
KeAcquireSpinLock (SpinLock, &Irql);
// If we're already processing another SRB, add this current request
// to the queue and return TRUE
if (*BusyFlag == TRUE) {
// Save the SRB pointer away in the SRB Extension
pSrbExt->pSrb = pSrb;
InsertTailList(ListHead, &pSrbExt->ListEntry);
KeReleaseSpinLock(SpinLock, Irql);
return TRUE;
}
// Otherwise, set the busy flag, release the spinlock, and return FALSE
*BusyFlag = TRUE;
KeReleaseSpinLock(SpinLock, Irql);
return FALSE;
}
/*
** RemoveFromListIfAvailable ()
**
** Grabs a spinlock, checks for an available SRB, and removes it from the list
**
** Arguments:
**
** &pSrb - where to return the Stream request block if available
**
** SpinLock - The spinlock to use
**
** BusyFlag - The flag to clear if the list is empty
**
** ListHead - The list from which an SRB will be removed if available
**
** Returns:
**
** TRUE if an SRB was removed from the list
** FALSE if the list is empty
**
** Side Effects: none
*/
BOOL
STREAMAPI
RemoveFromListIfAvailable (
IN OUT PHW_STREAM_REQUEST_BLOCK *pSrb,
IN KSPIN_LOCK *SpinLock,
IN OUT BOOL *BusyFlag,
IN LIST_ENTRY *ListHead
)
{
KIRQL Irql;
KeAcquireSpinLock (SpinLock, &Irql);
//
// If the queue is now empty, clear the busy flag, and return
//
if (IsListEmpty(ListHead)) {
*BusyFlag = FALSE;
KeReleaseSpinLock(SpinLock, Irql);
return FALSE;
}
//
// otherwise extract the SRB
//
else {
PUCHAR ptr;
PSRB_EXTENSION pSrbExt;
ptr = (PUCHAR)RemoveHeadList(ListHead);
*BusyFlag = TRUE;
KeReleaseSpinLock(SpinLock, Irql);
// Get the SRB out of the SRB extension and return it
pSrbExt = (PSRB_EXTENSION) (((PUCHAR) ptr) -
FIELDOFFSET(SRB_EXTENSION, ListEntry));
*pSrb = pSrbExt->pSrb;
}
return TRUE;
}
//==========================================================================;
// Routines for managing the SRB queue on a per stream basis
//==========================================================================;
/*
** VideoQueueAddSRB ()
**
** Adds a stream data SRB to a stream queue. The queue is maintained in a
** first in, first out order.
**
** Arguments:
**
** pSrb - Stream request block for the Video stream
**
** Returns: nothing
**
** Side Effects: none
*/
VOID
STREAMAPI
VideoQueueAddSRB (
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;
KIRQL oldIrql;
KeAcquireSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], &oldIrql);
// Save the SRB pointer in the IRP so we can use the IRPs
// ListEntry to maintain a doubly linked list of pending
// requests
pSrb->Irp->Tail.Overlay.DriverContext[0] = pSrb;
InsertTailList (
&pHwDevExt->StreamSRBList[StreamNumber],
&pSrb->Irp->Tail.Overlay.ListEntry);
// Increment the count of outstanding SRBs in this queue
pHwDevExt->StreamSRBListSize[StreamNumber]++;
KeReleaseSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], oldIrql);
}
/*
** VideoQueueRemoveSRB ()
**
** Removes a stream data SRB from a stream queue
**
** Arguments:
**
** pHwDevExt - Device Extension
**
** StreamNumber - Index of the stream
**
** Returns: SRB or NULL
**
** Side Effects: none
*/
PHW_STREAM_REQUEST_BLOCK
STREAMAPI
VideoQueueRemoveSRB (
PHW_DEVICE_EXTENSION pHwDevExt,
int StreamNumber
)
{
PUCHAR ptr;
PIRP pIrp;
PHW_STREAM_REQUEST_BLOCK pSrb = NULL;
KIRQL oldIrql;
KeAcquireSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], &oldIrql);
//
// Get the SRB out of the IRP out of the pending list
//
if (!IsListEmpty (&pHwDevExt->StreamSRBList[StreamNumber])) {
ptr = (PUCHAR) RemoveHeadList(
&pHwDevExt->StreamSRBList[StreamNumber]);
pIrp = (PIRP) (((PUCHAR) ptr) -
FIELDOFFSET(IRP, Tail.Overlay.ListEntry));
pSrb = (PHW_STREAM_REQUEST_BLOCK) pIrp->Tail.Overlay.DriverContext[0];
// Decrement the count of SRBs in this queue
pHwDevExt->StreamSRBListSize[StreamNumber]--;
}
KeReleaseSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], oldIrql);
return pSrb;
}
/*
** VideoQueueCancelAllSRBs()
**
** In case of a client crash, this empties the stream queue when the stream closes
**
** Arguments:
**
** pStrmEx - pointer to the stream extension
**
** Returns:
**
** Side Effects: none
*/
VOID
STREAMAPI
VideoQueueCancelAllSRBs (
PSTREAMEX pStrmEx
)
{
PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pStrmEx->pHwDevExt;
int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
PUCHAR ptr;
PIRP pIrp;
PHW_STREAM_REQUEST_BLOCK pSrb;
KIRQL oldIrql;
if (pStrmEx->KSState != KSSTATE_STOP) {
DbgLogInfo(("TestCap: VideoQueueCancelAllSRBs without being in the stopped state\n"));
// May need to force the device to a stopped state here
// may need to disable interrupts here !
}
//
// The stream class will cancel all outstanding IRPs for us
// (but only if we've set TurnOffSynchronization = FALSE)
//
KeAcquireSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], &oldIrql);
//
// Get the SRB out of the IRP out of the pending list
//
while (!IsListEmpty (&pHwDevExt->StreamSRBList[StreamNumber])) {
ptr = (PUCHAR) RemoveHeadList(
&pHwDevExt->StreamSRBList[StreamNumber]);
pIrp = (PIRP) (((PUCHAR) ptr) -
FIELDOFFSET(IRP, Tail.Overlay.ListEntry));
pSrb = (PHW_STREAM_REQUEST_BLOCK) pIrp->Tail.Overlay.DriverContext[0];
// Decrement the count of SRBs in this queue
pHwDevExt->StreamSRBListSize[StreamNumber]--;
//
// Make the length zero, and status cancelled
//
pSrb->CommandData.DataBufferArray->DataUsed = 0;
pSrb->Status = STATUS_CANCELLED;
DbgLogInfo(("TestCap: VideoQueueCancelALLSRBs FOUND Srb=%p, Stream=%d\n", pSrb, StreamNumber));
CompleteStreamSRB (pSrb);
}
KeReleaseSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], oldIrql);
DbgLogInfo(("TestCap: VideoQueueCancelAll Completed\n"));
}
/*
** VideoQueueCancelOneSRB()
**
** Called when cancelling a particular SRB
**
** Arguments:
**
** pStrmEx - pointer to the stream extension
**
** pSRBToCancel - pointer to the SRB
**
** Returns:
**
** TRUE if the SRB was found in this queue
**
** Side Effects: none
*/
BOOL
STREAMAPI
VideoQueueCancelOneSRB (
PSTREAMEX pStrmEx,
PHW_STREAM_REQUEST_BLOCK pSrbToCancel
)
{
PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pStrmEx->pHwDevExt;
int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
KIRQL oldIrql;
BOOL Found = FALSE;
PIRP pIrp;
PHW_STREAM_REQUEST_BLOCK pSrb;
PLIST_ENTRY Entry;
KeAcquireSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], &oldIrql);
Entry = pHwDevExt->StreamSRBList[StreamNumber].Flink;
//
// Loop through the linked list from the beginning to end,
// trying to find the SRB to cancel
//
while (Entry != &pHwDevExt->StreamSRBList[StreamNumber]) {
pIrp = (PIRP) (((PUCHAR) Entry) -
FIELDOFFSET(IRP, Tail.Overlay.ListEntry));
pSrb = (PHW_STREAM_REQUEST_BLOCK) pIrp->Tail.Overlay.DriverContext[0];
if (pSrb == pSrbToCancel) {
RemoveEntryList(Entry);
Found = TRUE;
break;
}
Entry = Entry->Flink;
}
KeReleaseSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], oldIrql);
if (Found) {
pHwDevExt->StreamSRBListSize[StreamNumber]--;
//
// Make the length zero, and status cancelled
//
pSrbToCancel->CommandData.DataBufferArray->DataUsed = 0;
pSrbToCancel->Status = STATUS_CANCELLED;
CompleteStreamSRB (pSrbToCancel);
DbgLogInfo(("TestCap: VideoQueueCancelOneSRB FOUND Srb=%p, Stream=%d\n", pSrb, StreamNumber));
}
DbgLogInfo(("TestCap: VideoQueueCancelOneSRB Completed Stream=%d\n", StreamNumber));
return Found;
}
/*
** VideoSetFormat()
**
** Sets the format for a video stream. This happens both when the
** stream is first opened, and also when dynamically switching formats
** on the preview pin.
**
** It is assumed that the format has been verified for correctness before
** this call is made.
**
** Arguments:
**
** pSrb - Stream request block for the Video stream
**
** Returns:
**
** TRUE if the format could be set, else FALSE
**
** Side Effects: none
*/
BOOL
STREAMAPI
VideoSetFormat(
IN PHW_STREAM_REQUEST_BLOCK pSrb
)
{
PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
int StreamNumber = pSrb->StreamObject->StreamNumber;
UINT nSize;
PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat;
// -------------------------------------------------------------------
// Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
// -------------------------------------------------------------------
if (IsEqualGUID (&pKSDataFormat->Specifier,
&KSDATAFORMAT_SPECIFIER_VIDEOINFO)) {
PKS_DATAFORMAT_VIDEOINFOHEADER pVideoInfoHeader =
(PKS_DATAFORMAT_VIDEOINFOHEADER) pSrb->CommandData.OpenFormat;
PKS_VIDEOINFOHEADER pVideoInfoHdrRequested =
&pVideoInfoHeader->VideoInfoHeader;
nSize = KS_SIZE_VIDEOHEADER (pVideoInfoHdrRequested);
DbgLogInfo(("TestCap: New Format\n"));
DbgLogInfo(("TestCap: pVideoInfoHdrRequested=%p\n", pVideoInfoHdrRequested));
DbgLogInfo(("TestCap: KS_VIDEOINFOHEADER size=%d\n", nSize));
DbgLogInfo(("TestCap: Width=%d Height=%d BitCount=%d\n",
pVideoInfoHdrRequested->bmiHeader.biWidth,
pVideoInfoHdrRequested->bmiHeader.biHeight,
pVideoInfoHdrRequested->bmiHeader.biBitCount));
DbgLogInfo(("TestCap: biSizeImage=%d\n",
pVideoInfoHdrRequested->bmiHeader.biSizeImage));
//
// If a previous format was in use, release the memory
//
if (pStrmEx->pVideoInfoHeader) {
ExFreePool(pStrmEx->pVideoInfoHeader);
pStrmEx->pVideoInfoHeader = NULL;
}
// Since the VIDEOINFOHEADER is of potentially variable size
// allocate memory for it
pStrmEx->pVideoInfoHeader = ExAllocatePool(NonPagedPool, nSize);
if (pStrmEx->pVideoInfoHeader == NULL) {
DbgLogError(("TestCap: ExAllocatePool failed\n"));
pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
return FALSE;
}
// Copy the VIDEOINFOHEADER requested to our storage
RtlCopyMemory(
pStrmEx->pVideoInfoHeader,
pVideoInfoHdrRequested,
nSize);
// A renderer may be switching formats, and in this case, the AvgTimePerFrame
// will be zero. Don't overwrite a previously set framerate.
if (pStrmEx->pVideoInfoHeader->AvgTimePerFrame) {
pStrmEx->AvgTimePerFrame = pStrmEx->pVideoInfoHeader->AvgTimePerFrame;
}
}
else {
// Unknown format
pSrb->Status = STATUS_INVALID_PARAMETER;
return FALSE;
}
return TRUE;
}
/*
** VideoReceiveDataPacket()
**
** Receives Video data packet commands on the output streams
**
** Arguments:
**
** pSrb - Stream request block for the Video stream
**
** Returns: nothing
**
** Side Effects: none
*/
VOID
STREAMAPI
VideoReceiveDataPacket(
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!=NULL);
DbgLogTrace(("TestCap: Receiving Stream Data SRB %p, %x\n", pSrb, pSrb->Command));
//
// Default to success
//
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -