📄 capstrm.cpp
字号:
ASSERT(pCurrentSrb->Irp->MdlAddress);
StreamClassStreamNotification( StreamRequestComplete,
pCurrentSrb->StreamObject,
pCurrentSrb);
}
}
void CWDMCaptureStream::AddBuffersToDirectDraw()
{
KIRQL Irql;
BOOL fAdded;
KeAcquireSpinLock(&m_streamDataLock, &Irql);
while (!IsListEmpty(&m_incomingDataSrbQueue))
{
// So if we've reached this point, we are in the run state, and
// we have an SRB on our incoming queue, and we are holding the
// the stream lock
PSRB_DATA_EXTENSION pSrbExt = (PSRB_DATA_EXTENSION)RemoveHeadList(&m_incomingDataSrbQueue);
PHW_STREAM_REQUEST_BLOCK pSrb = pSrbExt->pSrb;
// Calls to DXAPI must be at Passive level, so release the spinlock temporarily
KeReleaseSpinLock(&m_streamDataLock, Irql);
DBGINFO(("Removed 0x%x from data queue\n", pSrb));
fAdded = AddBuffer(pSrb);
KeAcquireSpinLock(&m_streamDataLock, &Irql);
if (fAdded)
{
DBGINFO(("Adding 0x%x to wait queue\n", pSrb));
InsertTailList(&m_waitQueue, &pSrbExt->srbListEntry);
}
else
{
DBGINFO(("Adding 0x%x back to dataqueue\n", pSrb));
// put it back where it was
InsertHeadList(&m_incomingDataSrbQueue, &pSrbExt->srbListEntry);
break;
}
}
KeReleaseSpinLock(&m_streamDataLock, Irql);
}
BOOL CWDMCaptureStream::AddBuffer(PHW_STREAM_REQUEST_BLOCK pSrb)
{
DDADDVPCAPTUREBUFF ddAddVPCaptureBuffIn;
DWORD ddOut = DD_OK;
PIRP irp = pSrb->Irp;
PSRB_DATA_EXTENSION pSrbExt = (PSRB_DATA_EXTENSION)pSrb->SRBExtension;
DBGINFO(("In AddBuffer. pSrb: 0x%x.\n", pSrb));
// For handling full-screen DOS, res changes, etc.
if (m_hCapture == 0)
{
if (!GetCaptureHandle())
{
return FALSE;
}
}
ddAddVPCaptureBuffIn.hCapture = m_hCapture;
ddAddVPCaptureBuffIn.dwFlags = DDADDBUFF_SYSTEMMEMORY;
ddAddVPCaptureBuffIn.pMDL = irp->MdlAddress;
ddAddVPCaptureBuffIn.lpBuffInfo = &pSrbExt->ddCapBuffInfo;
ddAddVPCaptureBuffIn.pKEvent = &pSrbExt->bufferDoneEvent;
DxApi(DD_DXAPI_ADDVPCAPTUREBUFFER, &ddAddVPCaptureBuffIn, sizeof(ddAddVPCaptureBuffIn), &ddOut, sizeof(ddOut));
if (ddOut != DD_OK)
{
// Not necessarily an error.
DBGINFO(("DD_DXAPI_ADDVPCAPTUREBUFFER failed.\n"));
// TRAP();
return FALSE;
}
return TRUE;
}
VOID CWDMCaptureStream::HandleStateTransition()
{
KIRQL Irql;
switch (m_stateChange)
{
case Running:
AddBuffersToDirectDraw();
m_stateChange = ChangeComplete;
KeSetEvent(&m_specialEvent, 0, FALSE);
break;
case Pausing:
KeAcquireSpinLock(&m_streamDataLock, &Irql);
if (IsListEmpty(&m_waitQueue))
{
KeReleaseSpinLock(&m_streamDataLock, Irql);
m_stateChange = ChangeComplete;
KeSetEvent(&m_specialEvent, 0, FALSE);
}
else
{
KeReleaseSpinLock(&m_streamDataLock, Irql);
}
break;
case Stopping:
KeAcquireSpinLock(&m_streamDataLock, &Irql);
if (IsListEmpty(&m_waitQueue))
{
KeReleaseSpinLock(&m_streamDataLock, Irql);
EmptyIncomingDataSrbQueue();
m_stateChange = ChangeComplete;
KeSetEvent(&m_specialEvent, 0, FALSE);
}
else
{
KeReleaseSpinLock(&m_streamDataLock, Irql);
}
break;
case Closing:
m_stateChange = ChangeComplete;
KeSetEvent(&m_specialEvent, 0, FALSE);
DBGTRACE(("StreamThread exiting\n"));
PsTerminateSystemThread(STATUS_SUCCESS);
DBGERROR(("Shouldn't get here\n"));
TRAP();
break;
case ChangeComplete:
DBGTRACE(("Must have completed transition in HandleBusMasterCompletion\n"));
break;
default:
TRAP();
break;
}
}
BOOL CWDMCaptureStream::ResetFieldNumber()
{
int streamNumber = m_pStreamObject->StreamNumber;
DDSETFIELDNUM ddSetFieldNum;
DWORD ddOut;
ASSERT(streamNumber == STREAM_VideoCapture || streamNumber == STREAM_VBICapture);
if (m_pVideoPort->GetDirectDrawHandle() == 0) {
DBGERROR(("Didn't expect ring0DirectDrawHandle to be zero.\n"));
TRAP();
return FALSE;
}
if (m_pVideoPort->GetVideoPortHandle() == 0) {
DBGERROR(("Didn't expect ring0VideoPortHandle to be zero.\n"));
TRAP();
return FALSE;
}
RtlZeroMemory(&ddSetFieldNum, sizeof(ddSetFieldNum));
RtlZeroMemory(&ddOut, sizeof(ddOut));
KSPROPERTY_DROPPEDFRAMES_CURRENT_S DroppedFrames;
GetDroppedFrames(&DroppedFrames);
ddSetFieldNum.hDirectDraw = m_pVideoPort->GetDirectDrawHandle();
ddSetFieldNum.hVideoPort = m_pVideoPort->GetVideoPortHandle();
ddSetFieldNum.dwFieldNum = ((ULONG)DroppedFrames.PictureNumber + 1) * GetFieldInterval();
DxApi(DD_DXAPI_SET_VP_FIELD_NUMBER, &ddSetFieldNum, sizeof(ddSetFieldNum), &ddOut, sizeof(ddOut));
if (ddOut != DD_OK)
{
DBGERROR(("DD_DXAPI_SET_VP_FIELD_NUMBER failed.\n"));
TRAP();
return FALSE;
}
else
{
#ifdef DEBUG
DBGINFO(("PictureNumber: %d; ", DroppedFrames.PictureNumber));
DBGINFO(("DropCount: %d\n", DroppedFrames.DropCount));
DBGINFO(("AverageFrameSize: %d\n", DroppedFrames.AverageFrameSize));
#endif
return TRUE;
}
}
BOOL CWDMCaptureStream::FlushBuffers()
{
DWORD ddOut = DD_OK;
// commented out the trap because it is possible that capture handle is closed in DD before flushbuffer is called during mode switch
if (m_hCapture == NULL) {
//DBGERROR(("m_hCapture === NULL in FlushBuffers.\n"));
//TRAP();
return FALSE;
}
DxApi(DD_DXAPI_FLUSHVPCAPTUREBUFFERS, &m_hCapture, sizeof(HANDLE), &ddOut, sizeof(ddOut));
if (ddOut != DD_OK)
{
DBGERROR(("DD_DXAPI_FLUSHVPCAPTUREBUFFERS failed.\n"));
TRAP();
return FALSE;
}
else
{
return TRUE;
}
}
VOID CWDMCaptureStream::TimeStampSrb(PHW_STREAM_REQUEST_BLOCK pSrb)
{
PKSSTREAM_HEADER pDataPacket = pSrb->CommandData.DataBufferArray;
PSRB_DATA_EXTENSION pSrbExt = (PSRB_DATA_EXTENSION)pSrb->SRBExtension;
pDataPacket->Duration = GetFieldInterval() * NTSCFieldDuration;
pDataPacket->OptionsFlags |=
KSSTREAM_HEADER_OPTIONSF_DURATIONVALID |
KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT;
// Find out what time it is, if we're using a clock
if (m_hMasterClock) {
LARGE_INTEGER Delta;
HW_TIME_CONTEXT TimeContext;
// TimeContext.HwDeviceExtension = pHwDevExt;
TimeContext.HwDeviceExtension = (struct _HW_DEVICE_EXTENSION *)m_pVideoDecoder;
TimeContext.HwStreamObject = m_pStreamObject;
TimeContext.Function = TIME_GET_STREAM_TIME;
StreamClassQueryMasterClockSync (
m_hMasterClock,
&TimeContext);
// This calculation should result in the stream time WHEN the buffer
// was filled.
Delta.QuadPart = TimeContext.SystemTime -
pSrbExt->ddCapBuffInfo.liTimeStamp.QuadPart;
// Be safe, just use the current stream time, without the correction for when
// DDraw actually returned the buffer to us.
pDataPacket->PresentationTime.Time = TimeContext.Time;
#ifdef THIS_SHOULD_WORK_BUT_IT_DOESNT
if (TimeContext.Time > (ULONGLONG) Delta.QuadPart)
{
pDataPacket->PresentationTime.Time = TimeContext.Time - Delta.QuadPart;
}
else
{
// There's a bug in Ks or Stream after running for 2 hours
// that makes this hack necessary. Will be fixed soon...
pDataPacket->PresentationTime.Time = TimeContext.Time;
}
#endif
#ifdef DEBUG
ULONG *tmp1, *tmp2;
tmp1 = (ULONG *)&pDataPacket->PresentationTime.Time;
tmp2 = (ULONG *)&TimeContext.Time;
DBGINFO(("PT: 0x%x%x; ST: 0x%x%x\n", tmp1[1], tmp1[0], tmp2[1], tmp2[0]));
#endif
pDataPacket->PresentationTime.Numerator = 1;
pDataPacket->PresentationTime.Denominator = 1;
pDataPacket->OptionsFlags |=
KSSTREAM_HEADER_OPTIONSF_TIMEVALID;
}
else
{
pDataPacket->OptionsFlags &=
~KSSTREAM_HEADER_OPTIONSF_TIMEVALID;
}
}
void CWDMCaptureStream::CancelPacket( PHW_STREAM_REQUEST_BLOCK pSrbToCancel)
{
PHW_STREAM_REQUEST_BLOCK pCurrentSrb;
KIRQL Irql;
PLIST_ENTRY Entry;
BOOL bFound = FALSE;
if ( m_stateChange == Initializing ) // Stream not completely setup, so nothing in the queue
{
DBGINFO(( "Bt829: Didn't find Srb 0x%x\n", pSrbToCancel));
return;
}
KeAcquireSpinLock( &m_streamDataLock, &Irql);
Entry = m_incomingDataSrbQueue.Flink;
//
// Loop through the linked list from the beginning to end,
// trying to find the SRB to cancel
//
while( Entry != &m_incomingDataSrbQueue)
{
PSRB_DATA_EXTENSION pSrbExt;
pSrbExt = ( PSRB_DATA_EXTENSION)Entry;
pCurrentSrb = pSrbExt->pSrb;
if( pCurrentSrb == pSrbToCancel)
{
RemoveEntryList( Entry);
bFound = TRUE;
break;
}
Entry = Entry->Flink;
}
KeReleaseSpinLock( &m_streamDataLock, Irql);
if( bFound)
{
pCurrentSrb->Status = STATUS_CANCELLED;
pCurrentSrb->CommandData.DataBufferArray->DataUsed = 0;
DBGINFO(( "Bt829: Cancelled Srb 0x%x\n", pCurrentSrb));
StreamClassStreamNotification( StreamRequestComplete,
pCurrentSrb->StreamObject,
pCurrentSrb);
}
else
{
// If this is a DATA_TRANSFER and a STREAM_REQUEST SRB,
// then it must be in the waitQueue, being filled by DDraw.
// If so, mark it cancelled, and it will
// be returned when DDraw is finished with it.
if(( pSrbToCancel->Flags & (SRB_HW_FLAGS_DATA_TRANSFER | SRB_HW_FLAGS_STREAM_REQUEST)) ==
(SRB_HW_FLAGS_DATA_TRANSFER | SRB_HW_FLAGS_STREAM_REQUEST))
{
pSrbToCancel->Status = STATUS_CANCELLED;
DBGINFO(( "Bt829: Cancelled Srb on waitQueue 0x%x\n", pSrbToCancel));
}
else
{
DBGINFO(( "Bt829: Didn't find Srb 0x%x\n", pSrbToCancel));
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -