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

📄 dcampkt.c

📁 winddk src目录下的WDM源码压缩!
💻 C
📖 第 1 页 / 共 5 页
字号:
Routine Description:

    Returns the information of all streams that are supported by the driver

Arguments:

    Srb - Pointer to Stream request block

Return Value:

    Nothing

--*/

{
    //
    // pick up the pointer to the stream information data structure
    //
    PIRB pIrb;
    PHW_STREAM_HEADER StreamHeader = &(Srb->CommandData.StreamBuffer->StreamHeader);        
    PDCAM_EXTENSION pDevExt = (PDCAM_EXTENSION) Srb->HwDeviceExtension;
    PHW_STREAM_INFORMATION StreamInfo = &(Srb->CommandData.StreamBuffer->StreamInfo);

    PAGED_CODE();

    pIrb = (PIRB) Srb->SRBExtension;

    //
    // set number of streams
    //

    ASSERT (Srb->NumberOfBytesToTransfer >= 
            sizeof (HW_STREAM_HEADER) +
            sizeof (HW_STREAM_INFORMATION));

    //
    // initialize stream header
    //

    RtlZeroMemory(StreamHeader, 
                sizeof (HW_STREAM_HEADER) +
                sizeof (HW_STREAM_INFORMATION));

    //
    // initialize the number of streams supported
    //

    StreamHeader->NumberOfStreams = 1;
    StreamHeader->SizeOfHwStreamInformation = sizeof(HW_STREAM_INFORMATION);

    //
    // set the device property info
    // 

    StreamHeader->NumDevPropArrayEntries = pDevExt->ulPropSetSupported;
    StreamHeader->DevicePropertiesArray  = &pDevExt->VideoProcAmpSet;


    //
    // Initialize the stream structure.
    //
    // Number of instances field indicates the number of concurrent streams
    // of this type the device can support.  
    //

    StreamInfo->NumberOfPossibleInstances = 1;

    //
    // indicates the direction of data flow for this stream, relative to 
    // the driver
    //

    StreamInfo->DataFlow = KSPIN_DATAFLOW_OUT;

    //
    // dataAccessible - Indicates whether the data is "seen" by the host
    // processor.
    //

    StreamInfo->DataAccessible = TRUE;

    // 
    // Return number of formats and the table.
    // These information is collected dynamically.
    //
    StreamInfo->NumberOfFormatArrayEntries = pDevExt->ModeSupported;
    StreamInfo->StreamFormatsArray = &pDevExt->DCamStrmModes[0];


    //
    // set the property information for the video stream
    //


    StreamInfo->NumStreamPropArrayEntries = NUMBER_VIDEO_STREAM_PROPERTIES;
    StreamInfo->StreamPropertiesArray = (PKSPROPERTY_SET) VideoStreamProperties;

    //
    // set the pin name and category
    //

    StreamInfo->Name = (GUID *) &PINNAME_VIDEO_CAPTURE;
    StreamInfo->Category = (GUID *) &PINNAME_VIDEO_CAPTURE;


    //
    // store a pointer to the topology for the device
    //
        
    Srb->CommandData.StreamBuffer->StreamHeader.Topology = &Topology;


    //
    // indicate success
    //

    Srb->Status = STATUS_SUCCESS;

    DbgMsg2(("\'DCamGetStreamInfo: NumFormat %d, StreamFormatArray %x\n",
        StreamInfo->NumberOfFormatArrayEntries,  StreamInfo->StreamFormatsArray));

}

#define TIME_ROUNDING                        1000   // Give it some rounding error of 100microsec
#define TIME_0750FPS      (1333333+TIME_ROUNDING)   // 1/7.50 * 10,000,000 (unit=100ns)
#define TIME_1500FPS       (666666+TIME_ROUNDING)   // 1/15.0 * 10,000,000 (unit=100ns)  do not round to 666667
#define TIME_3000FPS       (333333+TIME_ROUNDING)   // 1/30.0 * 10,000,000 (unit=100ns)

NTSTATUS
DCamAllocateIsochResource(
    PDCAM_EXTENSION pDevExt,
    PIRB Irb,
    BOOL bAllocateResource
    )
{
    PIRP Irp;
    CCHAR StackSize;
    ULONG ModeIndex;
    PSTREAMEX pStrmEx;
    DWORD dwAvgTimePerFrame, dwCompression;
    ULONG fulSpeed;
    NTSTATUS Status = STATUS_SUCCESS;


    ASSERT(pDevExt);
    pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
    ASSERT(pStrmEx);


    DbgMsg2(("\'DCamAllocateIsochResource: enter; pStrmEx %x; pVideoInfo %x\n", pStrmEx, pStrmEx->pVideoInfoHeader));
    //
    // Now if they're on a YUV4:2:2 format, we've gotta check what
    // resolution they want it at, since we support this format
    // but in two different resolutions (modes on the camera).
    //

    // This is the INDEX to the frame rate and resource allocation; see IsochInfoTable.
    // 0 : reserved
    // 1 : 3.75
    // 2 : 7.5
    // 3 : 15 (DEFAULT_FRAME_RATE)
    // 4 : 30 
    // 5 : 60 (Not supported for Mode 1 & 3)
    dwAvgTimePerFrame = (DWORD) pStrmEx->pVideoInfoHeader->AvgTimePerFrame;
    dwCompression = (DWORD) pStrmEx->pVideoInfoHeader->bmiHeader.biCompression;



    // Determine the Frame rate
    if (dwAvgTimePerFrame      > TIME_0750FPS) 
        pDevExt->FrameRate = 1;        //  3.75FPS
    else if (dwAvgTimePerFrame >  TIME_1500FPS) 
        pDevExt->FrameRate = 2;        //  7.5FPS
    else if (dwAvgTimePerFrame >  TIME_3000FPS) 
        pDevExt->FrameRate = 3;        // 15 FPS
    else 
        pDevExt->FrameRate = 4;        // 30 FPS


    DbgMsg2(("\'DCamAllocateIsochResource: FrameRate: %d FPS\n", (1 << (pDevExt->FrameRate-1)) * 15 / 4));

    // Determine the Video Mode
    switch(dwCompression) {
#ifdef SUPPORT_YUV444          
    case FOURCC_Y444:     // Mode 0
         ModeIndex = VMODE0_YUV444;
         break;
#endif

    case FOURCC_UYVY:     // Mode 1 or 3
         if (pStrmEx->pVideoInfoHeader->bmiHeader.biWidth == 640 &&
             (pStrmEx->pVideoInfoHeader->bmiHeader.biHeight == 480 || 
             pStrmEx->pVideoInfoHeader->bmiHeader.biHeight == -480)) {
              ModeIndex = VMODE3_YUV422;
              // Max frame rate is 15
              if(pDevExt->FrameRate > 3)
                 pDevExt->FrameRate = 3;
         } else
              ModeIndex = VMODE1_YUV422;
         break;

#ifdef SUPPORT_YUV411          
    case FOURCC_Y411:     // Mode 2
         ModeIndex = VMODE2_YUV411;
         break;
#endif

#ifdef SUPPORT_RGB24          
    case KS_BI_RGB:  // = 0
         ModeIndex = VMODE4_RGB24;
         // Max frame rate is 15
         if(pDevExt->FrameRate > 3)
            pDevExt->FrameRate = 3;
         break;
#endif

#ifdef SUPPORT_YUV800
    case FOURCC_Y800:  
         ModeIndex = VMODE5_YUV800;
         break;
#endif

    default:          
         Status = STATUS_NOT_IMPLEMENTED;;
         return Status;;
    }


    DbgMsg1(("\'DCamAllocateIsochResource: ModeIndex=%d, AvgTimePerFrame=%d, FrameRate=%d\n", 
             ModeIndex, dwAvgTimePerFrame, pDevExt->FrameRate));

    //
    // Get an Irp so we can send some allocation commands down
    //

    StackSize = pDevExt->BusDeviceObject->StackSize;
    Irp = IoAllocateIrp(StackSize, FALSE);

    if (!Irp) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    // Calculate the index to use to reference the ISOCH table
    //
    pStrmEx->idxIsochTable = ModeIndex * NUM_POSSIBLE_RATES + pDevExt->FrameRate;

    ASSERT(pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage == IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize);
    DbgMsg2(("\'DCamAllocateIsochResource: ModeIndex=%d, idxIsochTable=%d, biSizeImage=%d, CompletePictureSize=%d\n", 
             ModeIndex, pStrmEx->idxIsochTable, pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage, IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize));          

    //
    // 0. Determine the MAX_SPEED and not use the speed defined in the static table.
    //
    Irb->FunctionNumber = REQUEST_GET_SPEED_BETWEEN_DEVICES;
    Irb->Flags = 0;
    Irb->u.GetMaxSpeedBetweenDevices.fulFlags = USE_LOCAL_NODE;
    Irb->u.GetMaxSpeedBetweenDevices.ulNumberOfDestinations = 0;
    Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
    if(Status) {
        ERROR_LOG(("\'DCamAllocateIsochResource: Error %x while trying to get maximun speed between devices.\n", Status));        

        IoFreeIrp(Irp);
        return STATUS_INSUFFICIENT_RESOURCES;
    }     
    
    fulSpeed = Irb->u.GetMaxSpeedBetweenDevices.fulSpeed;

    //
    // The max speed between devices should be within supported speed range, and
    // must be equal or greater than the required speed for the chosen format.
    //
    if(
        (  fulSpeed != SPEED_FLAGS_100 
        && fulSpeed != SPEED_FLAGS_200 
        && fulSpeed != SPEED_FLAGS_400
        )
        || fulSpeed < IsochInfoTable[pStrmEx->idxIsochTable].SpeedRequired
       ) {

        ASSERT(fulSpeed == SPEED_FLAGS_100 || fulSpeed == SPEED_FLAGS_200 ||  fulSpeed == SPEED_FLAGS_400);
        ASSERT(fulSpeed >= IsochInfoTable[pStrmEx->idxIsochTable].SpeedRequired);

        IoFreeIrp(Irp);
        return STATUS_UNSUCCESSFUL;
    }

    pDevExt->SpeedCode = fulSpeed >> 1;  // Safe for S100, 200 and 400 (is checked above).
    DbgMsg2(("\'GetMaxSpeedBetweenDevices.fulSpeed=%x; SpeedCode:%x\n", fulSpeed, pDevExt->SpeedCode));


    //
    // 1. Allocate CHANNEL
    //       First try to re-allocate the same channel
    //       If it is used, try to get any channel.  1394DCam can only be on channel 0..15
    //
    Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_CHANNEL;
    Irb->Flags = 0;

    //
    //      ULONG           nRequestedChannel;      // Need a specific channel
    //      ULONG           Channel;                // Returned channel
    //      LARGE_INTEGER   ChannelsAvailable;      // Channels available
    // Instead of hardcoded '0'; use -1 to ask the bus driver to get the next available channel for us.
    // -1 (any channel) or an existing channel
    Irb->u.IsochAllocateChannel.nRequestedChannel = pDevExt->IsochChannel;  
    Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
    if(Status) {

        //
        // Due to channel change, 
        // all Pending read will be either resubmitted, 
        // or cancelled (if out of resource).
        //
        pDevExt->bStopIsochCallback = TRUE;  // Set back to FALSE after pending buffer are attached.


        //
        // If this is an initial request and no channel available,
        // free all resource and abort.
        //
        if(pDevExt->IsochChannel == ISOCH_ANY_CHANNEL)
            goto NoResource_abort;

        DbgMsg1(("DCamAllocateIsochResource: last allocated channel %d is not available; pending count %d.\n",  
            pDevExt->IsochChannel, pDevExt->PendingReadCount));                      

        // Try gettting any channel.
        Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_CHANNEL;
        Irb->Flags = 0;
        Irb->u.IsochAllocateChannel.nRequestedChannel = ISOCH_ANY_CHANNEL;  
        Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
        if(Status) {
            ERROR_LOG(("DCamAllocateIsochResource: allocate any channel failed, status %x!\n",  Status));
            goto NoResource_abort;           
        }

        //
        // Channel changed, we MUST reallocate resource.
        // The "stale" resrouce will be free later when 
        // pending packet are detached.
        //

        bAllocateResource = TRUE;
    }   
    
    DbgMsg1(("**IsochAlloc: Channel(Old) %d, requested %d, got %d, HiLo(0x%x:%x), PendingRead %d\n", 
         pDevExt->IsochChannel, 
         Irb->u.IsochAllocateChannel.nRequestedChannel, 
         Irb->u.IsochAllocateChannel.Channel, 
         Irb->u.IsochAllocateChannel.ChannelsAvailable.u.HighPart,
         Irb->u.IsochAllocateChannel.ChannelsAvailable.u.LowPart,
         pDevExt->PendingReadCount));

    // New channel
    pDevExt->IsochChannel = Irb->u.IsochAllocateChannel.Channel;  // Used in allocating iso. resource and reallocation


    //
    // 2. Allocate BANDWIDTH
    //
    Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_BANDWIDTH;
    Irb->Flags = 0;
    Irb->u.IsochAllocateBandwidth.nMaxBytesPerFrameRequested = IsochInfoTable[pStrmEx->idxIsochTable].QuadletPayloadPerPacket << 2;
    Irb->u.IsochAllocateBandwidth.fulSpeed = fulSpeed;
    Irb->u.IsochAllocateBandwidth.hBandwidth = 0;
    Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
    
    if(Status) {
        ERROR_LOG(("DCamAllocateIsochResource: Error %x while trying to allocate Isoch bandwidth\n", Status));                  
        goto NoResource_abort;
    }

    pDevExt->hBandwidth = Irb->u.IsochAllocateBandwidth.hBandwidth;
    DbgMsg2(("**IsochAlloc: nMaxBytesPerFrameRequested %d, fulSpeed %d; hBandWidth 0x%x\n",
         IsochInfoTable[pStrmEx->idxIsochTable].QuadletPayloadPerPacket << 2, fulSpeed, pDevExt->hBandwidth));



    //
    // 3. Allocate RESOURCES
    //    Note: after a bus reset, we need not free and re-allocate this resoruce again.
    //
    if(bAllocateResource) {
        Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_RESOURCES;
        Irb->Flags = 0;
        Irb->u.IsochAllocateResources.fulSpeed = fulSpeed;
        Irb->u.IsochAllocateResources.nChannel = pDevExt->IsochChannel;
        Irb->u.IsochAllocateResources.nMaxBytesPerFrame = IsochInfoTable[pStrmEx->idxIsochTable].QuadletPayloadPerPacket << 2;
        // For slower frame rate use smaller quadlets
        // smaller frame size will use more packet to fill the same amount of data
        // this is why smaller frame rate actually demand more resource !!
        Irb->u.IsochAllocateResources.nNumberOfBuffers = MAX_BUFFERS_SUPPLIED + 1;  // "+1" as a "safety"
        Irb->u.IsochAllocateResources.nMaxBufferSize = IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize;
        if (pDevExt->HostControllerInfomation.HostCapabilities & HOST_INFO_SUPPORTS_RETURNING_ISO_HDR) {       
            Irb->u.IsochAllocateResources.nQuadletsToStrip = 1;
            Irb->u.IsochAllocateResources.fulFlags = RESOURCE_USED_IN_LISTENING | RESOURCE_STRIP_ADDITIONAL_QUADLETS;

        } else {
            Irb->u.IsochAllocateResources.nQuadletsToStrip = 0;
            Irb->u.IsochAllocateResources.fulFlags = RESOURCE_USED_IN_LISTENING;
        }

        Irb->u.IsochAllocateResources.hResource = 0;
        DbgMsg2(("\'DCamAllocateIsochResource: fullSpeed(%d), nMaxBytesPerFrame(%d), nMaxBufferSize(%d)\n", 
                              Irb->u.IsochAllocateResources.fulSpeed,
                              Irb->u.IsochAllocateResources.nMaxBytesPerFrame,
                              Irb->u.IsochAllocateResources.nMaxBufferSize));
        Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);          

        if(Status) {
            ERROR_LOG(("DCamAllocateIsochResource: Error %x while trying to allocate Isoch resources\n", Status));
            goto NoResource_abort;
        }


        pDevExt->hResource = Irb->u.IsochAllocateResources.hResource;

    }

⌨️ 快捷键说明

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