Hal3_2v6模块介绍---普通Photo模式configureStreams及processCaptureRequest流程

上篇介绍了openCamera的流程,从hal3_2v6到oem的过程。
本篇介绍下openCamera之后紧接着的动作,configureStreams 和 processCaptureRequest。

configureStreams 配流

普通Photo模式会配两路流,预览和拍照。

1,传入一个 camera3_stream_configuration_t 类型的参数
int SprdCamera3HWI::configureStreams(camera3_stream_configuration_t *streamList)
2,创建三个channel

SprdCamera3MetadataChannel:参数
SprdCamera3RegularChannel:预览
SprdCamera3PicChannel :拍照

注意:在new这三个对象的时候,第二个参数都传如了 captureResultCb

    // Create metadata channel and initialize it
    if (mMetadataChannel == NULL) {
        mMetadataChannel = new SprdCamera3MetadataChannel(
            mOEMIf, captureResultCb, mSetting, this);
        if (mMetadataChannel == NULL) {
            HAL_LOGE("failed to allocate metadata channel");
        }
    } else {
        mMetadataChannel->stop(mFrameNum);
    }

    // regular channel
    if (mRegularChan == NULL) {
        mRegularChan = new SprdCamera3RegularChannel(
            mOEMIf, captureResultCb, mSetting, mMetadataChannel,
            CAMERA_CHANNEL_TYPE_REGULAR, this);
        if (mRegularChan == NULL) {
            HAL_LOGE("channel created failed");
            return INVALID_OPERATION;
        }
    } else {
        // for performance: dont delay for dc/dv switch or front/back switch
        mOEMIf->setSensorCloseFlag();
        mRegularChan->stop(mFrameNum);
    }

    // picture channel
    if (mPicChan == NULL) {
        mPicChan = new SprdCamera3PicChannel(mOEMIf, captureResultCb, mSetting,
                                             mMetadataChannel,
                                             CAMERA_CHANNEL_TYPE_PICTURE, this);
        if (mPicChan == NULL) {
            HAL_LOGE("channel created failed");
            return INVALID_OPERATION;
        }
    } else {
        mPicChan->stop(mFrameNum);
    }

在SprdCamera3HIW中看到 captureResultCb 是:

void SprdCamera3HWI::captureResultCb(cam_result_data_info_t *result_info) {
    // Mutex::Autolock l(mLock);

    if (NULL == result_info) {
        HAL_LOGE("param invalid");
        return;
    }
    HAL_LOGD("SprdCamera3HWI");
    handleCbDataWithLock(result_info);

    return;
}

void SprdCamera3HWI::captureResultCb(cam_result_data_info_t *result_info,
                                     void *userdata) {
    SprdCamera3HWI *hw = (SprdCamera3HWI *)userdata;
    if (hw == NULL) {
        HAL_LOGE("Invalid hw %p", hw);
        return;
    }

    hw->captureResultCb(result_info);
    return;
}

即调用 handleCbDataWithLock ,我们在开启预览的流程中会看到当预览帧数据会调的时候会调用 handleCbDataWithLock

3,遍历参数的类型和格式

对我们当前普通Photo模式下有两路流:
472 944 D Cam3HWI : 719, configureStreams: stream_type=0 format=34
472 944 D Cam3HWI : 719, configureStreams: stream_type=0 format=33
stream_type都为0,即 CAMERA3_STREAM_OUTPUT = 0,
format的对应关系是:
HAL_PIXEL_FORMAT_RAW16=32,
HAL_PIXEL_FORMAT_BLOB=33, //拍照
HAL_PIXEL_FORMAT_YV12=842094169,
HAL_PIXEL_FORMAT_YCrCb_420_SP=17
HAL_PIXEL_FORMAT_YCbCr_420_888=35
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED=34 //预览

for (i = 0; i < streamList->num_streams; i++) {
	HAL_LOGD("stream_type=%d format=%d", streamList->streams[i]->stream_type, streamList->streams[i]->format);
}
4,根据上述参数的stream_type和 format 得到 : stream_type 和 channel_type

预览:
stream_type = CAMERA_STREAM_TYPE_PREVIEW;
channel_type = CAMERA_CHANNEL_TYPE_REGULAR;
拍照:
stream_type = CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT;
channel_type = CAMERA_CHANNEL_TYPE_PICTURE;

5,根据channel_type配置mStreamConfiguration

代码省略了与本篇不相关的分支

switch (channel_type) {
        case CAMERA_CHANNEL_TYPE_REGULAR: {
            ret = mRegularChan->addStream(stream_type, newStream);
            if (ret) {
                HAL_LOGE("addStream failed");
            }

            if (stream_type == CAMERA_STREAM_TYPE_PREVIEW) {
                preview_size.width = newStream->width;
                preview_size.height = newStream->height;
                previewFormat = newStream->format;
                previewStreamType = CAMERA_STREAM_TYPE_PREVIEW;
                mStreamConfiguration.preview.status = CONFIGURED;
                mStreamConfiguration.preview.width = newStream->width;
                mStreamConfiguration.preview.height = newStream->height;
                mStreamConfiguration.preview.format = newStream->format;
                mStreamConfiguration.preview.type = CAMERA_STREAM_TYPE_PREVIEW;
                mStreamConfiguration.preview.stream = newStream;
            }
        case CAMERA_CHANNEL_TYPE_PICTURE: {
            ret = mPicChan->addStream(stream_type, newStream);
            if (ret) {
                HAL_LOGE("addStream failed");
            }

            if (stream_type == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT) {
                capture_size.width = newStream->width;
                capture_size.height = newStream->height;
                captureFormat = newStream->format;
                captureStreamType = CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT;
                mStreamConfiguration.snapshot.status = CONFIGURED;
                mStreamConfiguration.snapshot.width = newStream->width;
                mStreamConfiguration.snapshot.height = newStream->height;
                mStreamConfiguration.snapshot.format = newStream->format;
                mStreamConfiguration.snapshot.type =
                    CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT;
                mStreamConfiguration.snapshot.stream = newStream;
            }

            newStream->priv = mPicChan;
            newStream->max_buffers = SprdCamera3PicChannel::kMaxBuffers;//1
            mPictureRequest = false;
            break;
        }

        default:
            HAL_LOGE("channel type is invalid channel");
            break;
        }
    }

6,将上一步得到的参数,通过SprdCamera3OEMIf继续设下去
	mOEMIf->setCamStreamInfo(preview_size, previewFormat, previewStreamType);
    mOEMIf->setCamStreamInfo(capture_size, captureFormat, captureStreamType);
    mOEMIf->setCamStreamInfo(video_size, videoFormat, videoStreamType);
    mOEMIf->setCamStreamInfo(callback_size, callbackFormat, callbackStreamType);
    mOEMIf->setCamStreamInfo(yuv2_size, yuv2Format, yuv2StreamType);

    // need to update crop region each time when ConfigureStreams
    mOEMIf->setCameraConvertCropRegion();

    mSetting->setPreviewSize(preview_size);
    mSetting->setVideoSize(video_size);
    mSetting->setPictureSize(capture_size);
    mSetting->setCallbackSize(callback_size);
7,SprdCamera3OEMIf的处理

代码去除了与本篇不相关的分支逻辑
case CAMERA_STREAM_TYPE_PREVIEW:
设置了mPreviewWidth 和 mPreviewHeight ,在后面的开启预览阶段会在使用这两个参数

case CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT:
通过 SET_PARM(mHalOem, mCameraHandle, CAMERA_PARAM_RAW_CAPTURE_SIZE, (cmr_uint)&req_size);将拍照的size进一步设下去

int SprdCamera3OEMIf::setCamStreamInfo(struct img_size size, int format,
                                       int stream_tpye) {
    int i;
    SPRD_DEF_Tag *sprddefInfo;
    char value[PROPERTY_VALUE_MAX];
    struct img_size req_size;
    struct sensor_mode_info mode_info[SENSOR_MODE_MAX];

    switch (stream_tpye) {
    case CAMERA_STREAM_TYPE_PREVIEW:
        mPreviewWidth = size.width;
        mPreviewHeight = size.height;
        if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP ||
            format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
            format == HAL_PIXEL_FORMAT_YCBCR_420_888) {
            mPreviewFormat = CAM_IMG_FMT_YUV420_NV21;
        } else if (format == HAL_PIXEL_FORMAT_RAW16) {
            mPreviewFormat = CAM_IMG_FMT_BAYER_MIPI_RAW;
        }
        break;
    case CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT:
        mCaptureWidth = size.width;
        mCaptureHeight = size.height;
        if (format == HAL_PIXEL_FORMAT_BLOB) {
            mPictureFormat = CAM_IMG_FMT_YUV420_NV21;
        }

        if (getMultiCameraMode() != MODE_TUNING) {
            if (mIsRawCapture == 1) {
                mHalOem->ops->camera_get_sensor_info_for_raw(mCameraHandle,
                                                             mode_info);
                for (i = SENSOR_MODE_PREVIEW_ONE; i < SENSOR_MODE_MAX; i++) {
                    HAL_LOGD("trim w=%d, h=%d", mode_info[i].trim_width,
                             mode_info[i].trim_height);
                    if (mode_info[i].trim_width >= mCaptureWidth) {
                        mCaptureWidth = mode_info[i].trim_width;
                        mCaptureHeight = mode_info[i].trim_height;
                        break;
                    }
                }
                req_size.width = mCaptureWidth;
                req_size.height = mCaptureHeight;
                SET_PARM(mHalOem, mCameraHandle, CAMERA_PARAM_RAW_CAPTURE_SIZE,
                         (cmr_uint)&req_size);
                HAL_LOGD(
                    "raw capture mode: mCaptureWidth=%d, mCaptureHeight=%d",
                    mCaptureWidth, mCaptureHeight);
            }
        }
        break;

    default:
        break;
    }

    return NO_ERROR;
}

configureStreams的流程到此就结束了,总的来说,就是将传入的 camera3_stream_configuration_t 类型的参数中的数据,进一步设下去

processCaptureRequest流程

请求预览和请求拍照都叫Request,并且预览的每一帧都代表一个Request。
我们以预览为例,看下processCaptureRequest的流程。

1,根据参数 camera3_capture_request_t 中的stream状态去setCapturePara
int SprdCamera3HWI::processCaptureRequest(camera3_capture_request_t *request) {

    switch (captureIntent) {
    case ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW:

        if (mStreamConfiguration.num_streams == 2 &&
            mStreamConfiguration.preview.status == CONFIGURED &&
            mStreamConfiguration.snapshot.status == CONFIGURED) {

            if (mOldCapIntent == SPRD_CONTROL_CAPTURE_INTENT_CONFIGURE) {
                {
                    // when sensor_rotation is 1 for volte, volte dont need capture
                    if ((mOEMIf->isYuvSensor() == 0) && (sprddefInfo->sensor_rotation == 0)) {
                        mOEMIf->setStreamOnWithZsl();
                    }
                    mFirstRegularRequest = 1;
                }
                mOEMIf->setCapturePara(CAMERA_CAPTURE_MODE_PREVIEW, mFrameNum);
                if (streamType[0] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT ||
                    streamType[1] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT ||
                    streamType[2] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT) {
                    mPictureRequest = 1;
                    mOEMIf->setCapturePara(CAMERA_CAPTURE_MODE_STILL_CAPTURE,
                                           mFrameNum);
                }
                break;
            }

            if (streamType[0] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT ||
                streamType[1] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT ||
                streamType[2] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT) {
                mPictureRequest = 1;
                mOEMIf->setCapturePara(CAMERA_CAPTURE_MODE_STILL_CAPTURE,
                                       mFrameNum);
            }
            break;
        }

        if (mOldCapIntent == SPRD_CONTROL_CAPTURE_INTENT_CONFIGURE) {
            if (mStreamConfiguration.snapshot.status == CONFIGURED) {
                if (mOEMIf->isYuvSensor() == 0) {
                    mOEMIf->setStreamOnWithZsl();
                }
            }
            mFirstRegularRequest = 1;
            mOEMIf->setCapturePara(CAMERA_CAPTURE_MODE_PREVIEW, mFrameNum);
            if (streamType[0] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT ||
                streamType[1] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT ||
                streamType[2] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT) {
                mPictureRequest = 1;
                mOEMIf->setCapturePara(CAMERA_CAPTURE_MODE_STILL_CAPTURE,
                                       mFrameNum);
            }
            break;
        }

        if (streamType[0] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT ||
            streamType[1] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT ||
            streamType[2] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT) {
            mPictureRequest = 1;
            mOEMIf->setCapturePara(CAMERA_CAPTURE_MODE_STILL_CAPTURE,
                                   mFrameNum);
        }
        break;

mOEMIf->setCapturePara(CAMERA_CAPTURE_MODE_PREVIEW, mFrameNum);
mOEMIf->setCapturePara(CAMERA_CAPTURE_MODE_STILL_CAPTURE, mFrameNum);
是向SprdCamera3OEMIf中设置 mTakePictureMode、mCaptureMode、mPicCaptureCnt等值的状态

2,acquireFence
for (size_t i = 0; i < request->num_output_buffers; i++) {
  	const camera3_stream_buffer_t &output = request->output_buffers[i];
    sp<Fence> acquireFence = new Fence(output.acquire_fence);

    ret = acquireFence->wait(Fence::TIMEOUT_NEVER);
    if (ret) {
        HAL_LOGE("fence wait failed %d", ret);
        goto exit;
    }

    acquireFence = NULL;
}
3,构建 pendingRequestInfo
    pendingRequest.meta_info.flash_mode = flashInfo.mode;
    pendingRequest.meta_info.ae_mode = controlInfo.ae_mode;
    memcpy(pendingRequest.meta_info.ae_regions, controlInfo.ae_regions,
           5 * sizeof(controlInfo.ae_regions[0]));
    memcpy(pendingRequest.meta_info.af_regions, controlInfo.af_regions,
           5 * sizeof(controlInfo.af_regions[0]));
    pendingRequest.frame_number = frameNumber;
    pendingRequest.threeA_info.af_trigger = controlInfo.af_trigger;
    pendingRequest.threeA_info.af_state = controlInfo.af_state;
    pendingRequest.threeA_info.ae_precap_trigger =
        controlInfo.ae_precap_trigger;
    pendingRequest.threeA_info.ae_state = controlInfo.ae_state;
    pendingRequest.threeA_info.ae_manual_trigger =
        controlInfo.ae_manual_trigger;
#ifdef SUPPORT_EXPOSURE_SENSITIVITY
    pendingRequest.threeA_info.exposure_time = streamParaInfo.exposure_time;
    pendingRequest.threeA_info.sensitivity= streamParaInfo.sensitivity;
#endif
    pendingRequest.num_buffers = request->num_output_buffers;
    pendingRequest.request_id = captureRequestId;
    pendingRequest.bNotified = 0;
    pendingRequest.input_buffer = request->input_buffer;
    pendingRequest.pipeline_depth = 0;

并将该pendingRequest : mPendingRequestsList.push_back(pendingRequest);

4,将Setting信息更新下去
mMetadataChannel->start(mFrameNum);
5,开启预览

在上面的case ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW 中会将 mFirstRegularRequest 置为 1。开启预览只在第一次调用processCaptureRequest的时候走,就将

if (mFirstRegularRequest == 1) {
        HAL_LOGD(" mRegularChan->start num_output_buffers:%d", request->num_output_buffers);
        ret = mRegularChan->start(mFrameNum);//开启预览
        if (ret) {
            HAL_LOGE("mRegularChan->start failed, ret=%d", ret);
            goto exit;
        }
        mFirstRegularRequest = 0;
    }
6,调用SprdCamera3RegularChannel 的 request,请求预览帧数据
for (i = 0; i < request->num_output_buffers; i++) {
        const camera3_stream_buffer_t &output = request->output_buffers[i];
        camera3_stream_t *stream = output.stream;
        SprdCamera3Channel *channel = (SprdCamera3Channel *)stream->priv;

        if (channel == NULL) {
            HAL_LOGE("invalid channel pointer for stream");
            continue;
        }
        HAL_LOGD(" getStreamType:%d",getStreamType(stream));
        ret = channel->request(stream, output.buffer, frameNumber);
        if (ret) {
            HAL_LOGE("channel->request failed %p (%d)", output.buffer,
                     frameNumber);
            continue;
        }
    }

ReguarChannel的request主要做两个动作
1,map buffer
2,queue buffer
在这里插入图片描述

7,触发拍照

mPictureRequest == 1 的条件是在 case ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE 中设置的1

if (mPictureRequest == 1) {
        ret = mPicChan->start(mFrameNum);
        if (ret) {
            HAL_LOGE("mPicChan->start failed, ret=%d", ret);
            goto exit;
        }
        mPictureRequest = 0;
    }

8, case ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE

    case ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE:

        if (streamType[0] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT ||
            streamType[1] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT ||
            streamType[2] == CAMERA_STREAM_TYPE_PICTURE_SNAPSHOT) {
            mPictureRequest = 1;
            mOEMIf->setCapturePara(CAMERA_CAPTURE_MODE_STILL_CAPTURE,
                                   mFrameNum);
        }
        break;
    }

processCaptureRequest的流程到这里就完成了,请求了预览帧,那就会有预览帧数据的回调。
我们在configureStreams的第二步中提到,创建三个Channel对象,都传入了 captureResultCb ,该回调会调用 handleCbDataWithLock 函数

void SprdCamera3HWI::handleCbDataWithLock(cam_result_data_info_t *result_info) {
	for (List<PendingRequestInfo>::iterator i = mPendingRequestsList.begin();
         i != mPendingRequestsList.end();) {
		
		if (i->frame_number < frame_number) {
			//比当前 frame_number 小,调用 process_capture_result
			if (!i->bNotified) {
                mCallbackOps->process_capture_result(mCallbackOps, &result);
                free_camera_metadata(const_cast<camera_metadata_t *>(result.result));
            }
			
		} else if (i->frame_number == frame_number) {
			//与当前 frame_number 相等,调用 process_capture_result
			if (!i->bNotified) {
                mCallbackOps->process_capture_result(mCallbackOps, &result);
                free_camera_metadata(const_cast<camera_metadata_t *>(result.result));
            }
           	//遍历当前 pendingRequestInfo 中的所有buffer,result.result 置为 null,然后在调用 process_capture_result
            for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
                 j != i->buffers.end();) {
                if (j->stream == stream && j->buffer == buffer) {
                    camera3_stream_buffer_t *result_buffers =
                        new camera3_stream_buffer_t[1];

                    result_buffers->stream = stream;
                    result_buffers->buffer = buffer;
                    if (mBufferStatusError || sprddefInfo ->return_previewframe_after_nozsl_cap == 1||
                        (mSuperExposeNonzsl == 1 && sprddefInfo ->return_previewframe_after_nozsl_cap == 1)) {
                        result_buffers->status = CAMERA3_BUFFER_STATUS_ERROR;
                        HAL_LOGI("bufferstatus:%d",result_buffers->status);
                    } else {
                        result_buffers->status = buffer_status;
                    }
                    result_buffers->acquire_fence = -1;
                    result_buffers->release_fence = -1;

                    result.result = NULL;
                    result.frame_number = i->frame_number;
                    result.num_output_buffers = 1;
                    result.output_buffers = result_buffers;
                    result.input_buffer = i->input_buffer;
                    result.partial_result = 0;
                    if (mMultiCameraMode == MODE_3D_VIDEO) {
                        setVideoBufferTimestamp(capture_time);
                    }
                    mCallbackOps->process_capture_result(mCallbackOps, &result);
                    HAL_LOGV("data frame_number = %d, input_buffer = %p",
                             result.frame_number, i->input_buffer);

                    delete[] result_buffers;

                    i->num_buffers--;
                    j = i->buffers.erase(j);

                    break;
                } else {
                    ++j;
                }
            }
		} else if (i->frame_number > frame_number) {
			//不做任何操作
		}    

     }
}

可见,在预览帧回调handleCbDataWithLock的时候,或判断参数 cam_result_data_info_t 中的frame_number,与在processCaptureRequest中push的pendingRequestsInfo的frame_number的关系。

  • mPendingRequestsList 中的 frame_number < cam_result_data_info_t 的 frame_number ==> process_capture_result
  • mPendingRequestsList 中的 frame_number = cam_result_data_info_t 的 frame_number ==> process_capture_result 并且遍历当前 pendingRequestsInfo 中的buffer
  • mPendingRequestsList 中的 frame_number > cam_result_data_info_t 的 frame_number ==>不处理

process_capture_result 是将当前帧数据向上回调。

到这里,我们就完整的讲了 配置、请求预览、预览数据回调的流程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值