// $Header: G:/SwDev/WDM/Video/bt848/rcs/Capvideo.c 1.11 1998/05/08 00:11:02 tomz Exp $ //==========================================================================; // // 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 - 1996 Microsoft Corporation. All Rights Reserved. // //==========================================================================; extern "C" { #include "strmini.h" #include "ksmedia.h" #include "ddkmapi.h" } #include "capdebug.h" #include "device.h" #include "capmain.h" #define DD_OK 0 ErrorCode VerifyVideoStream( const KS_DATAFORMAT_VIDEOINFOHEADER &vidHDR ); ErrorCode VerifyVideoStream2( const KS_DATAFORMAT_VIDEOINFOHEADER2 &vidHDR ); ErrorCode VerifyVBIStream( const KS_DATAFORMAT_VBIINFOHEADER &rKSDataFormat ); void CheckSrbStatus( PHW_STREAM_REQUEST_BLOCK pSrb ); // notify class we are ready to rock void STREAMAPI StreamCompleterData( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("StreamCompleterData()"); DebugOut((1, "*** 1 *** completing SRB %x\n", pSrb)); CheckSrbStatus( pSrb ); StreamClassStreamNotification( StreamRequestComplete, pSrb->StreamObject, pSrb ); StreamClassStreamNotification( ReadyForNextStreamDataRequest, pSrb->StreamObject ); } // notify class we are ready to rock void STREAMAPI StreamCompleterControl( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("StreamCompleterControl()"); CheckSrbStatus( pSrb ); StreamClassStreamNotification( StreamRequestComplete, pSrb->StreamObject, pSrb ); StreamClassStreamNotification( ReadyForNextStreamControlRequest, pSrb->StreamObject ); } /* Function: ProposeDataFormat * Purpose: Verifies that data format can be supported * Input: SRB */ void ProposeDataFormat( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("ProposeDataFormat()"); PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension; PsDevice *adapter = HwDeviceExtension->psdevice; VideoStream StreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber; if ( StreamNumber == STREAM_IDX_VBI ) { const KS_DATAFORMAT_VBIINFOHEADER &rKSVBIDataFormat = *(PKS_DATAFORMAT_VBIINFOHEADER) pSrb->CommandData.OpenFormat; if ( VerifyVBIStream( rKSVBIDataFormat ) != Success ) pSrb->Status = STATUS_INVALID_PARAMETER; return; } const KS_DATAFORMAT_VIDEOINFOHEADER &rKSDataFormat = *(PKS_DATAFORMAT_VIDEOINFOHEADER) pSrb->CommandData.OpenFormat; const KS_DATAFORMAT_VIDEOINFOHEADER2 &rKSDataFormat2 = *(PKS_DATAFORMAT_VIDEOINFOHEADER2) pSrb->CommandData.OpenFormat; DebugOut((1, "Proposed Data format\n")); if ( VerifyVideoStream( rKSDataFormat ) != Success ) { if ( VerifyVideoStream2( rKSDataFormat2 ) != Success ) { pSrb->Status = STATUS_INVALID_PARAMETER; } else { pSrb->ActualBytesTransferred = sizeof( KS_DATAFORMAT_VIDEOINFOHEADER2 ); } } else { pSrb->ActualBytesTransferred = sizeof( KS_DATAFORMAT_VIDEOINFOHEADER ); } } /*************************************************************************** Data Packet Handling Routines ***************************************************************************/ /* ** VideoReceiveDataPacket() ** ** Receives Video data packet commands ** ** Arguments: ** ** pSrb - Stream request block for the Video device ** ** Returns: ** ** Side Effects: none */ void MockStampVBI( PHW_STREAM_REQUEST_BLOCK pSrb ) { PKSSTREAM_HEADER pDataPacket = pSrb->CommandData.DataBufferArray; pDataPacket->PresentationTime.Numerator = 1; pDataPacket->PresentationTime.Denominator = 1; pDataPacket->OptionsFlags &= ~KSSTREAM_HEADER_OPTIONSF_DURATIONVALID; pDataPacket->OptionsFlags &= ~KSSTREAM_HEADER_OPTIONSF_TIMEVALID; pDataPacket->OptionsFlags &= ~KS_VBI_FLAG_TVTUNER_CHANGE; pDataPacket->OptionsFlags &= ~KS_VBI_FLAG_VBIINFOHEADER_CHANGE; pDataPacket->PresentationTime.Time = 0; pDataPacket->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT; pSrb->Status = STATUS_SUCCESS; CheckSrbStatus( pSrb ); StreamClassStreamNotification( StreamRequestComplete, pSrb->StreamObject, pSrb ); } VOID STREAMAPI VideoReceiveDataPacket( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("VideoReceiveDataPacket()"); VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension; PsDevice *adapter = HwDeviceExtension->psdevice; VideoStream StreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber; // // make sure we have a device extension // DEBUG_ASSERT((ULONG)adapter); // default to success pSrb->Status = STATUS_SUCCESS; // // determine the type of packet. // DebugOut((1, "VideoReceiveDataPacket(%x) cmd(%x)\n", pSrb, pSrb->Command)); switch ( pSrb->Command ) { case SRB_READ_DATA: // // remember the current srb // DebugOut((1, "PsDevice::VideoReceiveDataPacket - SRB_READ_DATA\n")); chan->SetSRB( pSrb ); adapter->AddBuffer( *chan, pSrb ); break; default: // // invalid / unsupported command. Fail it as such // DebugOut((1, "PsDevice::VideoReceiveDataPacket - unknown command(%x)\n", pSrb->Command)); pSrb->Status = STATUS_NOT_IMPLEMENTED; StreamCompleterData( pSrb ); } } /* ** VideoReceiveCtrlPacket() ** ** Receives packet commands that control the Video stream ** ** Arguments: ** ** pSrb - The stream request block for the Video stream ** ** Returns: ** ** Side Effects: none */ VOID STREAMAPI VideoReceiveCtrlPacket( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("VideoReceiveCtrlPacket()"); PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension; PsDevice *adapter = HwDeviceExtension->psdevice; DEBUG_ASSERT((ULONG)adapter); // default to success pSrb->Status = STATUS_SUCCESS; // // determine the type of packet. // DebugOut((1, "VideoReceiveCtrlPacket(%x) cmd(%x)\n", pSrb, pSrb->Command)); int Command = pSrb->Command; switch ( Command ) { case SRB_SET_STREAM_STATE: adapter->SetVideoState( pSrb ); break; case SRB_GET_STREAM_STATE: adapter->GetVideoState( pSrb ); break; case SRB_PROPOSE_DATA_FORMAT: DebugOut((1, "Propose Data Format\n")); ProposeDataFormat( pSrb ); break; case SRB_SET_DATA_FORMAT: DebugOut((1, "Set Data Format\n")); // should re-validate just in case ? adapter->ProcessSetDataFormat( pSrb ); break; case SRB_GET_STREAM_PROPERTY: adapter->GetStreamProperty( pSrb ); break; case SRB_SET_STREAM_PROPERTY: DebugOut(( 0, "SRB_SET_STREAM_PROPERTY\n" )); break; /* case SRB_OPEN_MASTER_CLOCK: case SRB_CLOSE_MASTER_CLOCK: // // This stream is being selected to provide a Master clock // adapter->SetClockMaster( pSrb ); break; */ case SRB_INDICATE_MASTER_CLOCK: // // Assigns a clock to a stream // adapter->SetClockMaster( pSrb ); break; default: // // invalid / unsupported command. Fail it as such // pSrb->Status = STATUS_NOT_IMPLEMENTED; break; } if ( Command != SRB_SET_STREAM_STATE && Command != SRB_SET_STREAM_PROPERTY && Command != SRB_SET_DATA_FORMAT ) StreamCompleterControl( pSrb ); } /* ** GetVideoState() ** ** Gets the current state of the requested stream ** ** Arguments: ** ** pSrb - pointer to the stream request block for properties ** ** Returns: ** ** Side Effects: none */ VOID PsDevice::GetVideoState( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("PsDevice::GetVideoState()"); VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; pSrb->Status = STATUS_SUCCESS; pSrb->CommandData.StreamState = chan->GetKSState(); pSrb->ActualBytesTransferred = sizeof (KSSTATE); // A very odd rule: // When transitioning from stop to pause, DShow tries to preroll // the graph. Capture sources can't preroll, and indicate this // by returning VFW_S_CANT_CUE in user mode. To indicate this // condition from drivers, they must return ERROR_NO_DATA_DETECTED // // [TMZ] JayBo says KSSTATE_ACQUIRE should return success if (pSrb->CommandData.StreamState == KSSTATE_PAUSE) { pSrb->Status = STATUS_NO_DATA_DETECTED; } } /* ** SetVideoState() ** ** Sets the current state of the requested stream ** ** Arguments: ** ** pSrb - pointer to the stream request block for properties ** ** Returns: ** ** Side Effects: none */ VOID PrintState(StreamState st) { switch( st ) { case Started: DebugOut((1, "*** Streamstate was STARTED\n")); break; case Created: DebugOut((1, "*** Streamstate was CREATED\n")); break; case Paused: DebugOut((1, "*** Streamstate was PAUSED\n")); break; case Open: DebugOut((1, "*** Streamstate was OPEN\n")); break; default: DebugOut((1, "*** Streamstate was ??? (%x)\n", st)); break; } } VOID PsDevice::SetVideoState( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("PsDevice::SetVideoState()"); PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension; PsDevice *adapter = HwDeviceExtension->psdevice; VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; VideoStream StreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber; // // determine which new state is requested // pSrb->Status = STATUS_SUCCESS; chan->SetKSState( pSrb->CommandData.StreamState ); switch ( pSrb->CommandData.StreamState ) { case KSSTATE_ACQUIRE: // Documented as "same as pause for most minidrivers" DebugOut((1, "*** KSSTATE_ACQUIRE(%d) state(%d) falling through to PAUSE\n", StreamNumber, chan->GetState())); case KSSTATE_PAUSE: // PrintState(chan->GetState()); DebugOut((1, "*** KSSTATE_PAUSE(%d) state(%d)\n", StreamNumber, chan->GetState())); switch ( chan->GetState() ) { case Started: if ( StreamNumber == 2 ) { DebugOut((1, "#############################################################\n")); DebugOut((1, "About to pause channel %d\n", StreamNumber )); //adapter->CaptureContrll_.DumpRiscPrograms(); } Pause( *chan ); // intentional fall-through if ( StreamNumber == 2 ) { DebugOut((1, "Done pausing channel %d\n", StreamNumber )); DebugOut((1, "#############################################################\n")); //adapter->CaptureContrll_.DumpRiscPrograms(); } case Created: case Paused: // 2 PAUSE in a row; ignore StreamCompleterControl( pSrb ); break; case Open: StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, Low, PHW_PRIORITY_ROUTINE( CreateVideo ), pSrb ); break; } break; case KSSTATE_STOP: // PrintState(chan->GetState()); DebugOut((1, "*** KSSTATE_STOP(%d) state(%d)\n", StreamNumber, chan->GetState())); // // stop the video // switch ( chan->GetState() ) { default: if ( StreamNumber == 2 ) { DebugOut((1, "'#############################################################\n")); DebugOut((1, "'About to pause channel %d\n", StreamNumber )); //adapter->CaptureContrll_.DumpRiscPrograms(); } Pause( *chan ); // intentional fall-through if ( StreamNumber == 2 ) { DebugOut((1, "'Done pausing channel %d\n", StreamNumber )); DebugOut((1, "'#############################################################\n")); //adapter->CaptureContrll_.DumpRiscPrograms(); } case Paused: case Created: StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, Low, PHW_PRIORITY_ROUTINE( DestroyVideo ), pSrb ); break; } break; case KSSTATE_RUN: { // PrintState(chan->GetState()); { VideoStream nStreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber; DebugOut((1, "*** KSSTATE_RUN(%d)\n", nStreamNumber)); } // // play the video // StreamState st = chan->GetState(); if ( st != Created && st != Paused ) { DebugOut((1, "*** KSSTATE_RUN Error (st == %d)\n", st)); pSrb->Status = STATUS_IO_DEVICE_ERROR; } else { Start( *chan ); } StreamCompleterControl( pSrb ); } break; default: DebugOut((0, "*** KSSTATE_??? (%x)\n", pSrb->CommandData.StreamState)); pSrb->Status = STATUS_SUCCESS; StreamCompleterControl( pSrb ); break; } // when going to paused mode from open and stopping, notification is done in callback } /* Method: PsDevice::StartVideo * Purpose: Starts a stream * Input: pSrb */ void STREAMAPI PsDevice::StartVideo( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("PsDevice::StartVideo()"); PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension; PsDevice *adapter = HwDeviceExtension->psdevice; VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; // restart the stream adapter->Start( *chan ); adapter->Pause( *chan ); // finally, can complete the SET dataformat SRB // StreamCompleterControl( pSrb ); // cannot call any other class' services; have to schedule a callback StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, LowToHigh, PHW_PRIORITY_ROUTINE( StreamCompleterControl ), pSrb ); } /* Method: PsDevice::CreateVideo * Purpose: Starts a stream * Input: pSrb */ void STREAMAPI PsDevice::CreateVideo( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("PsDevice::CreateVideo()"); PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension; PsDevice *adapter = HwDeviceExtension->psdevice; VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; if ( adapter->Create( *chan ) != Success ) pSrb->Status = STATUS_IO_DEVICE_ERROR; // cannot call any other class' services; have to schedule a callback StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, LowToHigh, PHW_PRIORITY_ROUTINE( StreamCompleterControl ), pSrb ); } /* Method: PsDevice::DestroyVideo * Purpose: Called at low priority to stop video and free the resources */ void STREAMAPI PsDevice::DestroyVideoNoComplete( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("PsDevice::DestroyVideoNoComplete()"); PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension; PsDevice *adapter = HwDeviceExtension->psdevice; VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; // have all resources freed adapter->Stop( *chan ); // set new format KS_DATAFORMAT_VIDEOINFOHEADER &rDataVideoInfHdr = *(PKS_DATAFORMAT_VIDEOINFOHEADER) pSrb->CommandData.OpenFormat; KS_DATAFORMAT_VIDEOINFOHEADER2 &rDataVideoInfHdr2 = *(PKS_DATAFORMAT_VIDEOINFOHEADER2) pSrb->CommandData.OpenFormat; if ( IsEqualGUID( rDataVideoInfHdr.DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO ) ) { chan->SetVidHdr( rDataVideoInfHdr.VideoInfoHeader ); } else { chan->SetVidHdr2( rDataVideoInfHdr2.VideoInfoHeader2 ); } // re-create the stream if ( adapter->Create( *chan ) != Success ) { pSrb->Status = STATUS_IO_DEVICE_ERROR; StreamCompleterControl( pSrb ); } else { DebugOut((1, "1 pSrb = %lx\n", pSrb)); DebugOut((1, "1 pSrb->StreamObject = %lx\n", pSrb->StreamObject)); DebugOut((1, "1 chan = %lx\n", chan)); DebugOut((1, "1 HwStreamExtension = %lx\n", pSrb->StreamObject->HwStreamExtension)); // we're already at low priority ??? // StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, Low, // PHW_PRIORITY_ROUTINE( StartVideo ), pSrb ); // StartVideo( pSrb); // cannot call any other class' services; have to schedule a callback StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, LowToHigh, PHW_PRIORITY_ROUTINE( StreamCompleterControl ), pSrb ); } } /* Method: PsDevice::DestroyVideo * Purpose: Called at low priority to stop video and free the resources */ void STREAMAPI PsDevice::DestroyVideo( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("PsDevice::DestroyVideo()"); PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension; PsDevice *adapter = HwDeviceExtension->psdevice; VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; adapter->Stop( *chan ); // cannot call any other class' services; have to schedule a callback StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, LowToHigh, PHW_PRIORITY_ROUTINE( StreamCompleterControl ), pSrb ); } /* ** VideoGetProperty() ** ** Routine to process video property requests ** ** Arguments: ** ** pSrb - pointer to the stream request block for properties ** ** Returns: ** ** Side Effects: none */ void PsDevice::GetStreamProperty( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("PsDevice::GetStreamProperty()"); PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo; if ( IsEqualGUID( KSPROPSETID_Connection, pSPD->Property->Set ) ) { GetStreamConnectionProperty( pSrb ); } else { pSrb->Status = STATUS_NOT_IMPLEMENTED; } } /* Method: PsDevice::ProcessSetDataFormat * Purpose: Implements SET KSPROPERTY_CONNECTION_DATAFORMAT * Input: chan: VideoChannel & * VidInfHdr: KS_VIDEOINFOHEADER & */ void PsDevice::ProcessSetDataFormat( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("PsDevice::ProcessSetDataFormat()"); VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; // have to stop first Pause( *chan ); // destroy at low prioriy StreamClassCallAtNewPriority( pSrb->StreamObject, pSrb->HwDeviceExtension, Low, PHW_PRIORITY_ROUTINE( DestroyVideoNoComplete ), pSrb ); } /* Method: PsDevice::GetStreamConnectionProperty * Purpose: Obtains allocator and state properties */ void PsDevice::GetStreamConnectionProperty( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("PsDevice::GetStreamConnectionProperty()"); VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo; ULONG Id = pSPD->Property->Id; // index of the property switch ( Id ) { case KSPROPERTY_CONNECTION_ALLOCATORFRAMING: { //KdPrint(( "KSPROPERTY_CONNECTION_ALLOCATORFRAMING\n" )); PKSALLOCATOR_FRAMING Framing = (PKSALLOCATOR_FRAMING) pSPD->PropertyInfo; Framing->RequirementsFlags = KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY | KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER | KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY; Framing->PoolType = NonPagedPool; //KdPrint(( "Framing->Frames == 0x%08X\n", Framing->Frames )); if( (VideoStream)pSrb->StreamObject->StreamNumber == STREAM_IDX_VBI ) { Framing->Frames = 8; } else { //if( Framing->Frames == 0 ) //{ // Framing->Frames = 1; //} //else //{ Framing->Frames = 3; //} } if( chan->IsVideoInfo2() ) { Framing->FrameSize = chan->GetVidHdr2()->bmiHeader.biSizeImage; } else { Framing->FrameSize = chan->GetVidHdr()->bmiHeader.biSizeImage; } Framing->FileAlignment = 0;//FILE_QUAD_ALIGNMENT;// PAGE_SIZE - 1; Framing->Reserved = 0; pSrb->ActualBytesTransferred = sizeof( KSALLOCATOR_FRAMING ); } break; default: break; } } void PsDevice::SetClockMaster( PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("PsDevice::SetClockMaster()"); VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; chan->SetClockMaster( pSrb->CommandData.MasterClockHandle ); } /* Method: AnalogReceiveDataPacket * Purpose: Receives data packets for analog stream ( tuner change notifications ) * Input: SRB */ VOID STREAMAPI AnalogReceiveDataPacket( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("AnalogReceiveDataPacket()"); pSrb->Status = STATUS_SUCCESS; PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension; PsDevice *adapter = HwDeviceExtension->psdevice; DebugOut((1, "AnalogReceiveDataPacket(%x) cmd(%x)\n", pSrb, pSrb->Command)); switch ( pSrb->Command ) { case SRB_READ_DATA: break; case SRB_WRITE_DATA: // // This data packet contains the channel change information // passed on the AnalogVideoIn // if ( pSrb->CommandData.DataBufferArray->FrameExtent == sizeof( KS_TVTUNER_CHANGE_INFO ) ) adapter->ChangeNotifyChannels( pSrb ); break; default: // // invalid / unsupported command. Fail it as such // pSrb->Status = STATUS_NOT_IMPLEMENTED; } StreamCompleterData( pSrb ); } /* Method: AnalogReceiveCtrlPacket * Purpose: Receives control packets for analog stream ( are there any ? ) * Input: SRB */ VOID STREAMAPI AnalogReceiveCtrlPacket( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { Trace t("AnalogReceiveCtrlPacket()"); DebugOut((1, "AnalogReceiveCtrlPacket(%x) cmd(%x)\n", pSrb, pSrb->Command)); pSrb->Status = STATUS_SUCCESS; StreamCompleterControl( pSrb ); } #ifdef ENABLE_DDRAW_STUFF DWORD FAR PASCAL DirectDrawEventCallback( DWORD dwEvent, PVOID pContext, DWORD dwParam1, DWORD dwParam2 ) { switch( dwEvent ) { case DDNOTIFY_PRERESCHANGE: { VideoChannel* pChan = (VideoChannel*)pContext; KdPrint(( "DDNOTIFY_PRERESCHANGE; stream = %d\n", pChan->pSRB_->StreamObject->StreamNumber )); pChan->bPreEventOccurred = TRUE; } break; case DDNOTIFY_POSTRESCHANGE: { VideoChannel* pChan = (VideoChannel*)pContext; KdPrint(( "DDNOTIFY_POSTRESCHANGE; stream = %d\n", pChan->pSRB_->StreamObject->StreamNumber )); pChan->bPostEventOccurred = TRUE; KdPrint(( "before Attempted Renegotiation due to DDNOTIFY_POSTRESCHANGE\n" )); // AttemptRenegotiation(pStrmEx); KdPrint(( "after Attempted Renegotiation due to DDNOTIFY_POSTRESCHANGE\n" )); } break; case DDNOTIFY_PREDOSBOX: { VideoChannel* pChan = (VideoChannel*)pContext; KdPrint(( "DDNOTIFY_PREDOSBOX; stream = %d\n", pChan->pSRB_->StreamObject->StreamNumber )); pChan->bPreEventOccurred = TRUE; } break; case DDNOTIFY_POSTDOSBOX: { VideoChannel* pChan = (VideoChannel*)pContext; KdPrint(( "DDNOTIFY_POSTDOSBOX; stream = %d\n", pChan->pSRB_->StreamObject->StreamNumber )); pChan->bPostEventOccurred = TRUE; KdPrint(( "before Attempted Renegotiation due to DDNOTIFY_POSTDOSBOX\n" )); // AttemptRenegotiation(pStrmEx); KdPrint(( "after Attempted Renegotiation due to DDNOTIFY_POSTDOSBOX\n" )); } break; case DDNOTIFY_CLOSEDIRECTDRAW: { VideoChannel* pChan = (VideoChannel*)pContext; KdPrint(( "DDNOTIFY_CLOSEDIRECTDRAW\n" )); pChan->hKernelDirectDrawHandle = 0; pChan->hUserDirectDrawHandle = 0; } break; case DDNOTIFY_CLOSESURFACE: { VideoChannel* pChan = (VideoChannel*)pContext; PSRB_EXTENSION pSrbExt = (PSRB_EXTENSION)pChan->pSRB_->SRBExtension; KdPrint(( "DDNOTIFY_CLOSESURFACE\n" )); pSrbExt->hKernelSurfaceHandle = 0; } break; default: KdPrint(( "unknown/unhandled ddraw event\n" )); break; } return 0; } BOOL RegisterForDirectDrawEvents( PHW_STREAM_REQUEST_BLOCK pSrb ) { PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension; DDREGISTERCALLBACK ddRegisterCallback; DWORD ddOut; VideoChannel* pChan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; KdPrint(( "stream %d registering for DirectDraw events\n", pSrb->StreamObject->StreamNumber )); // =============== DDEVENT_PRERESCHANGE =============== RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) ); RtlZeroMemory( &ddOut, sizeof(ddOut) ); ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle; ddRegisterCallback.dwEvents = DDEVENT_PRERESCHANGE; ddRegisterCallback.pfnCallback = DirectDrawEventCallback; ddRegisterCallback.pContext = pChan; DxApi( DD_DXAPI_REGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut) ); if( ddOut != DD_OK ) { KdPrint(( "DD_DXAPI_REGISTER_CALLBACK failed.\n" )); return FALSE; } // =============== DDEVENT_POSTRESCHANGE ============== RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) ); RtlZeroMemory( &ddOut, sizeof(ddOut) ); ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle; ddRegisterCallback.dwEvents = DDEVENT_POSTRESCHANGE; ddRegisterCallback.pfnCallback = DirectDrawEventCallback; ddRegisterCallback.pContext = pChan; DxApi(DD_DXAPI_REGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut) ); if( ddOut != DD_OK ) { KdPrint(( "DD_DXAPI_REGISTER_CALLBACK failed.\n" )); return FALSE; } // =============== DDEVENT_PREDOSBOX ================= RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) ); RtlZeroMemory( &ddOut, sizeof(ddOut) ); ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle; ddRegisterCallback.dwEvents = DDEVENT_PREDOSBOX; ddRegisterCallback.pfnCallback = DirectDrawEventCallback; ddRegisterCallback.pContext = pChan; DxApi( DD_DXAPI_REGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut) ); if( ddOut != DD_OK ) { KdPrint(( "DD_DXAPI_REGISTER_CALLBACK failed.\n" )); return FALSE; } // =============== DDEVENT_POSTDOSBOX ================ RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) ); RtlZeroMemory( &ddOut, sizeof(ddOut) ); ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle; ddRegisterCallback.dwEvents = DDEVENT_POSTDOSBOX; ddRegisterCallback.pfnCallback = DirectDrawEventCallback; ddRegisterCallback.pContext = pChan; DxApi( DD_DXAPI_REGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut) ); if( ddOut != DD_OK ) { KdPrint(( "DD_DXAPI_REGISTER_CALLBACK failed.\n" )); return FALSE; } pChan->bKernelDirectDrawRegistered = TRUE; return TRUE; } BOOL UnregisterForDirectDrawEvents( PHW_STREAM_REQUEST_BLOCK pSrb ) { PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension; DDREGISTERCALLBACK ddRegisterCallback; DWORD ddOut; VideoChannel* pChan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; KdPrint(( "stream %d un-registering for DirectDraw events\n", pSrb->StreamObject->StreamNumber )); // =============== DDEVENT_PRERESCHANGE =============== RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) ); RtlZeroMemory( &ddOut, sizeof(ddOut) ); ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle; ddRegisterCallback.dwEvents = DDEVENT_PRERESCHANGE; ddRegisterCallback.pfnCallback = DirectDrawEventCallback; ddRegisterCallback.pContext = pChan; DxApi( DD_DXAPI_UNREGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut)); if( ddOut != DD_OK ) { KdPrint(( "DD_DXAPI_UNREGISTER_CALLBACK failed.\n" )); return FALSE; } // =============== DDEVENT_POSTRESCHANGE ============== RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) ); RtlZeroMemory( &ddOut, sizeof(ddOut) ); ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle; ddRegisterCallback.dwEvents = DDEVENT_POSTRESCHANGE; ddRegisterCallback.pfnCallback = DirectDrawEventCallback; ddRegisterCallback.pContext = pChan; DxApi( DD_DXAPI_UNREGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut) ); if( ddOut != DD_OK ) { KdPrint(( "DD_DXAPI_UNREGISTER_CALLBACK failed.\n" )); return FALSE; } // =============== DDEVENT_PREDOSBOX ================== RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) ); RtlZeroMemory( &ddOut, sizeof(ddOut) ); ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle; ddRegisterCallback.dwEvents = DDEVENT_PREDOSBOX; ddRegisterCallback.pfnCallback = DirectDrawEventCallback; ddRegisterCallback.pContext = pChan; DxApi( DD_DXAPI_UNREGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut) ); if( ddOut != DD_OK ) { KdPrint(( "DD_DXAPI_UNREGISTER_CALLBACK failed.\n" )); return FALSE; } // =============== DDEVENT_POSTDOSBOX ================= RtlZeroMemory( &ddRegisterCallback, sizeof(ddRegisterCallback) ); RtlZeroMemory( &ddOut, sizeof(ddOut) ); ddRegisterCallback.hDirectDraw = pChan->hKernelDirectDrawHandle; ddRegisterCallback.dwEvents = DDEVENT_POSTDOSBOX; ddRegisterCallback.pfnCallback = DirectDrawEventCallback; ddRegisterCallback.pContext = pChan; DxApi( DD_DXAPI_UNREGISTER_CALLBACK, (DWORD) &ddRegisterCallback, sizeof(ddRegisterCallback), (DWORD)&ddOut, sizeof(ddOut) ); if( ddOut != DD_OK ) { KdPrint(( "DD_DXAPI_UNREGISTER_CALLBACK failed.\n" )); return FALSE; } pChan->bKernelDirectDrawRegistered = FALSE; return TRUE; } BOOL OpenKernelDirectDraw( PHW_STREAM_REQUEST_BLOCK pSrb ) { /* VideoChannel* pChan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; if( pChan->hUserDirectDrawHandle != 0 ) { DDOPENDIRECTDRAWIN ddOpenIn; DDOPENDIRECTDRAWOUT ddOpenOut; ASSERT( pChan->hKernelDirectDrawHandle == 0 ); KdPrint(( "stream %d getting kernel ddraw handle\n", pSrb->StreamObject->StreamNumber )); RtlZeroMemory( &ddOpenIn, sizeof(ddOpenIn) ); RtlZeroMemory( &ddOpenOut, sizeof(ddOpenOut) ); ddOpenIn.dwDirectDrawHandle = (DWORD)pChan->hUserDirectDrawHandle; ddOpenIn.pfnDirectDrawClose = DirectDrawEventCallback; ddOpenIn.pContext = pChan; DxApi( DD_DXAPI_OPENDIRECTDRAW, (DWORD)&ddOpenIn, sizeof(ddOpenIn), (DWORD)&ddOpenOut, sizeof(ddOpenOut) ); if( ddOpenOut.ddRVal != DD_OK ) { KdPrint(( "DD_DXAPI_OPENDIRECTDRAW failed.\n" )); } else { pChan->hKernelDirectDrawHandle = ddOpenOut.hDirectDraw; return TRUE; } } */ return FALSE; } BOOL CloseKernelDirectDraw( PHW_STREAM_REQUEST_BLOCK pSrb ) { VideoChannel* pChan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; /* if( pChan->hKernelDirectDrawHandle != 0 ) { DWORD ddOut; DDCLOSEHANDLE ddClose; KdPrint(( "stream %d CloseKernelDirectDraw\n", pSrb->StreamObject->StreamNumber )); ddClose.hHandle = pChan->hKernelDirectDrawHandle; DxApi( DD_DXAPI_CLOSEHANDLE, (DWORD)&ddClose, sizeof(ddClose), (DWORD) &ddOut, sizeof(ddOut) ); pChan->hKernelDirectDrawHandle = 0; if( ddOut != DD_OK ) { KdPrint(( "CloseKernelDirectDraw FAILED.\n" )); return FALSE; } } */ return TRUE; } BOOL IsKernelLockAndFlipAvailable( PHW_STREAM_REQUEST_BLOCK pSrb ) { VideoChannel* pChan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; if( pChan->hKernelDirectDrawHandle != 0 ) { DDGETKERNELCAPSOUT ddGetKernelCapsOut; KdPrint(( "stream %d getting Kernel Caps\n", pSrb->StreamObject->StreamNumber )); RtlZeroMemory( &ddGetKernelCapsOut, sizeof(ddGetKernelCapsOut) ); DxApi( DD_DXAPI_GETKERNELCAPS, (DWORD) &pChan->hKernelDirectDrawHandle, sizeof(pChan->hKernelDirectDrawHandle), (DWORD)&ddGetKernelCapsOut, sizeof(ddGetKernelCapsOut) ); if( ddGetKernelCapsOut.ddRVal != DD_OK ) { //KdPrint(( "DDGETKERNELCAPSOUT failed.\n" )); } else { //KdPrint(( "stream %d KernelCaps = %x\n", pSrb->StreamObject->StreamNumber, ddGetKernelCapsOut.dwCaps )); // TODO:, check the flags here // if (ddGetKernelCapsOut.dwCaps & ???) return TRUE; } } return FALSE; } BOOL OpenKernelDDrawSurfaceHandle( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { VideoChannel* pChan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; PSRB_EXTENSION pSrbExt = (PSRB_EXTENSION)pSrb->SRBExtension; ASSERT( pChan->hKernelDirectDrawHandle != 0 ); ASSERT( pSrbExt->hUserSurfaceHandle != 0 ); if( pSrbExt->hUserSurfaceHandle == 0 ) { DDOPENSURFACEIN ddOpenSurfaceIn; DDOPENSURFACEOUT ddOpenSurfaceOut; //KdPrint(( "stream %d getting Kernel surface handle\n", pSrb->StreamObject->StreamNumber )); RtlZeroMemory( &ddOpenSurfaceIn, sizeof(ddOpenSurfaceIn) ); RtlZeroMemory( &ddOpenSurfaceOut, sizeof(ddOpenSurfaceOut) ); ddOpenSurfaceIn.hDirectDraw = pChan->hUserDirectDrawHandle; ddOpenSurfaceIn.pfnSurfaceClose = DirectDrawEventCallback; ddOpenSurfaceIn.pContext = pSrb; ddOpenSurfaceIn.dwSurfaceHandle = (DWORD)pSrbExt->hUserSurfaceHandle; DxApi( DD_DXAPI_OPENSURFACE, (DWORD)&ddOpenSurfaceIn, sizeof(ddOpenSurfaceIn), (DWORD)&ddOpenSurfaceOut, sizeof(ddOpenSurfaceOut) ); if( ddOpenSurfaceOut.ddRVal != DD_OK ) { pSrbExt->hKernelSurfaceHandle = 0; //KdPrint(( "DD_DXAPI_OPENSURFACE failed.\n" )); } else { pSrbExt->hKernelSurfaceHandle = ddOpenSurfaceOut.hSurface; return TRUE; } } return FALSE; } BOOL CloseKernelDDrawSurfaceHandle( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { VideoChannel* pChan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel; PSRB_EXTENSION pSrbExt = (PSRB_EXTENSION)pSrb->SRBExtension; ASSERT( pChan->hKernelDirectDrawHandle != 0 ); ASSERT( pSrbExt->hUserSurfaceHandle != 0 ); ASSERT( pSrbExt->hKernelSurfaceHandle != 0 ); if( pSrbExt->hKernelSurfaceHandle != 0 ) { DWORD ddOut; DDCLOSEHANDLE ddClose; //KdPrint(( "stream %d ReleaseKernelDDrawSurfaceHandle\n", pSrb->StreamObject->StreamNumber )); ddClose.hHandle = pSrbExt->hKernelSurfaceHandle; DxApi( DD_DXAPI_CLOSEHANDLE, (DWORD)&ddClose, sizeof(ddClose), (DWORD) &ddOut, sizeof(ddOut) ); pSrbExt->hKernelSurfaceHandle = 0; // what else can we do? if( ddOut != DD_OK ) { //KdPrint(( "ReleaseKernelDDrawSurfaceHandle() FAILED.\n" )); return FALSE; } else { return TRUE; } } return FALSE; } BOOL FlipOverlay( HANDLE hDirectDraw, HANDLE hCurrentSurface, HANDLE hTargetSurface ) { DDFLIPOVERLAY ddFlipOverlay; DWORD ddOut; RtlZeroMemory( &ddFlipOverlay, sizeof(ddFlipOverlay) ); ddFlipOverlay.hDirectDraw = hDirectDraw; ddFlipOverlay.hCurrentSurface = hCurrentSurface; ddFlipOverlay.hTargetSurface = hTargetSurface; ddFlipOverlay.dwFlags = 0; DxApi( DD_DXAPI_FLIP_OVERLAY, (DWORD)&ddFlipOverlay, sizeof(ddFlipOverlay), (DWORD)&ddOut, sizeof(ddOut) ); if( ddOut != DD_OK ) { //KdPrint(( "FlipOverlay() FAILED.\n" )); return FALSE; } else { return TRUE; } } #endif