⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 capstrm.cpp

📁 传说中的 视频抓取驱动源码 啊啊啊啊啊啊啊啊啊啊啊啊啊
💻 CPP
📖 第 1 页 / 共 3 页
字号:
*/

VOID CWDMCaptureStream::VideoSetState(PHW_STREAM_REQUEST_BLOCK pSrb, BOOL bVPConnected, BOOL bVPVBIConnected)
{
    //
    // For each stream, the following states are used:
    // 
    // Stop:    Absolute minimum resources are used.  No outstanding IRPs.
    // Pause:   Getting ready to run.  Allocate needed resources so that 
    //          the eventual transition to Run is as fast as possible.
    //          SRBs will be queued at either the Stream class or in your
    //          driver.
    // Run:     Streaming. 
    //
    // Moving to Stop or Run ALWAYS transitions through Pause, so that ONLY 
    // the following transitions are possible:
    //
    // Stop -> Pause
    // Pause -> Run
    // Run -> Pause
    // Pause -> Stop
    //
    // Note that it is quite possible to transition repeatedly between states:
    // Stop -> Pause -> Stop -> Pause -> Run -> Pause -> Run -> Pause -> Stop
    //
    BOOL bStreamCondition;

    DBGINFO(("CWDMCaptureStream::VideoSetState for stream %d\n", pSrb->StreamObject->StreamNumber));

    pSrb->Status = STATUS_SUCCESS;

    switch (pSrb->CommandData.StreamState)  
    {
        case KSSTATE_STOP:
            DBGINFO(("   state KSSTATE_STOP"));

            ASSERT(m_stateChange == ChangeComplete);
            m_stateChange = Stopping;
            FlushBuffers();
            KeResetEvent(&m_specialEvent);
            KeSetEvent(&m_stateTransitionEvent, 0, TRUE);
            KeWaitForSingleObject(&m_specialEvent, Suspended, KernelMode, FALSE, NULL);
            ASSERT(m_stateChange == ChangeComplete);
            break;

        case KSSTATE_ACQUIRE:
            DBGINFO(("   state KSSTATE_ACQUIRE"));
            ASSERT(m_KSState == KSSTATE_STOP);
            break;

        case KSSTATE_PAUSE:
            DBGINFO(("   state KSSTATE_PAUSE"));
            
            switch( pSrb->StreamObject->StreamNumber)
            {
                case STREAM_VideoCapture:
                    bStreamCondition = bVPConnected;
                    break;

                case STREAM_VBICapture:
                    bStreamCondition = bVPVBIConnected;
                    break;

                default:
                    bStreamCondition = FALSE;
                    break;
            }
            
            if( !bStreamCondition)
            {
                pSrb->Status = STATUS_UNSUCCESSFUL;
            }
            else 

            if (m_pVideoDecoder->PreEventOccurred() &&
                        (m_KSState == KSSTATE_STOP || m_KSState == KSSTATE_ACQUIRE))
            {
                pSrb->Status = STATUS_UNSUCCESSFUL;
            }
            else if (m_KSState == KSSTATE_STOP || m_KSState == KSSTATE_ACQUIRE)
            {
                ResetFrameCounters();
                ResetFieldNumber();
                
                if (!GetCaptureHandle())
                    pSrb->Status = STATUS_UNSUCCESSFUL;
            }
            else if (m_KSState == KSSTATE_RUN)
            {
                // Transitioning from run to pause
                ASSERT(m_stateChange == ChangeComplete);
                m_stateChange = Pausing;
                FlushBuffers();
                KeResetEvent(&m_specialEvent);
                KeSetEvent(&m_stateTransitionEvent, 0, TRUE);
                KeWaitForSingleObject(&m_specialEvent, Suspended, KernelMode, FALSE, NULL);
                ASSERT(m_stateChange == ChangeComplete);
            }
            
            break;

        case KSSTATE_RUN:
            DBGINFO(("   state KSSTATE_RUN"));

            ASSERT(m_KSState == KSSTATE_ACQUIRE || m_KSState == KSSTATE_PAUSE);

            if (m_pVideoDecoder->PreEventOccurred())
            {
                pSrb->Status = STATUS_UNSUCCESSFUL;
            }
            else
            {
                ResetFieldNumber();

                // Transitioning from pause to run
                ASSERT(m_stateChange == ChangeComplete);
                m_stateChange = Running;
                KeResetEvent(&m_specialEvent);
                KeSetEvent(&m_stateTransitionEvent, 0, TRUE);
                KeWaitForSingleObject(&m_specialEvent, Suspended, KernelMode, FALSE, NULL);
                ASSERT(m_stateChange == ChangeComplete);
            }
            break;
    }

    if (pSrb->Status == STATUS_SUCCESS) {
        m_KSState = pSrb->CommandData.StreamState;
        DBGINFO((" entered\n"));
    }
    else
        DBGINFO((" NOT entered ***\n"));
}


VOID CWDMCaptureStream::VideoStreamGetConnectionProperty (PHW_STREAM_REQUEST_BLOCK pSrb)
{
    PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
    PKSALLOCATOR_FRAMING Framing = (PKSALLOCATOR_FRAMING) pSPD->PropertyInfo;

    ASSERT(pSPD->Property->Id == KSPROPERTY_CONNECTION_ALLOCATORFRAMING);
    if (pSPD->Property->Id == KSPROPERTY_CONNECTION_ALLOCATORFRAMING) {

        RtlZeroMemory(Framing, sizeof(KSALLOCATOR_FRAMING));

        Framing->RequirementsFlags   =
            KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY |
            KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER |
            KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY;
        Framing->PoolType = NonPagedPool;
        Framing->Frames = NumBuffers;
        Framing->FrameSize = GetFrameSize();
        Framing->FileAlignment = 0;//FILE_QUAD_ALIGNMENT;// PAGE_SIZE - 1;

        pSrb->ActualBytesTransferred = sizeof(KSALLOCATOR_FRAMING);
    }
    else {

        pSrb->Status = STATUS_NOT_IMPLEMENTED;
    }
}

/*
** VideoStreamGetDroppedFramesProperty
**
**    Gets dropped frame information
**
** Arguments:
**
**    pSrb - pointer to the stream request block for properties
**
** Returns:
**
** Side Effects:  none
*/

VOID CWDMCaptureStream::VideoStreamGetDroppedFramesProperty(PHW_STREAM_REQUEST_BLOCK pSrb)
{
    PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
    PKSPROPERTY_DROPPEDFRAMES_CURRENT_S pDroppedFrames = 
        (PKSPROPERTY_DROPPEDFRAMES_CURRENT_S) pSPD->PropertyInfo;

    ASSERT(pSPD->Property->Id == KSPROPERTY_DROPPEDFRAMES_CURRENT);
    if (pSPD->Property->Id == KSPROPERTY_DROPPEDFRAMES_CURRENT) {

        RtlCopyMemory(pDroppedFrames, pSPD->Property, sizeof(KSPROPERTY));  // initialize the unused portion

        GetDroppedFrames(pDroppedFrames);

        DBGINFO(("PictNumber: 0x%x; DropCount: 0x%x; BufSize: 0x%x\n",
            (ULONG) pDroppedFrames->PictureNumber,
            (ULONG) pDroppedFrames->DropCount,
            (ULONG) pDroppedFrames->AverageFrameSize));

        pSrb->ActualBytesTransferred = sizeof (KSPROPERTY_DROPPEDFRAMES_CURRENT_S);
    }
    else {

        pSrb->Status = STATUS_NOT_IMPLEMENTED;
    }
}


VOID CWDMCaptureStream::CloseCapture()
{
    DBGTRACE(("DDNOTIFY_CLOSECAPTURE; stream = %d\n", m_pStreamObject->StreamNumber));

    m_hCapture = 0;
}    


VOID CWDMCaptureStream::EmptyIncomingDataSrbQueue()
{
    KIRQL Irql;
    PKSSTREAM_HEADER pDataPacket;
    
    if ( m_stateChange == Initializing )
    {
        return; // queue not setup yet, so we can return knowing that nothing is in the queue
    }
    
    // Think about replacing with ExInterlockedRemoveHeadList. 
    KeAcquireSpinLock(&m_streamDataLock, &Irql);
    
    while (!IsListEmpty(&m_incomingDataSrbQueue))
    {
        PSRB_DATA_EXTENSION pSrbExt = (PSRB_DATA_EXTENSION)RemoveHeadList(&m_incomingDataSrbQueue);
        PHW_STREAM_REQUEST_BLOCK pSrb = pSrbExt->pSrb;
        
        pSrb->Status = STATUS_SUCCESS;
        pDataPacket = pSrb->CommandData.DataBufferArray;
        pDataPacket->DataUsed = 0;
        
        KeReleaseSpinLock(&m_streamDataLock, Irql);
        DBGINFO(("Completing Srb 0x%x in STATE_STOP\n", pSrb));
        StreamClassStreamNotification(  StreamRequestComplete,
                                        pSrb->StreamObject,
                                        pSrb);
        KeAcquireSpinLock(&m_streamDataLock, &Irql);
    }
    
    KeReleaseSpinLock(&m_streamDataLock, Irql);
}


BOOL CWDMCaptureStream::ReleaseCaptureHandle()
{
    int streamNumber = m_pStreamObject->StreamNumber;
    DWORD ddOut = DD_OK;
    DDCLOSEHANDLE ddClose;

    if (m_hCapture != 0)
    {
        DBGTRACE(("Stream %d releasing capture handle\n", streamNumber));
        
        ddClose.hHandle = m_hCapture;

        DxApi(DD_DXAPI_CLOSEHANDLE, &ddClose, sizeof(ddClose), &ddOut, sizeof(ddOut));

        if (ddOut != DD_OK)
        {
            DBGERROR(("DD_DXAPI_CLOSEHANDLE failed.\n"));
            TRAP();
            return FALSE;
        }
        m_hCapture = 0;
    }
    return TRUE;
}

VOID CWDMCaptureStream::HandleBusmasterCompletion(PHW_STREAM_REQUEST_BLOCK pCurrentSrb)
{
    int streamNumber =  m_pStreamObject->StreamNumber;
    PSRB_DATA_EXTENSION pSrbExt = (PSRB_DATA_EXTENSION)pCurrentSrb->SRBExtension;
    KIRQL Irql;
    // This function is called as a result of DD completing a BM.  That means
    // m_stateChange will not be in the Initializing state for sure

    // First handle case where we get a Busmaster completion
    // indication while we are trying to pause or stop
    if (m_stateChange == Pausing || m_stateChange == Stopping)
    {
        PUCHAR ptr;
        KeAcquireSpinLock(&m_streamDataLock, &Irql);

        // Put it at the head of the temporary 'reversal' queue.
        InsertHeadList(&m_reversalQueue, &pSrbExt->srbListEntry);
        
        if (IsListEmpty(&m_waitQueue))
        {
            // if there is nothing left in the wait queue we can now
            // proceed to move everything back to the incoming queue.
            // This whole ugly ordeal is to
            // make sure that they end up in the original order
            while (!IsListEmpty(&m_reversalQueue))
            {
                ptr = (PUCHAR)RemoveHeadList(&m_reversalQueue);
                InsertHeadList(&m_incomingDataSrbQueue, (PLIST_ENTRY) ptr);
            }
            
            KeReleaseSpinLock(&m_streamDataLock, Irql);
            
            if (m_stateChange == Stopping)
            {
                EmptyIncomingDataSrbQueue();
            }
            
            // Indicate that we have successfully completed this part
            // of the transition to the pause state.
            m_stateChange = ChangeComplete;
            KeSetEvent(&m_specialEvent, 0, FALSE);
            return;
        }

        KeReleaseSpinLock(&m_streamDataLock, Irql);
        return;
    }

    // else it is a regular busmaster completion while in the run state
    else
    {
        ASSERT (pCurrentSrb);
        PKSSTREAM_HEADER    pDataPacket = pCurrentSrb->CommandData.DataBufferArray;
        pDataPacket->OptionsFlags = 0;

        pSrbExt = (PSRB_DATA_EXTENSION)pCurrentSrb->SRBExtension;

        DBGINFO(("FieldNum: %d; ddRVal: 0x%x; polarity: 0x%x\n",
                 pSrbExt->ddCapBuffInfo.dwFieldNumber,
                 pSrbExt->ddCapBuffInfo.ddRVal,
                 pSrbExt->ddCapBuffInfo.bPolarity));

        // It's possible that the srb got cancelled while we were waiting.
        // Currently, this status is reset below
        if (pCurrentSrb->Status == STATUS_CANCELLED)
        {
            DBGINFO(("pCurrentSrb 0x%x was cancelled while we were waiting\n", pCurrentSrb));
            pDataPacket->DataUsed = 0;
        }

        // It's also possible that there was a problem in DD-land
        else if (pSrbExt->ddCapBuffInfo.ddRVal != DD_OK)
        {
            // Two cases of which I am aware.
            // 1) flushed buffers
            if (pSrbExt->ddCapBuffInfo.ddRVal == E_FAIL)
            {
                DBGINFO(("ddRVal = 0x%x. Assuming we flushed\n", pSrbExt->ddCapBuffInfo.ddRVal));
                pDataPacket->DataUsed = 0;
            }
            // 2) something else
            else
            {
                DBGERROR(("= 0x%x. Problem in Busmastering?\n", pSrbExt->ddCapBuffInfo.ddRVal));
                pDataPacket->DataUsed = 0;
            }
        }

        // There is also the remote possibility that everything is OK
        else
        {
            SetFrameInfo(pCurrentSrb);
            TimeStampSrb(pCurrentSrb);
            pDataPacket->DataUsed = pDataPacket->FrameExtent;
        }
        
        DBGINFO(("StreamRequestComplete for SRB 0x%x\n", pCurrentSrb));

        // Always return success. Failure
        // is indicated by setting DataUsed to 0.
        pCurrentSrb->Status = STATUS_SUCCESS;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -