Camx process_capture_request流程

process_capture_request 流程

1.camxhaldevice.cpp–>ProcessCaptureRequest

文件路径:camx\src\core\hal\camxhaldevice.cpp

CamxResult HALDevice::ProcessCaptureRequest(
    Camera3CaptureRequest* pRequest)
{
    CamxResult result = CamxResultEFailed;

    if (TRUE == IsCHIModuleInitialized())
    {
        // Keep track of information related to request for error conditions
        PopulateFrameworkRequestBuffer(pRequest);

        result = GetCHIAppCallbacks()->chi_override_process_request(reinterpret_cast<const camera3_device*>(&m_camera3Device),reinterpret_cast<camera3_capture_request_t*>(pRequest),NULL);
        if (CamxResultSuccess != result)
        {
            // Remove the request from the framework data list if the request fails
            RemoveFrameworkRequestBuffer(pRequest);
        }
    }
    return result;
}

2.chxextensioninterface.cpp–>chi_override_process_request

文件路径:chi-cdk\core\chiframework\chxextensioninterface.cpp

static CDKResult chi_override_process_request(
    const camera3_device_t*     camera3_device,
    camera3_capture_request_t*  capture_request,
    void*                       priv)
{
    ExtensionModule* pExtensionModule = ExtensionModule::GetInstance();

    return pExtensionModule->OverrideProcessRequest(camera3_device, capture_request, priv);
}

3.chxextensionmodule.cpp–>OverrideProcessRequest

文件路径:chi-cdk\core\chiframework\chxextensioninterface.cpp
usecase对象存在之后,开始真正的capturerequest请求,首次的时候没有usecase对象,需要创建use case对象。

CDKResult ExtensionModule::OverrideProcessRequest(
    const camera3_device_t*     camera3_device,
    camera3_capture_request_t*  pCaptureRequest,
    VOID*                       pPriv)
{
    CDKResult result = CDKResultSuccess;

    for (UINT32 i = 0; i < pCaptureRequest->num_output_buffers; i++)
    {
        if (NULL != pCaptureRequest->output_buffers)
        {
            ChxUtils::WaitOnAcquireFence(&pCaptureRequest->output_buffers[i]);
            INT*   pAcquireFence = (INT*)&pCaptureRequest->output_buffers[i].acquire_fence;
            *pAcquireFence = -1;
        }
    }

    UINT32 logicalCameraId = GetCameraIdfromDevice(camera3_device);
    if (CDKInvalidId != logicalCameraId)
    {
        if (NULL != pCaptureRequest->settings)
        {
            FreeLastKnownRequestSetting(logicalCameraId);
            m_pLastKnownRequestSettings[logicalCameraId] = allocate_copy_camera_metadata_checked(pCaptureRequest->settings,
                get_camera_metadata_size(pCaptureRequest->settings));
        }
        // 如果设置不可用,则在刷新后设置有效的metadata
        if ((TRUE == m_hasFlushOccurred[logicalCameraId]) &&
            (NULL == pCaptureRequest->settings))
        {
            pCaptureRequest->settings = m_pLastKnownRequestSettings[logicalCameraId];
            m_hasFlushOccurred[logicalCameraId] = FALSE;
        }

        if (TRUE == static_cast<BOOL>(ChxUtils::AtomicLoadU32(&m_aFlushInProgress[logicalCameraId])))
        {
            HandleProcessRequestErrorAllPCRs(pCaptureRequest, logicalCameraId);
            return CDKResultSuccess;
        }

        if (ChxUtils::AndroidMetadata::IsLongExposureCapture(const_cast<camera_metadata_t*>(pCaptureRequest->settings)))
        {
            ChxUtils::AtomicStoreU32(&m_aLongExposureInProgress, TRUE);
            m_longExposureFrame = pCaptureRequest->frame_number;
        }

        m_pRecoveryLock[logicalCameraId]->Lock();
        if (TRUE == m_RecoveryInProgress[logicalCameraId])
        {
            m_pRecoveryCondition[logicalCameraId]->Wait(m_pRecoveryLock[logicalCameraId]->GetNativeHandle());
        }
        m_pRecoveryLock[logicalCameraId]->Unlock();

        // Save the original metadata
        const camera_metadata_t* pOriginalMetadata = pCaptureRequest->settings;
        (VOID)pPriv;

        m_pPCRLock[logicalCameraId]->Lock();
        if (NULL != m_pSelectedUsecase[logicalCameraId])
        {
            m_originalFrameWorkNumber[logicalCameraId] = pCaptureRequest->frame_number;
            // 如果框架没有发送任何metadata,则发生恢复,发送有效的元数据
            if (m_firstFrameAfterRecovery[logicalCameraId] == pCaptureRequest->frame_number &&
                NULL == pCaptureRequest->settings)
            {
                pCaptureRequest->settings = m_pLastKnownRequestSettings[logicalCameraId];
                m_firstFrameAfterRecovery[logicalCameraId] = 0;
            }

            if (pCaptureRequest->output_buffers != NULL)
            {
                for (UINT i = 0; i < pCaptureRequest->num_output_buffers; i++)
                {
                    if ((NULL != m_pPerfLockManager[logicalCameraId]) &&
                        (pCaptureRequest->output_buffers[i].stream->format == ChiStreamFormatBlob) &&
                        ((pCaptureRequest->output_buffers[i].stream->data_space ==
                            static_cast<android_dataspace_t>(DataspaceV0JFIF)) ||
                        (pCaptureRequest->output_buffers[i].stream->data_space ==
                            static_cast<android_dataspace_t>(DataspaceJFIF))))
                    {
                        m_pPerfLockManager[logicalCameraId]->AcquirePerfLock(PERF_LOCK_SNAPSHOT_CAPTURE, 2000);
                        break;
                    }

                    if ((NULL != m_pPerfLockManager[logicalCameraId]) &&
                        TRUE == UsecaseSelector::IsHEIFStream(pCaptureRequest->output_buffers[i].stream))
                    {
                        m_pPerfLockManager[logicalCameraId]->AcquirePerfLock(PERF_LOCK_SNAPSHOT_CAPTURE, 2000);
                        break;
                    }
                }
            }

            result = m_pSelectedUsecase[logicalCameraId]->ProcessCaptureRequest(pCaptureRequest);
        }

        if (pCaptureRequest->settings != NULL)
        {
            // Restore the original metadata pointer that came from the framework
            pCaptureRequest->settings = pOriginalMetadata;
        }

        // Need to return success on PCR to allow FW to continue sending requests
        if (result == CDKResultEBusy)
        {
            result = CDKResultSuccess;
        }

        if (result == CamxResultECancelledRequest)
        {
            // Ignore the Failure if flush or recovery returned CamcelRequest
            CHX_LOG("Flush/Recovery is in progress %d and so ignore failure", pCaptureRequest->frame_number);
            result = CDKResultSuccess;
        }

        m_pPCRLock[logicalCameraId]->Unlock();
    }
    else
    {
        CHX_LOG_ERROR("Invalid logical camera id device:%p!!", camera3_device);
    }
    return result;
} 

4.chxadvancamerausercase.cpp–>AdavanceCameraUsecase.ExecuteCaptureRequest

文件路径:vendor\qcom\proprietary\chi-cdk\core\chiusecase\chxadvancedcamerausecase.cpp

这里从chxusecase.cpp基类中ProcessCaptureRequest直接调用过来的

CDKResult CameraUsecaseBase::ExecuteCaptureRequest(
    camera3_capture_request_t* pRequest)
{
    // Base implementation finds the buffers that go to each output and invokes SubmitRequest for each pipeline with outputs
    // If the advanced class wishes to use this function, but not invoke all the pipelines, the output produced from the disired
    // inactive pipeline should be removed from the pRequest->output_buffers
    CDKResult result = CDKResultSuccess;

    CHX_LOG("CameraUsecaseBase::ExecuteCaptureRequest for frame %d with %d output buffers",
        pRequest->frame_number, pRequest->num_output_buffers);

    static const UINT32 NumOutputBuffers = 5;

    UINT frameIndex = pRequest->frame_number % MaxOutstandingRequests;

    if (InvalidId != m_rtSessionIndex)
    {
        UINT32 rtPipeline = m_sessions[m_rtSessionIndex].rtPipelineIndex;

        if (InvalidId != rtPipeline)
        {
            m_selectedSensorModeIndex =
                m_sessions[m_rtSessionIndex].pipelines[rtPipeline].pPipeline->GetSensorModeInfo()->modeIndex;
            result = UpdateSensorModeIndex(const_cast<camera_metadata_t*>(pRequest->settings));
        }
    }

    for (UINT session = 0; session < MaxSessions; session++)
    {
        BOOL bIsOffline = FALSE;

        for (UINT pipeline = 0; pipeline < m_sessions[session].numPipelines; pipeline++)
        {
            if (NULL != pRequest->input_buffer)
            {
                bIsOffline = TRUE;

                result = WaitForDeferThread();

                if (CDKResultSuccess != result)
                {
                    CHX_LOG_ERROR("Defer thread failure");
                    break;
                }

                // Skip submitting to realtime pipelines when an input buffer is provided
                if (TRUE == m_sessions[session].pipelines[pipeline].pPipeline->IsRealTime())
                {
                    continue;
                }
            }
            else
            {
                // Skip submitting to offline pipelines when an input buffer is not provided
                if (FALSE == m_sessions[session].pipelines[pipeline].pPipeline->IsRealTime())
                {
                    continue;
                }
            }

            CHISTREAMBUFFER outputBuffers[NumOutputBuffers] = { { 0 } };
            UINT32          outputCount                     = 0;
            PipelineData*   pPipelineData                   = &m_sessions[session].pipelines[pipeline];

            for (UINT32 buffer = 0; buffer < pRequest->num_output_buffers; buffer++)
            {
                for (UINT stream = 0; stream < pPipelineData->numStreams; stream++)
                {
                    if ( (TRUE == bIsOffline) &&
                        (FALSE == m_sessions[session].pipelines[pipeline].pPipeline->IsRealTime()) &&
                        (TRUE  == m_bCloningNeeded) )
                    {
                        UINT index = 0;
                        if (TRUE == IsThisClonedStream(m_pClonedStream, pPipelineData->pStreams[stream], &index))
                        {
                            if ((reinterpret_cast<CHISTREAM*>(pRequest->output_buffers[buffer].stream) ==
                                m_pFrameworkOutStreams[index]))
                            {
                                ChxUtils::PopulateHALToChiStreamBuffer(&pRequest->output_buffers[buffer],
                                                                       &outputBuffers[outputCount]);
                                outputBuffers[outputCount].pStream = pPipelineData->pStreams[stream];
                                outputCount++;
                            }
                        }
                    }
                    else
                    {
                        if (reinterpret_cast<CHISTREAM*>(pRequest->output_buffers[buffer].stream) ==
                            pPipelineData->pStreams[stream])
                        {
                            ChxUtils::PopulateHALToChiStreamBuffer(&pRequest->output_buffers[buffer],
                                                                   &outputBuffers[outputCount]);
                            outputCount++;
                        }
                    }
                }
            }

            if (0 < outputCount)
            {
                CHICAPTUREREQUEST request       = { 0 };
                CHISTREAMBUFFER   inputBuffer   = { 0 };
                UINT32            sensorModeIndex;

                if (NULL != pRequest->input_buffer)
                {
                    request.numInputs     = 1;
                    ChxUtils::PopulateHALToChiStreamBuffer(pRequest->input_buffer, &inputBuffer);
                    request.pInputBuffers = &inputBuffer;
                }

                request.frameNumber       = pRequest->frame_number;
                request.hPipelineHandle   = reinterpret_cast<CHIPIPELINEHANDLE>(
                                                m_sessions[session].pSession->GetPipelineHandle());
                request.numOutputs        = outputCount;
                request.pOutputBuffers    = outputBuffers;
                request.pPrivData         = &m_privData[frameIndex];

                UpdateMetadataBuffers(pRequest, pPipelineData->id, &request, session, pipeline, !bIsOffline);

                CHIPIPELINEREQUEST submitRequest = { 0 };
                submitRequest.pSessionHandle     = reinterpret_cast<CHIHANDLE>(
                                                        m_sessions[session].pSession->GetSessionHandle());
                submitRequest.numRequests        = 1;
                submitRequest.pCaptureRequests   = &request;

                UINT32 numPCRsBeforeStreamOn = ExtensionModule::GetInstance()->GetNumPCRsBeforeStreamOn();

                if (1 > numPCRsBeforeStreamOn)
                {
                    // Activate pipeline before submitting request when EarlyPCR disabled
                    CheckAndActivatePipeline(m_sessions[session].pSession);
                }

                CHX_LOG("Submitting request to Session %d Pipeline %d outputCount=%d", session, pipeline, outputCount);

                CHX_LOG_REQMAP("frame: %u  <==>  (chiFrameNum) chiOverrideFrameNum: %" PRIu64,
                               GetAppFrameNum(request.frameNumber),
                               request.frameNumber);

                result = SubmitRequest(&submitRequest);

                if (CDKResultSuccess != result)
                {
                    CHX_LOG_ERROR("Submit request failure for session:%d", session);
                    break;
                }

                if (0 < numPCRsBeforeStreamOn)
                {
                    // Activate pipeline after submitting request when EarlyPCR enabled
                    CheckAndActivatePipeline(m_sessions[session].pSession);
                }

            }
        }

        if (CDKResultSuccess != result)
        {
            CHX_LOG_ERROR("Defer thread or submit request failure for session:%d", session);
            break;
        }
    }

    return result;
}

5.chxadvancedcamerausecase.cpp–>SelectFeatureToExecuteCaptureRequest

文件路径:vendor\qcom\proprietary\chi-cdk\core\chiusecase\chxadvancedcamerausecase.cpp

Feature* AdvancedCameraUsecase::SelectFeatureToExecuteCaptureRequest(
    camera3_capture_request_t* pRequest,
    UINT32                     physicalCameraIndex)
{
    // OEM to change
    // @todo add logic to select the feature to run the request
    Feature*    pFeature                = NULL;
    UINT32      enabledAdvanceFeatures  = ExtensionModule::GetInstance()->GetAdvanceFeatureMask();

    if (m_enabledFeaturesCount[physicalCameraIndex] == 0)
    {
        return NULL;
    }

    BOOL isMultiframefeature = FALSE;
    BOOL isHDRSceneMode = FALSE;
    UINT32 burstShotFps = 0;
    UINT32 customNoiseReduction = 0;
    camera_metadata_t *metadata = const_cast<camera_metadata_t*>(pRequest->settings);

    camera_metadata_entry_t entry = { 0 };

    entry.tag = ExtensionModule::GetInstance()->GetVendorTagId(VendorTag::BurstFps);
    INT32 status = find_camera_metadata_entry(metadata, entry.tag, &entry);
    if (0 == status)
    {
        burstShotFps = static_cast<UINT32>(*(entry.data.u8));
        CHX_LOG_INFO("Burst mode selected %d", burstShotFps);
    }

    entry.tag = ExtensionModule::GetInstance()->GetVendorTagId(VendorTag::CustomNoiseReduction);
    status = find_camera_metadata_entry(metadata, entry.tag, &entry);
    if (0 == status)
    {
        customNoiseReduction = static_cast<UINT32>(*(entry.data.u8));
        CHX_LOG_INFO("Custom Noise Reduction %d", customNoiseReduction);
    }


    entry.tag = ANDROID_NOISE_REDUCTION_MODE;
    status = find_camera_metadata_entry(metadata, entry.tag, &entry);

    if (0 == status)
    {
        INT32 controlNoiseReductionMode = static_cast<INT32>(*(entry.data.i32));
        CHX_LOG_INFO("Noise Reduction Mode %d", controlNoiseReductionMode);
        isMultiframefeature =
            (ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY == controlNoiseReductionMode) ? TRUE : FALSE;
    }

    entry.tag = ANDROID_CONTROL_SCENE_MODE;
    status = find_camera_metadata_entry(metadata, entry.tag, &entry);

    if (0 == status)
    {
        INT32 controlSceneMode = static_cast<INT32>(*(entry.data.i32));
        CHX_LOG_INFO("Scene Mode %d", controlSceneMode);
        isHDRSceneMode =
            (ANDROID_CONTROL_SCENE_MODE_HDR == controlSceneMode) ? TRUE : FALSE;
    }

    if ((TRUE == isHDRSceneMode) && (TRUE == isMultiframefeature))
    {
        // If both HDR and Noise Reduction High quality enabled, give priority to HDR
        isMultiframefeature = FALSE;
    }

    if ((NULL != m_pLastSnapshotFeature) &&
        (FeatureStatus::BUSY == m_pLastSnapshotFeature->GetFeatureStatus()))
    {
        CHX_LOG_INFO("Mark to reject snapshot request for frame number=%d", pRequest->frame_number);
        m_rejectedSnapshotRequestList[pRequest->frame_number % MaxOutstandingRequests] = TRUE;
    }
    else
    {
        for (UINT32 i = 0; i < m_enabledFeaturesCount[physicalCameraIndex]; i++)
        {
            if (AdvanceFeature2Wrapper == (enabledAdvanceFeatures & AdvanceFeature2Wrapper))
            {
                if (FeatureType::Feature2 == m_enabledFeatures[physicalCameraIndex][i]->GetFeatureType())
                {
                    pFeature = m_enabledFeatures[physicalCameraIndex][i];
                    break;
                }
            }
            else if ((0 == burstShotFps) &&
                     (NULL == pRequest->input_buffer) &&
                     (1 == customNoiseReduction))
            {
                if (TRUE == isMultiframefeature)
                {
                    // Select enabled multiframe feature
                    if ((FeatureType::MFNR == m_enabledFeatures[physicalCameraIndex][i]->GetFeatureType()) ||
                        (FeatureType::SWMF == m_enabledFeatures[physicalCameraIndex][i]->GetFeatureType()))
                    {
                        pFeature = m_enabledFeatures[physicalCameraIndex][i];
                        break;
                    }
                }

                if (TRUE == isHDRSceneMode)
                {
                    // Select HDR  feature
                    if (FeatureType::HDR == m_enabledFeatures[physicalCameraIndex][i]->GetFeatureType())
                    {
                        pFeature = m_enabledFeatures[physicalCameraIndex][i];
                        break;
                    }
                }
            }
        }

        if (NULL == pFeature)
        {
            if (FALSE == IsMultiCameraUsecase())
            {
                // By default choose ZSL/yuvcb feature for Single camera
                // By default SAT will be choosen for Dual Camera
                pFeature = m_enabledFeatures[physicalCameraIndex][0];
            }
        }

        m_pLastSnapshotFeature = pFeature;
    }

    if ((UsecaseId::QuadCFA == m_usecaseId) &&
        (0 == (enabledAdvanceFeatures & AdvanceFeature2Wrapper)) &&
        (0 == (enabledAdvanceFeatures & AdvanceFeatureSWMF)))
    {
        // Feature QuadCFA is selected when iso gain is below pre-defined threshold,
        // in order to trigger remosaic snapshot (non-zsl).
        //
        // If a multi-frame feature is selected according to above rules,
        // it will be added as a sub feature after qcfa remosaic snapshot,
        // other wise single remosaic snapshot will be triggered
        Feature* pFeaturebyGain = PickAdvanceFeatureByGain(m_rdiStreamIndex);

        if ((NULL != pFeaturebyGain) && (FeatureType::QuadCFA == pFeaturebyGain->GetFeatureType()))
        {
            UINT32 frameIndex = pRequest->frame_number % MaxOutstandingRequests;

            m_snapshotFeatures[frameIndex].appFrameNum = pRequest->frame_number;
            m_snapshotFeatures[frameIndex].featureInfo[m_snapshotFeatures[frameIndex].numOfFeatures].pFeature = pFeaturebyGain;
            m_snapshotFeatures[frameIndex].numOfFeatures++;

            // currently only support comination of qcfa + mfnr
            if ((NULL != pFeature) && (FeatureType::MFNR == pFeature->GetFeatureType()))
            {
                UINT32 index = m_snapshotFeatures[frameIndex].numOfFeatures;
                m_snapshotFeatures[frameIndex].featureInfo[index].pFeature = pFeature;
                m_snapshotFeatures[frameIndex].numOfFeatures++;

                CHX_LOG("Multi frame remosaic snapshot, sub Feature: pFeature:%p, type:%d",
                    pFeature, pFeature->GetFeatureType());
            }
            else
            {
                CHX_LOG_INFO("Single remosaic snapshot");
            }

            // set FeatureQuadCFA as first Feature
            pFeature = pFeaturebyGain;
        }
    }

    // Uncomment following code to enable MFNR/MFSR testing
    // pFeature = PickAdvanceFeature(pRequest);

    if (NULL != pFeature)
    {
        CHX_LOG("Select Feature %p type %d for request:%d", pFeature, pFeature->GetFeatureType(),
            pRequest->frame_number);
    }
    else
    {
        CHX_LOG_ERROR("no feature selected for request=%d", pRequest->frame_number);
    }

    // return the first Feature
    return pFeature;
}

6.chxadvancedcamerausecase.cpp–>ExecuteCaptureRequest

文件路径:vendor\qcom\proprietary\chi-cdk\core\chiusecase\chxadvancedcamerausecase.cpp

CDKResult CameraUsecaseBase::ExecuteCaptureRequest(
    camera3_capture_request_t* pRequest)
{
    // Base implementation finds the buffers that go to each output and invokes SubmitRequest for each pipeline with outputs
    // If the advanced class wishes to use this function, but not invoke all the pipelines, the output produced from the disired
    // inactive pipeline should be removed from the pRequest->output_buffers
    CDKResult result = CDKResultSuccess;

    CHX_LOG("CameraUsecaseBase::ExecuteCaptureRequest for frame %d with %d output buffers",
        pRequest->frame_number, pRequest->num_output_buffers);

    static const UINT32 NumOutputBuffers = 5;

    UINT frameIndex = pRequest->frame_number % MaxOutstandingRequests;

    if (InvalidId != m_rtSessionIndex)
    {
        UINT32 rtPipeline = m_sessions[m_rtSessionIndex].rtPipelineIndex;

        if (InvalidId != rtPipeline)
        {
            m_selectedSensorModeIndex =
                m_sessions[m_rtSessionIndex].pipelines[rtPipeline].pPipeline->GetSensorModeInfo()->modeIndex;
            result = UpdateSensorModeIndex(const_cast<camera_metadata_t*>(pRequest->settings));
        }
    }

    for (UINT session = 0; session < MaxSessions; session++)
    {
        BOOL bIsOffline = FALSE;

        for (UINT pipeline = 0; pipeline < m_sessions[session].numPipelines; pipeline++)
        {
            if (NULL != pRequest->input_buffer)
            {
                bIsOffline = TRUE;

                result = WaitForDeferThread();

                if (CDKResultSuccess != result)
                {
                    CHX_LOG_ERROR("Defer thread failure");
                    break;
                }

                // Skip submitting to realtime pipelines when an input buffer is provided
                if (TRUE == m_sessions[session].pipelines[pipeline].pPipeline->IsRealTime())
                {
                    continue;
                }
            }
            else
            {
                // Skip submitting to offline pipelines when an input buffer is not provided
                if (FALSE == m_sessions[session].pipelines[pipeline].pPipeline->IsRealTime())
                {
                    continue;
                }
            }

            CHISTREAMBUFFER outputBuffers[NumOutputBuffers] = { { 0 } };
            UINT32          outputCount                     = 0;
            PipelineData*   pPipelineData                   = &m_sessions[session].pipelines[pipeline];

            for (UINT32 buffer = 0; buffer < pRequest->num_output_buffers; buffer++)
            {
                for (UINT stream = 0; stream < pPipelineData->numStreams; stream++)
                {
                    if ( (TRUE == bIsOffline) &&
                        (FALSE == m_sessions[session].pipelines[pipeline].pPipeline->IsRealTime()) &&
                        (TRUE  == m_bCloningNeeded) )
                    {
                        UINT index = 0;
                        if (TRUE == IsThisClonedStream(m_pClonedStream, pPipelineData->pStreams[stream], &index))
                        {
                            if ((reinterpret_cast<CHISTREAM*>(pRequest->output_buffers[buffer].stream) ==
                                m_pFrameworkOutStreams[index]))
                            {
                                ChxUtils::PopulateHALToChiStreamBuffer(&pRequest->output_buffers[buffer],
                                                                       &outputBuffers[outputCount]);
                                outputBuffers[outputCount].pStream = pPipelineData->pStreams[stream];
                                outputCount++;
                            }
                        }
                    }
                    else
                    {
                        if (reinterpret_cast<CHISTREAM*>(pRequest->output_buffers[buffer].stream) ==
                            pPipelineData->pStreams[stream])
                        {
                            ChxUtils::PopulateHALToChiStreamBuffer(&pRequest->output_buffers[buffer],
                                                                   &outputBuffers[outputCount]);
                            outputCount++;
                        }
                    }
                }
            }

            if (0 < outputCount)
            {
                CHICAPTUREREQUEST request       = { 0 };
                CHISTREAMBUFFER   inputBuffer   = { 0 };
                UINT32            sensorModeIndex;

                if (NULL != pRequest->input_buffer)
                {
                    request.numInputs     = 1;
                    ChxUtils::PopulateHALToChiStreamBuffer(pRequest->input_buffer, &inputBuffer);
                    request.pInputBuffers = &inputBuffer;
                }

                request.frameNumber       = pRequest->frame_number;
                request.hPipelineHandle   = reinterpret_cast<CHIPIPELINEHANDLE>(
                                                m_sessions[session].pSession->GetPipelineHandle());
                request.numOutputs        = outputCount;
                request.pOutputBuffers    = outputBuffers;
                request.pPrivData         = &m_privData[frameIndex];

                UpdateMetadataBuffers(pRequest, pPipelineData->id, &request, session, pipeline, !bIsOffline);

                CHIPIPELINEREQUEST submitRequest = { 0 };
                submitRequest.pSessionHandle     = reinterpret_cast<CHIHANDLE>(
                                                        m_sessions[session].pSession->GetSessionHandle());
                submitRequest.numRequests        = 1;
                submitRequest.pCaptureRequests   = &request;

                UINT32 numPCRsBeforeStreamOn = ExtensionModule::GetInstance()->GetNumPCRsBeforeStreamOn();

                if (1 > numPCRsBeforeStreamOn)
                {
                    // Activate pipeline before submitting request when EarlyPCR disabled
                    CheckAndActivatePipeline(m_sessions[session].pSession);
                }

                CHX_LOG("Submitting request to Session %d Pipeline %d outputCount=%d", session, pipeline, outputCount);

                CHX_LOG_REQMAP("frame: %u  <==>  (chiFrameNum) chiOverrideFrameNum: %" PRIu64,
                               GetAppFrameNum(request.frameNumber),
                               request.frameNumber);

                result = SubmitRequest(&submitRequest);

                if (CDKResultSuccess != result)
                {
                    CHX_LOG_ERROR("Submit request failure for session:%d", session);
                    break;
                }

                if (0 < numPCRsBeforeStreamOn)
                {
                    // Activate pipeline after submitting request when EarlyPCR enabled
                    CheckAndActivatePipeline(m_sessions[session].pSession);
                }

            }
        }

        if (CDKResultSuccess != result)
        {
            CHX_LOG_ERROR("Defer thread or submit request failure for session:%d", session);
            break;
        }
    }

    return result;
}

7.chxextensionmodule.cpp–>ActivatePipeline

CDKResult ExtensionModule::ActivatePipeline(
    CHIHANDLE             sessionHandle,
    CHIPIPELINEDESCRIPTOR pipelineHandle)
{
    return g_chiContextOps.pActivatePipeline(m_hCHIContext, sessionHandle, pipelineHandle, NULL);

8.camxchi.cpp–>ChiActivatePipeline

static CDKResult ChiActivatePipeline(
    CHIHANDLE          hChiContext,
    CHIHANDLE          hSession,
    CHIHANDLE          hPipeline,
    CHISENSORMODEINFO* pModeInfo)
{
    CDKResult           result              = CDKResultSuccess;
    ChiContext*         pChiContext         = GetChiContext(hChiContext);
    CHISession*         pChiSession         = GetChiSession(hSession);
    CHIPIPELINEHANDLE   hPipelineDescriptor = hPipeline;

    CAMX_UNREFERENCED_PARAM(pModeInfo);

    result = pChiContext->ActivatePipeline(pChiSession, hPipelineDescriptor);

    return result;
}

9.camxchicontext.cpp–>ActivatePipeline

CamxResult ChiContext::ActivatePipeline(
    CHISession*         pChiSession,
    CHIPIPELINEHANDLE   hPipelineDescriptor)
{
    CAMX_ASSERT(NULL != pChiSession);
    CAMX_ASSERT(NULL != hPipelineDescriptor);

    CamxResult result = CamxResultSuccess;

    if (TRUE == pChiSession->UsingResourceManager(0))
    {
        ResourceID resourceId = static_cast<ResourceID>(ResourceType::RealtimePipeline);
        GetResourceManager()->CheckAndAcquireResource(resourceId, static_cast<VOID*>(hPipelineDescriptor), 0);
    }

    result = pChiSession->StreamOn(hPipelineDescriptor);

    return result;
}

10.camxsession.cpp–>StreamOn

CamxResult Session::StreamOn(
    CHIPIPELINEHANDLE hPipelineDescriptor)
{
    UINT32     index  = 0;
    CamxResult result = CamxResultSuccess;

    // input pipelineIndex not really match the index recorded by Session, so use Descriptor to find it.
    for (index = 0; index < m_numPipelines; index++)
    {
        if (hPipelineDescriptor == m_pipelineData[index].pPipelineDescriptor)
        {
            // found corresponding pipeline can use index to get to it
            break;
        }
    }

    CAMX_ASSERT(index < m_numPipelines);

    Pipeline* pPipeline = m_pipelineData[index].pPipeline;

    m_pStreamOnOffLock->Lock();

    if ((NULL != pPipeline) && (PipelineStatus::STREAM_ON != pPipeline->GetPipelineStatus()))
    {
        PipelineStatus pipelineStatus = pPipeline->GetPipelineStatus();

        if (PipelineStatus::FINALIZED > pipelineStatus)
        {
            result = FinalizeDeferPipeline(index);
            pipelineStatus = pPipeline->GetPipelineStatus();
            CAMX_LOG_INFO(CamxLogGroupCore, "FinalizeDeferPipeline result: %d pipelineStatus: %d",
                result, pipelineStatus);
        }

        if (CamxResultSuccess != result)
        {
            CAMX_LOG_ERROR(CamxLogGroupCore, "FinalizeDeferPipeline() unsuccessful, Session StreamOn() is failed !!");
            pPipeline->ReleaseResources();
        }
        else
        {
            if (PipelineStatus::FINALIZED <= pipelineStatus)
            {
                result = pPipeline->StreamOn();

                if (CamxResultSuccess == result)
                {
                    if (TRUE == pPipeline->IsRealTime())
                    {
                        m_numStreamedOnRealtimePipelines++;

                        CheckAndSyncLinks();
                    }
                }
                else
                {
                    CAMX_LOG_ERROR(CamxLogGroupCore, "Pipeline %s failed to stream on.",
                        pPipeline->GetPipelineName());
                }
            }
        }
    }

    m_pStreamOnOffLock->Unlock();
    return result;
}

11.camxchi.cpp–>SubmitRequest

12.camxchi.cpp–>ChiSubmitPipelineRequest

static CDKResult ChiSubmitPipelineRequest(
    CHIHANDLE           hChiContext,
    CHIPIPELINEREQUEST* pRequest)
{
    CDKResult   result      = CDKResultSuccess;
    ChiContext* pChiContext = GetChiContext(hChiContext);
    CHISession* pChiSession = GetChiSession(pRequest->pSessionHandle);

    if ((NULL == pChiContext) || (NULL == pChiSession))
    {
        CAMX_LOG_ERROR(CamxLogGroupChi, "Invalid Argument - ChiContext: %p ChiSession: %p", pChiContext, pChiSession);

        result = CDKResultEInvalidArg;
    }

    if (CDKResultSuccess == result)
    {
        result = pChiContext->SubmitRequest(pChiSession, pRequest);

        if (CDKResultSuccess != result)
        {
            CAMX_LOG_ERROR(CamxLogGroupChi, "Submit request failed with error %d.", result);
        }
    }

    return result;
}

13.camxchicontext.cpp–>SubmitRequest

文件路径:vendor\qcom\proprietary\camx\src\core\chi\camxchicontext.cpp

CamxResult ChiContext::SubmitRequest(
    CHISession*         pSession,
    ChiPipelineRequest* pRequest)
{
    CamxResult result = CamxResultSuccess;

    // Validate requests
    for (UINT i = 0; i < pRequest->numRequests; i++)
    {
        if (0 != pRequest->pCaptureRequests[i].hPipelineHandle)
        {
            result = pSession->CheckValidInputRequest(&pRequest->pCaptureRequests[i]);

            if (CamxResultSuccess == result)
            {
                // Fall back to non optimized stream on before PCR logic if 0 or for non real time pipelines
                if ((FALSE == pSession->IsPipelineRealTime(pRequest->pCaptureRequests[i].hPipelineHandle)))
                {
                    result = pSession->StreamOn(pRequest->pCaptureRequests[i].hPipelineHandle);
                }
            }
            else
            {
                CAMX_ASSERT_ALWAYS_MESSAGE("Request batch index %u is not valid.", i);
                break;
            }
        }
    }

    // Submit requests to session.
    // For multi-camera, batch of requests for different pipeline are sent to session together.
    if (CamxResultSuccess == result)
    {
        result = pSession->ProcessCaptureRequest(pRequest);
        if (CamxResultSuccess != result)
        {
            CAMX_LOG_ERROR(CamxLogGroupChi, "Request %llu failed when submitting requests.",
                pRequest->pCaptureRequests[0].frameNumber);
        }
    }

    return result;
}

14.camxchicontext.cpp–>ProcessCaptureRequest

 result = pSession->ProcessCaptureRequest(pRequest);

15.camxpipeline.cpp–>ProcessRequest

m_pRequestQueue–>EnqueueWait(&m_captureRequest)将capturerequest请求入列,然后执行一个jobHandler线程,在另外一个线程中执行m_pRequestQueue–>Dequeue()

CamxResult Pipeline::ProcessRequest(
    PipelineProcessRequestData* pPipelineRequestData)
{
    CAMX_ASSERT(NULL != pPipelineRequestData);
    CAMX_ASSERT(NULL != pPipelineRequestData->pCaptureRequest);
    CAMX_ASSERT(NULL != pPipelineRequestData->pPerBatchedFrameInfo);

    CAMX_ENTRYEXIT_SCOPE_ID(CamxLogGroupCore,
                            SCOPEEventTopologyProcessRequest,
                            pPipelineRequestData->pCaptureRequest->requestId);

    CamxResult      result                    = CamxResultSuccess;
    CaptureRequest* pCaptureRequest           = pPipelineRequestData->pCaptureRequest;
    UINT            currentActiveStreamIdMask = 0;
    UINT64          requestId                 = pCaptureRequest->requestId;
    UINT            perRequestIdIndex         = (requestId % MaxPerRequestInfo);

    // Must have recieved all fences created back and freed their node in the LDLL
    CAMX_ASSERT(0 == m_perRequestInfo[perRequestIdIndex].fences.NumNodes());
    UINT32* pSequenceId = m_perRequestInfo[perRequestIdIndex].pSequenceId;
    Utils::Memset(pSequenceId, 0, sizeof(UINT32) * GetBatchedHALOutputNum());

    CAMX_ASSERT(GetBatchedHALOutputNum() >= pCaptureRequest->GetBatchedHALOutputNum(pCaptureRequest));

    m_perRequestInfo[perRequestIdIndex].pSequenceId = pSequenceId;
    m_perRequestInfo[perRequestIdIndex].aMetadataReady = 0;
    m_perRequestInfo[perRequestIdIndex].isSofDispatched = FALSE;
    m_perRequestInfo[perRequestIdIndex].numNodesRequestIdDone = 0;
    m_perRequestInfo[perRequestIdIndex].numNodesMetadataDone = 0;
    m_perRequestInfo[perRequestIdIndex].numNodesPartialMetadataDone = 0;
    m_perRequestInfo[perRequestIdIndex].numNodesConfigDone = 0;
    m_perRequestInfo[perRequestIdIndex].batchFrameIntervalNanoSeconds = 0;
    m_perRequestInfo[perRequestIdIndex].bufferDone = 0;
    m_perRequestInfo[perRequestIdIndex].fences.FreeAllNodesAndTheirClientData();
    m_perRequestInfo[perRequestIdIndex].isSlowdownPresent = FALSE;

    CAMX_ASSERT(m_perRequestInfo[perRequestIdIndex].request.pStreamBuffers ==
        &m_pStreamBufferBlob[perRequestIdIndex * GetBatchedHALOutputNum()]);

    result = CaptureRequest::PartialDeepCopy(&m_perRequestInfo[perRequestIdIndex].request, pCaptureRequest);

    UINT*                pCurrentActiveStreams = NULL;
    BOOL                 differentStreams      = FALSE;
    PerBatchedFrameInfo* pPerBatchedFrameInfo  = NULL;

    if (CamxResultSuccess == result)
    {
        for (UINT batchIndex = 0; batchIndex < pCaptureRequest->GetBatchedHALOutputNum(pCaptureRequest); batchIndex++)
        {
            // Create mapping between request id and framework frame number.
            m_perRequestInfo[perRequestIdIndex].pSequenceId[batchIndex] =
                pPipelineRequestData->pPerBatchedFrameInfo[batchIndex].sequenceId;

            CAMX_LOG_VERBOSE(CamxLogGroupCore,
                             "%s In perRequestInfo[%d], map request id %lld with sequence id %d",
                             GetPipelineIdentifierString(),
                             perRequestIdIndex,
                             requestId,
                             pPipelineRequestData->pPerBatchedFrameInfo[batchIndex].sequenceId);
        }

        /// @note It is assumed the first batchInfo will have all the streams that can possibly be enabled in other batches
        pPerBatchedFrameInfo = &pPipelineRequestData->pPerBatchedFrameInfo[0];
#if ASSERTS_ENABLED
        /// Validate assumption that the first batchInfo will have all the streams that can possibly be enabled
        for (UINT batchIndex = 1; batchIndex < pCaptureRequest->GetBatchedHALOutputNum(pCaptureRequest); batchIndex++)
        {
            if ((pPerBatchedFrameInfo[batchIndex].activeStreamIdMask | pPerBatchedFrameInfo[0].activeStreamIdMask) !=
                pPerBatchedFrameInfo[0].activeStreamIdMask)
            {
                CAMX_ASSERT_ALWAYS_MESSAGE("Pipeline-ERROR: First batch index does not have all the streams possible");
            }
        }
#endif // ASSERTS_ENABLED

        currentActiveStreamIdMask = pPerBatchedFrameInfo->activeStreamIdMask;
        differentStreams          = FALSE;

        if (m_lastRequestActiveStreamIdMask != currentActiveStreamIdMask)
        {
            differentStreams = TRUE;
            m_lastRequestActiveStreamIdMask = currentActiveStreamIdMask;
        }
        pCurrentActiveStreams = &currentActiveStreamIdMask;

        if (TRUE == m_pChiContext->GetHwContext()->GetImageSensorModuleData(m_cameraId)->IsExternalSensor())
        {
            PublishSensorModeInformation(pCaptureRequest->requestId);
        }

        // Init debug/tuning data buffer
        if (TRUE == HAL3MetadataUtil::IsDebugDataEnable())
        {
            InitializeDebugDataBuffer(requestId);
        }

        // Use this table to find the correct request ID from CSL sync ID when CSL callback comes
        m_pCSLSyncIDToRequestId[pCaptureRequest->CSLSyncID % (MaxPerRequestInfo * GetBatchedHALOutputNum())] =
            pCaptureRequest->requestId;

        if (FALSE == IsRealTime())
        {
            UINT64        requestIdInner = pCaptureRequest->requestId;
            MetadataSlot* pInputSlot     = m_pInputPool->GetSlot(requestIdInner);
            MetadataSlot* pMainSlot      = m_pMainPool->GetSlot(requestIdInner);
            UINT32        tag            = SensorTimestamp;

            if (NULL != pInputSlot)
            {
                UINT64* pTimestamp = static_cast<UINT64*>(pInputSlot->GetMetadataByTag(tag));

                if (NULL != pTimestamp)
                {
                    pMainSlot->SetMetadataByTag(tag, pTimestamp, 1, GetPipelineIdentifierString());
                }
                else
                {
                    UINT64 timeStamp = 0;
                    pMainSlot->SetMetadataByTag(tag, &timeStamp, 1, GetPipelineIdentifierString());
                    CAMX_LOG_WARN(CamxLogGroupCore, "Timestamp tag found! %p", pTimestamp);
                }

                pMainSlot->PublishMetadataList(&tag, 1);

                SendOfflineShutterNotification(requestIdInner, pTimestamp);
            }
            else
            {
                CAMX_LOG_ERROR(CamxLogGroupCore, "Pipeline::%s Metadata slots not found input %p main %p",
                               GetPipelineIdentifierString(), pInputSlot, pMainSlot);
            }
        }

        // Publish vendor tag to indicate if request has video buffer or not
        PublishRequestHasVideoBufferTag(pPipelineRequestData);
    }
    else
    {
        CAMX_LOG_ERROR(CamxLogGroupCore, "PartialDeepCopy() failed perRequestIdIndex=%u", perRequestIdIndex);
    }

    m_lastSubmittedRequestId = CamX::Utils::MaxUINT64(pCaptureRequest->requestId, m_lastSubmittedRequestId);
    CAMX_LOG_VERBOSE(CamxLogGroupCore, "Pipeline::%s last submitted request updated to %llu",
                    GetPipelineIdentifierString(), m_lastSubmittedRequestId);

    // Check if node recources acquired before process request, Acquire node recources if not yet acquired
    // This can happen in early PCR usecase
    if (CamxResultSuccess == result)
    {
        result = CallNodeAcquireResources();
        if (CamxResultSuccess != result)
        {
            CAMX_LOG_ERROR(CamxLogGroupCore, "Pipeline::%s Acquire resources failed",
                    GetPipelineIdentifierString());
        }
    }

    // For PCRs with input buffer(s), shall we assume that the HAL have successfully waited on (all) the input
    // acquire fence(s) before forwarding such a request to the topology? If YES, the topology need not wait on
    // any fences on the SourceBuffer nodes. If NO, then the fence will have to be waited on.

    // Since CSLCreateNativeFence is not implemented, it is expected that a CSLFence is created and passed on
    // with each Input Buffer of an Offline/Reprocess PCR

    if (CamxResultSuccess == result)
    {
        CAMX_ASSERT_MESSAGE(32 >= m_nodeCount, "Using a 32 bit bitmask to track node enable, and there are too many nodes");

        // If this is too costly, try to check for flush within the loop and partially setup requests.
        UINT32 nodesEnabled = 0;

        for (UINT nodeIndex = 0; nodeIndex  < m_nodeCount; nodeIndex++)
        {
            m_ppNodes[nodeIndex]->InvalidateRequest();
        }

        for (UINT nodeIndex = 0; nodeIndex < m_orderedNodeCount; nodeIndex++)
        {
            BOOL isNodeEnabled = FALSE;

            m_ppOrderedNodes[nodeIndex]->SetupRequest(pPerBatchedFrameInfo,
                                                pCurrentActiveStreams,
                                                differentStreams,
                                                requestId,
                                                pCaptureRequest->CSLSyncID,
                                                &isNodeEnabled);

            if (TRUE == isNodeEnabled)
            {
                nodesEnabled = Utils::BitSet(nodesEnabled, nodeIndex);
            }
            else
            {
                CAMX_LOG_DRQ("Failed to setup Node %s for Pipeline %u RequestId %llu Session %p",
                        m_ppOrderedNodes[nodeIndex]->NodeIdentifierString(),
                        m_pipelineIndex, requestId, m_pSession);
            }
        }

        // Queueing the nodes is deferred to ensure all nodes have completed setup before any are invoked, which could happen
        // in the event of a previous request kicking the queue
        UINT32 nodesSentToDRQ = 0;
        for (UINT nodeIndex = 0; nodeIndex  < m_orderedNodeCount ; nodeIndex++)
        {
            if (TRUE == Utils::IsBitSet(nodesEnabled, nodeIndex))
            {
                if (FALSE == GetFlushStatus())
                {
                    CAMX_LOG_DRQ("Queueing Node: %s on pipeline: %d for new requestId: %llu",
                            m_ppOrderedNodes[nodeIndex]->NodeIdentifierString(),
                            m_pipelineIndex, requestId);

                    result = m_pDeferredRequestQueue->AddDeferredNode(requestId,
                            m_ppOrderedNodes[nodeIndex], NULL);

                    if (CamxResultSuccess == result)
                    {
                        nodesSentToDRQ = Utils::BitSet(nodesSentToDRQ, nodeIndex);
                    }
                }
                else
                {
                    CAMX_LOG_DRQ("Skipping Node: %s on pipeline: %d for new requestId: %llu as Session %p in Flush state",
                            m_ppOrderedNodes[nodeIndex]->NodeIdentifierString(),
                            m_pipelineIndex, requestId, m_pSession);
                    m_ppOrderedNodes[nodeIndex]->Flush(requestId);
                }
            }
        }

        if (0 != nodesSentToDRQ)
        {

            // Consider any nodes now ready
            m_pDeferredRequestQueue->DispatchReadyNodes();

        }

        // If no nodes got setup, a flush was called right before the setup, no nodes were sent to DRQ. Notify the session.
        if (0 == nodesEnabled)
        {
            CAMX_LOG_ERROR(CamxLogGroupCore, "Returning Cancelled. Equal to flush");
            result = CamxResultECancelledRequest;
        }
    }

    if (CamxResultSuccess != result)
    {
        // If the request is cancelled/flushed, the next request stream setup should happen again.
        CAMX_LOG_ERROR(CamxLogGroupCore, "Cancelling request. Reset the streamMask. res = %d", result);
        m_lastRequestActiveStreamIdMask = 0;
    }
    if ((TRUE == GetFlushStatus()) && (result == CamxResultECancelledRequest))
    {
        CAMX_LOG_CONFIG(CamxLogGroupCore,
            "Flush status is set for %s with cancel request, trigger request error for reqid %d",
                       GetPipelineIdentifierString(), requestId);
        TriggerRequestError(requestId);
    }

    return result;
}

16.camxnode.cpp–>SetupRequest

CamxResult Node::SetupRequest(
    PerBatchedFrameInfo* pPerBatchedFrameInfo,
    UINT*                pCurrentActiveStreams,
    BOOL                 differentStreams,
    UINT64               requestId,
    UINT64               syncId,
    BOOL*                pIsNodeEnabled)
{
    CAMX_ASSERT(NULL != pIsNodeEnabled);
    CAMX_ASSERT(NULL != pPerBatchedFrameInfo);

    BOOL                   needPortsSetupUpdate = FALSE;
    UINT                   requestIdIndex       = requestId % MaxRequestQueueDepth;
    PerRequestActivePorts* pRequestPorts        = &m_perRequestInfo[requestIdIndex].activePorts;

    m_tRequestId = requestId;

    CamxResult result = CamxResultSuccess;

    m_perRequestInfo[requestIdIndex].numUnsignaledFences      = 0;
    m_perRequestInfo[requestIdIndex].numUnprocessedFences     = 0;
    m_perRequestInfo[requestIdIndex].requestId                = requestId;
    m_perRequestInfo[requestIdIndex].partialMetadataComplete  = 0;
    m_perRequestInfo[requestIdIndex].metadataComplete         = 0;
    m_perRequestInfo[requestIdIndex].requestComplete          = 0;
    m_perRequestInfo[requestIdIndex].partialPublishedSet.clear();

    memset(m_perRequestInfo[requestIdIndex].nodeProcessingStages, 0,
        sizeof(m_perRequestInfo[requestIdIndex].nodeProcessingStages));

    PerRequestOutputPortInfo* pPort = m_perRequestInfo[requestIdIndex].activePorts.pOutputPorts;

    for (UINT portidx = 0; portidx < m_outputPortsData.numPorts; portidx++)
    {
        pPort[portidx].numPerReqInputPortsDisabled = 0;
    }

    SetRequestStatus(requestId, PerRequestNodeStatus::Setup);

    // Set the CSL sync ID for this request ID
    SetCSLSyncId(requestId, syncId);

    if (NULL != pCurrentActiveStreams)
    {
        if (FALSE == IsRealTime())
        {
            // update node ports status if overriden by node due to limitations
            needPortsSetupUpdate = IsPortStatusUpdatedByOverride();

            // update node parameters which depends on status of ports

            // This vitual function currently used by IPE node only to update number of passes.
            // When node is dynamically enabled/disabled, there is corner case where m_numPasses do not set back for currently
            // enabled Ports.
            // Suppose for a request, offiline pipeline's node is disabled, and it disables all the ports in
            // DisablePerRequestOutputPortLink().
            // Once the node is enabled for a request, IsPortStatusUpdatedByOverride() updates m_inputPortDisableMask based
            // on current active ports. Accordingly m_numPasses should be updated to correct value based on final
            // m_inputPortDisableMask.
            // Below API makes a call in IPE node and update the m_numPasses correctly.

            UpdateNodeParamsOnPortStatus();
        }

        // Has the active streams or port status changed since the last request
        if ((TRUE == differentStreams) || (TRUE == needPortsSetupUpdate))
        {
            CAMX_LOG_INFO(CamxLogGroupCore, "Setup Active streams afresh");
            NewActiveStreamsSetup(*pCurrentActiveStreams);
        }
    }

    // The new set of streams for the current request may have disabled the node. For e.g. if this is a Node with
    // one sink port and that sink port is not active for the current request then the entire node is disabled

    if (TRUE == IsNodeEnabled())
    {
        result = SetupRequestOutputPorts(pPerBatchedFrameInfo);
        result = SetupRequestInputPorts(pPerBatchedFrameInfo);
        *pIsNodeEnabled = TRUE;
    }
    else
    {
        UINT        tag     = GetNodeCompleteProperty();
        const UINT  one     = 1;
        const VOID* pOne[1] = { &one };
        WriteDataList(&tag, pOne, &one, 1);

        SetRequestStatus(requestId, PerRequestNodeStatus::Running);
        ProcessPartialMetadataDone(m_tRequestId);
        ProcessMetadataDone(m_tRequestId);
        ProcessRequestIdDone(m_tRequestId);
        DisablePerRequestOutputPortLink(m_tRequestId);
        *pIsNodeEnabled = FALSE;
    }

    return result;
}

17.camxpipeline.cpp–>AddDeferredNode

mark当前的camxnode和requestId,将两者绑定在一起

   result = m_pDeferredRequestQueue->AddDeferredNode(requestId,
                            m_ppOrderedNodes[nodeIndex], NULL);

18.camxdeferredreqeustqueue.cpp–>DispatchReadyNodes

vendor\qcom\proprietary\camx\src\core\camxdeferredrequestqueue.cpp

VOID DeferredRequestQueue::DispatchReadyNodes()
{
    CAMX_TRACE_SYNC_BEGIN_F(CamxLogGroupCore, "DeferredRequestQueue::DispatchReadyNodes");

    // If preempt dependency enabled and dependency registered for preemption,
    // clear node dependency in deferred list first.
    if (TRUE == m_preemptDependency.isPreemptDependencyEnabled)
    {
        m_pDeferredQueueLock->Lock();
        LightweightDoublyLinkedListNode* pDeferred = m_deferredNodes.Head();
        while (NULL != pDeferred)
        {
            Dependency* pDependency = static_cast<Dependency*>(pDeferred->pData);
            if ((NULL != pDependency)  &&
                (((TRUE == pDependency->preemptable) &&
                (FALSE == pDependency->isInternalDependency) &&
                (FALSE == m_preemptDependency.pipelineDepenency)) ||
                ((TRUE == m_preemptDependency.pipelineDepenency) &&
                (m_preemptDependency.pipelineIndex == pDependency->pNode->GetPipelineId()))))
            {
                CAMX_LOG_DRQ("Remove dependencies for Node: %s, request: %llu, seqID %d",
                                pDependency->pNode->NodeIdentifierString(),
                                pDependency->requestId,
                                pDependency->processSequenceId);

                RemoveAllDependencies(pDependency);
            }

            if (NULL != (m_deferredNodes.FindByValue(pDependency)))
            {
                pDeferred = LightweightDoublyLinkedList::NextNode(pDeferred);
            }
            else
            {
                // pDeferred is removed from deferred list to ready list
                pDeferred = NULL;
            }
        }
        m_pDeferredQueueLock->Unlock();
    }

    while (0 < m_readyNodes.NumNodes())
    {
        LightweightDoublyLinkedListNode* pReady      = NULL;
        Dependency*                      pDependency = NULL;

        m_pReadyQueueLock->Lock();
        if (0 < m_readyNodes.NumNodes())
        {
            pReady      = m_readyNodes.Head();
            pDependency = static_cast<Dependency*>(pReady->pData);
            m_readyNodes.RemoveNode(pReady);
        }
        m_pReadyQueueLock->Unlock();

        // Dispatch and remove all completed subscribers from the deferred node subscription list
        if (NULL != pReady)
        {
            CAMX_FREE(pReady);
            CAMX_ASSERT(NULL != pDependency);

            if (NULL != pDependency)
            {
                if (NULL != pDependency->pChiFenceCallback)
                {
                    pDependency->pChiFenceCallback(pDependency->pChiFences[0]->hChiFence, pDependency->pUserData);
                }

                UINT64 id = reinterpret_cast<UINT64>(pDependency);
                CAMX_TRACE_ASYNC_END_F(CamxLogGroupDRQ, id, "Deferred Node %s", pDependency->pNode->NodeIdentifierString());

                CAMX_LOG_DRQ("Posting job for Node %s, request %llu seqID %d",
                                 pDependency->pNode->NodeIdentifierString(),
                                 pDependency->requestId,
                                 pDependency->processSequenceId);
                // Fire the deferred node processing
                VOID* pData[] = {pDependency, NULL};
                CamxResult result = m_pThreadManager->PostJob(m_hDeferredWorker, NULL, &pData[0], FALSE, FALSE);

                if (CamxResultSuccess != result)
                {
                    if (NULL != pDependency)
                    {
                        CAMX_LOG_ERROR(CamxLogGroupCore, "Failed to post ProcessRequest job for Node %s, request %llu seqID %d",
                                    pDependency->pNode->NodeIdentifierString(),
                                    pDependency->requestId, pDependency->processSequenceId);
                    }
                }

            }
            else
            {
                // No data for the entry to exist to track
                CAMX_LOG_ERROR(CamxLogGroupDRQ, "No dependencies");
            }
        }
    }

    CAMX_TRACE_SYNC_END(CamxLogGroupCore);
}

19.camxdeferredreqeustqueue.cpp–>DeferredWorkWrapper

m_pThreadManager–>PostJob(m_hDeferredWorker,…),其中m_hDeferredWorker注册的执行回调是DeferredWorkerWrapper函数

20.camxdeferredreqeustqueue.cpp–>DeferredWorkerCore

CamxResult DeferredRequestQueue::DeferredWorkerCore(
    Dependency* pDependency)
{
    CAMX_ASSERT(pDependency->pNode != NULL);

    CamxResult             result         = CamxResultSuccess;
    NodeProcessRequestData processRequest = { 0 };
    Node*                  pNode          = pDependency->pNode;

    processRequest.processSequenceId    = pDependency->processSequenceId;
    processRequest.bindIOBuffers        = pDependency->bindIOBuffers;
    processRequest.isSequenceIdInternal = pDependency->isInternalDependency;

    if (NULL != pNode)
    {
        CAMX_LOG_DRQ("DRQ dispatching node=%d Node::%s, request=%llu, seqId=%d, bindIOBuffers=%d",
                     pNode->Type(),
                     pNode->NodeIdentifierString(),
                     pDependency->requestId,
                     pDependency->processSequenceId,
                     pDependency->bindIOBuffers);

        result = pNode->ProcessRequest(&processRequest, pDependency->requestId);

        CAMX_LOG_DRQ("DRQ execute complete node=%d Node::%s, request=%llu, seqId=%d",
                     pNode->Type(),
                     pNode->NodeIdentifierString(),
                     pDependency->requestId,
                     pDependency->processSequenceId);

        if (CamxResultSuccess == result)
        {
            CAMX_ASSERT_MESSAGE(processRequest.numDependencyLists <= MaxDependencies,
                                "Number of Dependency: %d is greater Max: %d",
                                processRequest.numDependencyLists, MaxDependencies);

            for (UINT index = 0; index < processRequest.numDependencyLists; index++)
            {
                DependencyUnit* pDependencyInfo = &processRequest.dependencyInfo[index];

                // Nodes should have an actual dependency if they report a dependency count. Any that doesnt may have messed up
                // filling in the dependencies. e.g. set dependencies in index 1, expecting dependencies in index 0, but only
                // incrementing numDependencyLists by one, for which adding the deferred node would skip the actual dependencies
                // Loop below checks that nodes didnt set dependencies above the count as well
                // Disabling this assert by default as nodes are now allowed to report a dependency without setting a mask bit
                // CAMX_ASSERT_MESSAGE(TRUE == Node::HasAnyDependency(pDependencyInfo),
                //                    "Node %s reported dependency %u without actual dependency", pNode->Name(), index);

                result = AddDeferredNode(pDependency->requestId, pNode, pDependencyInfo);
            }

#if ASSERTS_ENABLED
            for (UINT index = processRequest.numDependencyLists; index < MaxDependencies; index++)
            {
                // Any dependencies set in entries outside of numDependencyLists will not be considered, will be dropped, and
                // processing expected to occurred will not
                CAMX_ASSERT(FALSE == Node::HasAnyDependency(pDependencyInfo));
            }
#endif // ASSERTS_ENABLED
        }
        else if (CamxResultECancelledRequest == result)
        {
            // returning success as request is intended to be dropped for flush call
            result = CamxResultSuccess;
        }
    }
    else
    {
        CAMX_LOG_PERF_INFO(CamxLogGroupCore, "DRQ dispatching Chi fence callback");

        // suport only one chi fence for now
        CAMX_ASSERT(1 == pDependency->chiFenceCount);

        pDependency->pChiFenceCallback(pDependency->pChiFences[0]->hChiFence, pDependency->pUserData);
    }

    // Consider any nodes ready immediately
    DispatchReadyNodes();

    return result;
}

21.camxnode.cpp–>ProcessRequest

CamxResult Node::ProcessRequest(
    NodeProcessRequestData* pNodeRequestData,
    UINT64                  requestId)
{
    CAMX_ASSERT(pNodeRequestData != NULL);

    // Saving the value of m_parallelProcessRequests in a local bool variable parallelProcessRequests in order to ensure that
    // any change in m_parallelProcessRequests does not cause the m_pProcessRequestLock mutex to be always in locked state.
    const BOOL parallelProcessRequests = m_parallelProcessRequests;

    if (FALSE == parallelProcessRequests)
    {
        m_pProcessRequestLock->Lock();
    }

    // copy the requestId after acquiring the lock to avoid synchronization issues
    m_tRequestId = requestId;

    BOOL       inErrorState         = m_pPipeline->RequestInErrorState(requestId);
    CamxResult result               = CamxResultEFailed;
    UINT       requestIdIndex       = requestId % MaxRequestQueueDepth;
    INT32      processSequenceId    = pNodeRequestData->processSequenceId;
    BOOL       bindIOBuffers        = pNodeRequestData->bindIOBuffers;
    BOOL       isSequenceIdInternal = pNodeRequestData->isSequenceIdInternal;
    UINT32     pipelineId           = GetPipelineId();

    pNodeRequestData->pCaptureRequest = m_pPipeline->GetRequest(requestId);

    CAMX_TRACE_SYNC_BEGIN_F(CamxLogGroupCore,
                            "Node::%s ProcessRequest %llu Sequence %d bindIOBuffers %d",
                            NodeIdentifierString(),
                            requestId,
                            pNodeRequestData->processSequenceId,
                            pNodeRequestData->bindIOBuffers);
    CAMX_LOG_DRQ("Node::%s ProcessRequest %llu", NodeIdentifierString(), m_tRequestId);

    // Initially, set dependency pipeline id to own one
    for (UINT32 i = 0; i < MaxDependencies; i++)
    {
        for (UINT32 j = 0; j < MaxProperties; j++)
        {
            pNodeRequestData->dependencyInfo[i].propertyDependency.pipelineIds[j] = pipelineId;
        }
    }

    PerRequestActivePorts*    pRequestPorts      = &m_perRequestInfo[requestIdIndex].activePorts;
    ExecuteProcessRequestData executeProcessData = { 0 };

    executeProcessData.pNodeProcessRequestData   = pNodeRequestData;
    executeProcessData.pEnabledPortsInfo         = pRequestPorts;

    result = FillTuningModeData(reinterpret_cast<VOID**>(&executeProcessData.pTuningModeData));
    CAMX_ASSERT(CamxResultSuccess == result);

    if (0 == executeProcessData.pNodeProcessRequestData->processSequenceId)
    {
        if (TRUE == NodeHasDelayedNotification())
        {
            ProcessPartialMetadataDone(requestId);
            ProcessMetadataDone(requestId);
        }

        // Set start of node processing of sequenceId 0
        SetNodeProcessingTime(m_tRequestId, executeProcessData.pNodeProcessRequestData->processSequenceId, NodeStage::Start);

        // Set buffer dependency for ports that has bypassable parent Node
        SetPendingBufferDependency(&executeProcessData);
    }
    else if (TRUE == pNodeRequestData->isSequenceIdInternal)
    {
        InternalDependencySequenceId id;
        id = static_cast<InternalDependencySequenceId>(executeProcessData.pNodeProcessRequestData->processSequenceId);
        switch (id)
        {
            case ResolveDeferredInputBuffers:
                // Update image buffer info for the port waiting on buffer dependency
                UpdateBufferInfoforPendingInputPorts(pRequestPorts);
                break;
            default:
                CAMX_LOG_ERROR(CamxLogGroupCore, "%s Unknown internal request sequence id: %d, reqid %llu",
                               NodeIdentifierString(), id, requestId);
                result = CamxResultEInvalidState;
                break;
        }

        if ((TRUE == CanDRQPreemptOnStopRecording()) && (TRUE == IsEndoOfStreamEnabled()))
        {
            // Check if current request has end of stream flag set for preempable node,
            // If so set processSequenceId = -1.
            CAMX_LOG_VERBOSE(CamxLogGroupCore, "Is end of stream enabled %d, reqid end of stream enabled on %llu",
                               IsEndoOfStreamEnabled(), GetEndoOfStreamRequestId());
            pNodeRequestData->processSequenceId = -1;
        }
        else
        {
            // Reset sequenceId to 0 so derived node will not see base Node sequenceIds
            pNodeRequestData->processSequenceId = 0;
        }
    }

    BOOL hasInternalDependency = (TRUE == (pNodeRequestData->numDependencyLists > 0)) &&
                                 (TRUE == pNodeRequestData->dependencyInfo[0].dependencyFlags.isInternalDependency);

    if (TRUE == hasInternalDependency)
    {
        CAMX_LOG_VERBOSE(CamxLogGroupCore,
                         "%s has internal dependency for request: %llu. Bypassing EPR until dependency is met.",
                         NodeIdentifierString(),
                         requestId);
    }
    else
    {
        if (TRUE == m_pPipeline->GetFlushStatus())
        {
            result = CamxResultECancelledRequest;
        }

        if ((CamxResultSuccess == result) && (FALSE == inErrorState))
        {
            if (TRUE == executeProcessData.pNodeProcessRequestData->bindIOBuffers)
            {
                // If LateBinding is enabled, input and output ImageBuffers may not have backing buffers yet.
                // If derived nodes set needBuffersOnDependencyMet for this sequenceId, that means, derived
                // node is going to access input, output buffers now. Lets bind buffers to ImageBuffers if not yet.
                result = BindInputOutputBuffers(executeProcessData.pEnabledPortsInfo, TRUE, TRUE);
                if (CamxResultSuccess != result)
                {
                    CAMX_LOG_ERROR(CamxLogGroupCore,
                                   "Node::%s Req[%llu] processSequenceId[%d] Failed in Binding backing buffers "
                                   "to input, output ImageBuffers, result=%s",
                                   NodeIdentifierString(),
                                   requestId, executeProcessData.pNodeProcessRequestData->processSequenceId,
                                   Utils::CamxResultToString(result));
                }
            }

            if (CamxResultSuccess == result)
            {
                SetNodeProcessingTime(m_tRequestId, executeProcessData.pNodeProcessRequestData->processSequenceId,
                    NodeStage::DependenciesMet);

                SetRequestStatus(requestId, PerRequestNodeStatus::Running);
                result = ExecuteProcessRequest(&executeProcessData);

                SetNodeProcessingTime(m_tRequestId, executeProcessData.pNodeProcessRequestData->processSequenceId,
                    NodeStage::EPReqEnd);
            }

        }

        // Flush the request if it was cancelled or completely failed
        if ((CamxResultSuccess != result) || (TRUE == inErrorState))
        {
            CAMX_LOG_CONFIG(CamxLogGroupCore,
                          "Flush called on Node %s requestId %llu Sequence %u",
                          NodeIdentifierString(),
                          m_tRequestId,
                          pNodeRequestData->processSequenceId);

            Flush(requestId);
        }

        // Print the log message with the right level and update the request status accordingly.
        if ((CamxResultSuccess != result) || (TRUE == inErrorState))
        {
            if (CamxResultECancelledRequest == result)
            {
                CAMX_LOG_CONFIG(CamxLogGroupCore,
                              "Canceling RequestId %llu Sequence %u for Node: %s is in flush state.",
                              m_tRequestId,
                              pNodeRequestData->processSequenceId,
                              NodeIdentifierString());
                SetRequestStatus(requestId, PerRequestNodeStatus::Cancelled);
            }
            else
            {
                CAMX_LOG_ERROR(CamxLogGroupCore,
                               "An Error occured with RequestId %llu Sequence %u for Node: %s inErrorState: %d"
                               " ExecuteProcessRequest returned with %s.",
                               m_tRequestId,
                               pNodeRequestData->processSequenceId,
                               NodeIdentifierString(),
                               inErrorState,
                               Utils::CamxResultToString(result));
                SetRequestStatus(requestId, PerRequestNodeStatus::Error);
            }
        }

        if ((CamxResultSuccess == result) && (FALSE == inErrorState))
        {
            // Check if node is registered for config done, send config done notification if no dependencies
            if (0 == executeProcessData.pNodeProcessRequestData->numDependencyLists)
            {
                if (TRUE == m_nodeFlags.callNotifyConfigDone)
                {
                    m_pPipeline->NotifyNodeConfigDone(requestId);
                }
                if (FALSE == m_perRequestInfo[requestId % MaxRequestQueueDepth].requestComplete)
                {
                    SetRequestStatus(requestId, PerRequestNodeStatus::Submit);
                    CAMX_LOG_INFO(CamxLogGroupCore, "Submitted to HW: %s Id: %d", NodeIdentifierString(), requestId);
                }
            }

            for (UINT index = 0; index < executeProcessData.pNodeProcessRequestData->numDependencyLists; index++)
            {
                // Start of next sequenceId
                DependencyUnit* pDependencyInfo = &executeProcessData.pNodeProcessRequestData->dependencyInfo[index];

                SetNodeProcessingTime(m_tRequestId, pDependencyInfo->processSequenceId,
                    NodeStage::Start);
            }
        }

        if ((FALSE == m_derivedNodeHandlesMetaDone) || (CamxResultSuccess != result) || (TRUE == inErrorState))
        {
            BOOL hasDependency = FALSE;
            for (UINT index = 0; index < executeProcessData.pNodeProcessRequestData->numDependencyLists; index++)
            {
                DependencyUnit* pDependencyInfo = &executeProcessData.pNodeProcessRequestData->dependencyInfo[index];

                if (TRUE == HasAnyDependency(pDependencyInfo))
                {
                    hasDependency = TRUE;
                    break;
                }
            }

            if (FALSE == hasDependency)
            {
                ProcessPartialMetadataDone(requestId);
                ProcessMetadataDone(requestId);
            }
        }

        if ((0 == pNodeRequestData->numDependencyLists) || (CamxResultSuccess != result))
        {
            UINT        tag     = GetNodeCompleteProperty();
            const UINT  one     = 1;
            const VOID* pOne[1] = { &one };
            WriteDataList(&tag, pOne, &one, 1);
        }

        // If node is not having any partial Tags to be published then node should send
        // Notification to Pipeline
        if ((0 == m_publishTagArray.partialTagCount) ||
            (m_perRequestInfo[requestIdIndex].partialPublishedSet.size() == m_publishTagArray.partialTagCount))
        {
            CAMX_LOG_VERBOSE(CamxLogGroupCore, "partialTagCount = %d partialPublishedSet.size=%d",
                             m_publishTagArray.partialTagCount, m_perRequestInfo[requestIdIndex].partialPublishedSet.size());
            ProcessPartialMetadataDone(requestId);
        }

        // For offline/reprocess requests, as the fence for a source buffer node is external we don't have the callback
        // We need to do either of the following -
        // 1) Release the input ImageBuffer when all the output buffer fences are signaled for the source buffer node,
        //    but that may be deemed too defensive, OR
        // 2) Use a pool (large enough) for container ImageBuffers for offline requests and recycle the LRU one

        // Going for (1) now, but need to be discussed further

        CAMX_LOG_CONFIG(CamxLogGroupCore, "%s Complete ProcessRequest %llu", NodeIdentifierString(), requestId);
    }

    CAMX_TRACE_SYNC_END(CamxLogGroupCore);

    if (FALSE == parallelProcessRequests)
    {
        m_pProcessRequestLock->Unlock();
    }

    UINT nodeId         = Type();
    UINT nodeInstanceId = InstanceID();
    auto hPipeline      = m_pPipeline->GetPipelineDescriptor();
    BINARY_LOG(LogEvent::Node_ProcessRequest, hPipeline, nodeId, nodeInstanceId, requestId, inErrorState, processSequenceId,
               isSequenceIdInternal, bindIOBuffers, hasInternalDependency, result);

    return result;
}

camxchinodewrapper.cpp–>ExecuteProcessRequest

CamxResult ChiNodeWrapper::ExecuteProcessRequest(
    ExecuteProcessRequestData*   pExecuteProcessRequestData)
{}

22.camxchinodewrapper.cpp–>pProcessRequest

根据设置的nodecallbace会回调到算法node中,这里开始进入算法流程

CDKResult cdkResult = m_nodeCallbacks.pProcessRequest(&info)
  • 7
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值