VOID STREAMAPI AdapterCloseStream ( 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; PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat; KS_VIDEOINFOHEADER *pVideoInfoHdr = pStrmEx->pVideoInfoHeader; DbgLogInfo(("TestCap: -------- ADAPTERCLOSESTREAM ------ StreamNumber=%d\n", StreamNumber)); if (pHwDevExt->StreamSRBListSize > 0) { VideoQueueCancelAllSRBs (pStrmEx); DbgLogError(("TestCap: Outstanding SRBs at stream close!!!\n")); } pHwDevExt->ActualInstances[StreamNumber]--; ASSERT (pHwDevExt->pStrmEx [StreamNumber] != 0); pHwDevExt->pStrmEx [StreamNumber] = 0; // // the minidriver should free any resources that were allocate at // open stream time etc. // // Free the variable length VIDEOINFOHEADER if (pVideoInfoHdr) { ExFreePool(pVideoInfoHdr); pStrmEx->pVideoInfoHeader = NULL; } // Make sure we no longer reference the clock pStrmEx->hMasterClock = NULL; // Make sure the state is reset to stopped, pStrmEx->KSState = KSSTATE_STOP; }
VOID STREAMAPI VideoSetState( 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; KSSTATE PreviousState; // // For each stream, the following states are used: // // Stop: Absolute minimum resources are used. No outstanding IRPs. // Acquire: KS only state that has no DirectShow correpondence // Acquire needed resources. // Pause: Getting ready to run. Allocate needed resources so that // the eventual transition to Run is as fast as possible. // Read SRBs will be queued at either the Stream class // or in your driver (depending on when you send "ReadyForNext") // and whether you're using the Stream class for synchronization // Run: Streaming. // // Moving to Stop to Run always transitions through Pause. // // But since a client app could crash unexpectedly, drivers should handle // the situation of having outstanding IRPs cancelled and open streams // being closed WHILE THEY ARE STREAMING! // // Note that it is quite possible to transition repeatedly between states: // Stop -> Pause -> Stop -> Pause -> Run -> Pause -> Run -> Pause -> Stop // // // 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); 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->FrameInfo.PictureNumber = 0; pStrmEx->FrameInfo.DropCount = 0; pStrmEx->FrameInfo.dwFrameFlags = 0; // Setup the next timer callback(s) VideoTimerRoutine(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) }