加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

2.5、高通camera框架:初理解之三_HAL3.0简介_整理

(2016-01-20 17:15:35)
标签:

it

linux

分类: Android之Camera开发
HAL3.0  Frameworks层总体框架

v3将更多的工作集中在了Framework去完成,将更多的控制权掌握在自己的手里,从而与HAL的交互的数据信息更少,也进一步减轻了一些在旧版本中HAL层所需要做的事情,也更加模块化。

下面以initialize为起点进行分析:

Camera2Client后会进行initialize操作,完成各个处理模块的创建:

 

代码目录:frameworks/av/services/camera/libcameraservice/api1/Camera2Client.cpp

status_t Camera2Client::initialize(CameraModule *module)

{

    ………

    mStreamingProcessor = new StreamingProcessor(this);//previewrecorder

    threadName = String8::format(C2-%d-StreamProc, mCameraId);

    mStreamingProcessor->run(threadName.string());//预览与录像

 

    mFrameProcessor = new FrameProcessor(mDevice, this);// 3A

    threadName = String8::format(C2-%d-FrameProc, mCameraId);

    mFrameProcessor->run(threadName.string()); //3A

 

    mCaptureSequencer = new CaptureSequencer(this);

    threadName = String8::format(C2-%d-CaptureSeq, mCameraId);

    mCaptureSequencer->run(threadName.string());//录像,拍照

 

    mJpegProcessor = new JpegProcessor(this, mCaptureSequencer);

    threadName = String8::format(C2-%d-JpegProc, mCameraId);

    mJpegProcessor->run(threadName.string());

………

    mCallbackProcessor = new CallbackProcessor(this);//回调处理

    threadName = String8::format(C2-%d-CallbkProc, mCameraId);

    mCallbackProcessor->run(threadName.string());

    ………

}

依次分别创建了:

1StreamingProcessor并启动一个它所属的thread,该模块主要负责处理previewsrecord两种视频流的处理,用于从hal层获取原始的视频数据

2FrameProcessor并启动一个thread,该模块专门用于处理回调回来的每一帧的3A等信息,即每一帧视频除去原始视频数据外,还应该有其他附加的数据信息,如3A值。

3CaptureSequencer并启动一个thread,该模块需要和其他模块配合使用,主要用于向APP层告知capture到的picture

4JpegProcessor并启动一个thread,该模块和streamprocessor类似,他启动一个拍照流,一般用于从HAL层获取jpeg编码后的图像照片数据。

5另外ZslProcessor模块称之为0秒快拍,其本质是直接从原始的Preview流中获取预存着的最近的几帧,直接编码后返回给APP,而不 需要再经过take picture去请求获取jpeg数据。0秒快拍技术得意于当下处理器CSI2 MIPI性能的提升以及Sensor支持全像素高帧率的实时输出。一般手机拍照在按下快门后都会有一定的延时,是因为需要切换底层Camera以及ISP 等的工作模式,并重新设置参数以及重新对焦等等,都需要花一定时间后才抓取一帧用于编码为jpeg图像。

以上5个模块整合在一起基本上实现了Camera应用开发所需的基本业务功能。

2.3.2 Preview模式下的控制流

代码目录,直接以Camera2Client::startPreview()作为入口来分析整个Framework层中Preview相关的数据流

   1、调用Camera2Client::startPreview函数

代码目录-1frameworks/av/services/camera/libcameraservice/api1/Camera2Client.cpp

status_t Camera2Client::startPreview() {

    ATRACE_CALL();

    ALOGV(%s: E, __FUNCTION__);

    Mutex::Autolock icl(mBinderSerializationLock);

    status_t res;

    if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

    SharedParameters::Lock l(mParameters);

    return startPreviewL(l.mParameters, false);

}

startPreview通过startPreviewL提取参数后真正的开始执行Preview相关的控制流。该函数看上去内容虽然较多,但基本采用了同一种处理方式:

2、    调用Camera2Client::startPreviewL函数

代码目录-1frameworks/av/services/camera/libcameraservice/api1/Camera2Client.cpp

后面会详细介绍2.1-2.6粗体标注部分;

status_t Camera2Client::startPreviewL(Parameters &params, bool restart){

......

//获取上一层Preview stream id

int lastPreviewStreamId = mStreamingProcessor->getPreviewStreamId();

//2.1创建camera3device streamCamera3OutputStream

    res = mStreamingProcessor->updatePreviewStream(params);

.....

int lastJpegStreamId = mJpegProcessor->getStreamId();

//2.2预览启动时就建立一个jpegoutstream

res = updateProcessorStream(mJpegProcessor, params);

.....

//2.3回调处理建立一个Camera3outputstream

res = mCallbackProcessor->updateStream(params);

………

//2.4

outputStreams.push(getCallbackStreamId());

......

outputStreams.push(getPreviewStreamId());//预览stream

......

if (!params.recordingHint) {

   if (!restart) {

      //2.5 request处理,更新了mPreviewrequest

      res = mStreamingProcessor->updatePreviewRequest(params); 

......

    }

        //2.6

        res = mStreamingProcessor->startStream(StreamingProcessor::PREVIEW,

                outputStreams);//启动stream,传入outputStreamsstreamid

    }

......

}

2.1、调用mStreamingProcessor->updatePreviewStream函数

   代码目录-2

    frameworks/av/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp

status_t StreamingProcessor::updatePreviewStream (const Parameters &params) {

......

    sp device = mDevice.promote();//Camera3Device

......

    if (mPreviewStreamId != NO_STREAM) {

        // Check if stream parameters have to change

        uint32_t currentWidth, currentHeight;

        res = device->getStreamInfo(mPreviewStreamId,

                &tWidth, &tHeight, 0);

    ......

        if (currentWidth != (uint32_t)params.previewWidth ||

                currentHeight != (uint32_t)params.previewHeight) {

        ......    

            res = device->waitUntilDrained();

        ......   

            res = device->deleteStream(mPreviewStreamId);

            ......

            mPreviewStreamId = NO_STREAM;

        }

    }

if (mPreviewStreamId == NO_STREAM) {//首次create stream

        //创建一个Camera3OutputStream

        res = device->createStream(mPreviewWindow,

                params.previewWidth, params.previewHeight,

                CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, &mPreviewStreamId);

        ......

        }

    }

    res = device->setStreamTransform(mPreviewStreamId,

            params.previewTransform);

    ......

}

该函数首先是查看当前StreamingProcessor模块下是否存在Stream,没有的话,则交由Camera3Device创建一个 stream。显然,一个StreamingProcessor只能拥有一个PreviewStream,而一个Camera3Device显然控制着所 有的Stream

注意:在Camera2Client中,5大模块的数据交互均以stream作为基础。

下面我们来重点关注Camera3Device的接口createStream,他是5个模块创建stream的基础:

      代码目录-3

       frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

status_t Camera3Device::createStream(sp consumer,

        uint32_t width, uint32_t height, int format, int *id) {

    ......

    assert(mStatus != STATUS_ACTIVE);

    sp newStream;

    if (format == HAL_PIXEL_FORMAT_BLOB) {//图片

        ssize_t jpegBufferSize = getJpegBufferSize(width, height);

       ......

        newStream = new Camera3OutputStream(mNextStreamId, consumer,

                width, height, jpegBufferSize, format);//jpeg 缓存的大小

    } else {

        newStream = new Camera3OutputStream(mNextStreamId, consumer,

                width, height, format);//Camera3OutputStream

    }

newStream->setStatusTracker(mStatusTracker);

//一个streamidCamera3OutputStream绑定

    res = mOutputStreams.add(mNextStreamId, newStream);

    ......

    *id = mNextStreamId++;//至少一个previewstream 一般还有CallbackStream

    mNeedConfig = true;

    // Continue captures if active at start

    if (wasActive) {

        ALOGV(%s: Restarting activity to reconfigure streams, __FUNCTION__);

        res = configureStreamsLocked();

       ......

        internalResumeLocked();

    }

    ALOGV(Camera %d: Created new stream, mId);

    return OK;

}

该函数重点是关注一个new Camera3OutputStream,在Camera3Device主要存在Camera3OutputStreamCamera3InputStream,两种stream,前者主要作为HAL的输出,是请求HAL填充数据的OutPutStream,后者是由FrameworkStream进行填充。无论是Previewrecord还是capture均是从HAL层获取数据,故都会以OutPutStream的形式存在,是我们关注的重点,后面在描述Preview的数据流时还会进一步的阐述。

每当创建一个OutPutStream后,相关的stream信息被push维护在一个mOutputStreamsKeyedVector表中,分别是该streamCamera3Device中创建时的ID以及Camera3OutputStreamsp值。同时对mNextStreamId记录下一个StreamID号。

上述过程完成StreamingProcessor模块中一个PreviewStream的创建,其中Camera3OutputStream创建时的ID值被返回记录作为mPreviewStreamId的值,此外每个Stream都会有一个对应的ANativeWindow,这里称之为Consumer

2.2、调用updateProcessorStream(mJpegProcessor, params)函数

    代码目录-2

    frameworks/av/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp

       status_t Camera2Client::updateProcessorStream(sp processor,

                                              camera2::Parameters params) {

            // No default template arguments until C++11, so we need this overload

             return updateProcessorStream(

                processor, params);

}

template

status_t Camera2Client::updateProcessorStream(sp processor,

                                              Parameters params) {

            status_t res;

            // Get raw pointer since sp doesn't have operator->*

            ProcessorT *processorPtr = processor.get();

            res = (processorPtr->*updateStreamF)(params);

.......

}

该模板函数处理过程最终通过非显示实例到显示实例调用JpegProcessor::updateStream,该函数处理的逻辑基本和Callback 模块处理一致,创建的一个OutPutStreamCaptureWindow相互绑定,同时StreamID保存在 mCaptureStreamId中。

此外需要说明一点:

preview模式下,就去创建一个jpeg处理的stream,目的在于启动takepicture时,可以更快的进行capture操作,是通过牺牲内存空间来提升效率。

2.3、调用mCallbackProcessor->updateStream函数

代码目录-2

    frameworks/av/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp

对比StreamingProcessor模块创建previewstream的过程,很容易定位到Callback模块是需要建立一个 callback流,同样需要创建一个Camera3OutputStream来接收HAL返回的每一帧帧数据,是否需要callback可以通过 callbackenable来控制。一般但预览阶段可能不需要回调每一帧的数据到APP,但涉及到相应的其他业务如视频处理时,就需要进行 callbackenable

status_t CallbackProcessor::updateStream(const Parameters &params) {

    ………

    sp device = mDevice.promote();

    ………

    // If possible, use the flexible YUV format

    int32_t callbackFormat = params.previewFormat;

    if (mCallbackToApp) {

        // TODO: etalvala: This should use the flexible YUV format as well, but

        // need to reconcile HAL2/HAL3 requirements.

        callbackFormat = HAL_PIXEL_FORMAT_YV12;

    } else if(params.fastInfo.useFlexibleYuv &&

            (params.previewFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP ||

             params.previewFormat == HAL_PIXEL_FORMAT_YV12) ) {

        callbackFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;

    }

    if (!mCallbackToApp && mCallbackConsumer == 0) {

        // Create CPU buffer queue endpoint, since app hasn't given us one

        // Make it async to avoid disconnect deadlocks

        spproducer;

        spconsumer;

       //BufferQueueProducerBufferQueueConsumer

        BufferQueue::createBufferQueue(&producer, &consumer);

        mCallbackConsumer = new CpuConsumer(consumer, kCallbackHeapCount);

//当前CallbackProcessor继承于CpuConsumer::FrameAvailableListener

        mCallbackConsumer->setFrameAvailableListener(this);

        mCallbackConsumer->setName(String8(Camera2Client::CallbackConsumer));

//用于queue操作,这里直接进行本地的buffer操作

        mCallbackWindow = new Surface(producer);

    }

    if (mCallbackStreamId != NO_STREAM) {

        // Check if stream parameters have to change

        uint32_t currentWidth, currentHeight, currentFormat;

        res = device->getStreamInfo(mCallbackStreamId,

                &tWidth, &tHeight, &tFormat);

       ………

    }

    if (mCallbackStreamId == NO_STREAM) {

        ALOGV(Creating callback stream: %d x %d, format 0x%x, API format 0x%x,

                params.previewWidth, params.previewHeight,

                callbackFormat, params.previewFormat);

        res = device->createStream(mCallbackWindow,

                params.previewWidth, params.previewHeight,

                callbackFormat, &mCallbackStreamId);//Creating callback stream

        ………

    }

    return OK;

}

2.4、整合startPreviewL中所有的streamVector outputStreams

outputStreams.push(getPreviewStreamId());//预览stream

outputStreams.push(getCallbackStreamId())//Callback stream

目前一次Preview构建的stream数目至少为两个。

2.5、调用mStreamingProcessor->updatePreviewRequest函数

代码目录-2

    frameworks/av/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp

在创建好多路stream后,由StreamingProcessor模块来将所有的stream信息交由Camera3Device去打包成Request请求。

注意:

Camera HAL2/3的特点是:将所有stream的请求都转化为几个典型的Request请求,而这些Request需要由HAL去解析,进而处理所需的业务,这也是Camera3数据处理复杂化的原因所在。

status_t StreamingProcessor::updatePreviewRequest(const Parameters &params) {

    ………

    if (mPreviewRequest.entryCount() == 0) {

        sp client = mClient.promote();

        if (client == 0) {

            ALOGE(%s: Camera %d: Client does not exist, __FUNCTION__, mId);

            return INVALID_OPERATION;

        }

        // Use CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG for ZSL streaming case.

        if (client->getCameraDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_0) {

            if (params.zslMode && !params.recordingHint) {

                res = device->createDefaultRequest(CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG,

                        &mPreviewRequest);

            } else {

                res = device->createDefaultRequest(CAMERA3_TEMPLATE_PREVIEW,

                        &mPreviewRequest);

            }

        } else {

          //创建一个Preview相关的request,由底层的hal来完成default创建

            res = device->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,

                    &mPreviewRequest);

        ………

}

//根据参数来更新CameraMetadata request,用于app设置参数,如antibanding设置

res = params.updateRequest(&mPreviewRequest);  

    ………

    res = mPreviewRequest.update(ANDROID_REQUEST_ID,

            &mPreviewRequestId, 1);//mPreviewRequestANDROID_REQUEST_ID

    ………

}

a mPreviewRequest是一个CameraMetadata类型数据,用于封装当前previewRequest;

b 调用device->createDefaultRequest(CAMERA3_TEMPLATE_PREVIEW, &mPreviewRequest)函数

代码目录-3

frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

status_t Camera3Device::createDefaultRequest(int templateId, CameraMetadata *request) {

    ………

const camera_metadata_t *rawRequest;

 ATRACE_BEGIN(camera3->construct_default_request_settings);

 rawRequest = mHal3Device->ops->construct_default_request_settings(

     mHal3Device, templateId);

 ATRACE_END();

 if (rawRequest == NULL) {

     SET_ERR_L(HAL is unable to construct default settings for template %d,

             templateId);

     return DEAD_OBJECT;

 }

 *request = rawRequest;

 mRequestTemplateCache[templateId] = rawRequest;

………

}

最终是由hal来实现构建一个rawrequest,即对于Preview,而言是构建了一个CAMERA3_TEMPLATE_PREVIEW类型的 Request。其实对HAL而言,rawrequest本质是用于操作一个camera_metadata_t类型的数据:

struct camera_metadata {

    metadata_size_t          size;

    uint32_t                 version;

    uint32_t                 flags;

    metadata_size_t          entry_count;

    metadata_size_t          entry_capacity;

    metadata_uptrdiff_t      entries_start; // Offset from camera_metadata

    metadata_size_t          data_count;

    metadata_size_t          data_capacity;

    metadata_uptrdiff_t      data_start; // Offset from camera_metadata

    uint8_t                  reserved[];

};

该数据结构可以存储多种数据,且可以根据entry tag的不同类型来存储数据,同时数据量的大小也可以自动调整;

c mPreviewRequest.update(ANDROID_REQUEST_ID,&mPreviewRequestId, 1)

将当前的PreviewRequest相应的ID保存到camera metadata

2.6、调用mStreamingProcessor->startStream函数启动整个预览的stream

代码目录-2

  frameworks/av/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp

该函数的处理过程较为复杂,可以说是整个Preview正常工作的核心控制:

tatus_t StreamingProcessor::startStream(StreamType type,

        const Vector&outputStreams) {

.....

CameraMetadata &request = (type == PREVIEW) ?

            mPreviewRequest : mRecordingRequest;//previewCameraMetadata request

//CameraMetadata中添加outputStreams

res = request.update(ANDROID_REQUEST_OUTPUT_STREAMS, outputStreams);

res = device->setStreamingRequest(request);//hal发送request

.....

}

该函数首先是根据当前工作模式来确定StreamingProcessor需要处理的Request,该模块负责PreviewRecord两个Request

PreviewRequest就是之前createDefaultRequest构建的,这里先是将这个Request所需要操作的Outputstream打包到一个tagANDROID_REQUEST_OUTPUT_STREAMSentry当中。

      a 调用setStreamingRequest函数

      代码目录:

       frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

真正的请求Camera3Device去处理这个带有多路streamPreviewRequest

a.1 status_t Camera3Device::setStreamingRequest(const CameraMetadata &request,

                                            int64_t* ) {

    ATRACE_CALL();

    List requests;

    requests.push_back(request);

    return setStreamingRequestList(requests, NULL);

}

该函数将mPreviewRequest push到一个list,调用setStreamingRequestList

a.2 status_t Camera3Device::setStreamingRequestList(const List &requests, int64_t *lastFrameNumber) {

        ATRACE_CALL();

        return submitRequestsHelper(requests, true, lastFrameNumber);

}

a.3 status_t Camera3Device::submitRequestsHelper(

        const List &requests, bool repeating,

       

        int64_t *lastFrameNumber) {//repeating = 1;lastFrameNumber = NULL

    ………

    status_t res = checkStatusOkToCaptureLocked();

    ………

    RequestList requestList;

//返回的是CaptureRequest RequestList

res = convertMetadataListToRequestListLocked(requests, &requestList);   

………

    if (repeating) {

//重复的request存入到RequestThread

res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber); 

else {

//capture模式,拍照单词

        res = mRequestThread->queueRequestList(requestList,lastFrameNumber);  

 }

    if (res == OK) {

        waitUntilStateThenRelock(true, kActiveTimeout);

        if (res != OK) {

            SET_ERR_L(Can't transition to active in %f seconds!,

                    kActiveTimeout/1e9);

        }

        ALOGV(Camera %d: Capture request % PRId32  enqueued, mId,

              (*(requestList.begin()))->mResultExtras.requestId);

    } else {

        CLOGE(Cannot queue request. Impossible.);

        return BAD_VALUE;

    }

    return res;

}

a.4 convertMetadataListToRequestListLocked

这个函数是需要将Requestlist中保存的CameraMetadata数据转换为List

status_t Camera3Device::convertMetadataListToRequestListLocked(

const List &metadataList, RequestList *requestList) {

    ………

    for (List::const_iterator it = metadataList.begin();//CameraMetadata, mPreviewRequest

            it != metadataList.end(); ++it) {

        //新建CaptureRequestCameraMetadata转化而来

        sp<<b>capturerequest> newRequest = setUpRequestLocked(*it);       

        ………

        // Setup burst Id and request Id

        newRequest->mResultExtras.burstId = burstId++;

        if (it->exists(ANDROID_REQUEST_ID)) {

            if (it->find(ANDROID_REQUEST_ID).count == 0) {

                CLOGE(RequestID entry exists; but must not be empty in metadata);

                return BAD_VALUE;

            }

        //设置该request对应的id

        newRequest->mResultExtras.requestId = it->find(ANDROID_REQUEST_ID).data.i32[0];

        } else {

            CLOGE(RequestID does not exist in metadata);

            return BAD_VALUE;

        }

        requestList->push_back(newRequest);

        ………

    }

    return OK;

}

这里是对List进行迭代解析处理,如当前模式下仅存在PreviewRequest这一个CameraMetadata,通过setUpRequestLocked将其转换为一个CaptureRequest

         a.5 setUpRequestLocked

           spCamera3Device::setUpRequestLocked(

                const CameraMetadata &request) {//mPreviewRequest

                status_t res;

                if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {

                res = configureStreamsLocked();

                ......

    //CameraMetadata转为CaptureRequest,包含mOutputStreams

    sp newRequest = createCaptureRequest(request);

                return newRequest;

}

configureStreamsLocked函数主要是将Camera3Device侧建立的所有Stream包括OutputInPut格式 的交由HAL3层的Device去实现处理的核心接口是configure_streamsregister_stream_buffer

createCaptureRequest函数是将一个CameraMetadata格式的数据如PreviewRequest转换为一个CaptureRequest

           a.6 spCamera3Device::createCaptureRequest(

                const CameraMetadata &request) {//mPreviewRequest

                ………

                spnewRequest = new CaptureRequest;

                newRequest->mSettings = request;//CameraMetadata

                camera_metadata_entry_t inputStreams =

                    newRequest->mSettings.find(ANDROID_REQUEST_INPUT_STREAMS);

                if (inputStreams.count > 0) {

                    if (mInputStream == NULL ||

                        mInputStream->getId() != inputStreams.data.i32[0]) {

                        CLOGE(Request references unknown input stream %d,

                        inputStreams.data.u8[0]);

                        return NULL;

                    }

                ………

                    newRequest->mInputStream = mInputStream;

                    newRequest->mSettings.erase(ANDROID_REQUEST_INPUT_STREAMS);

                }

//读取存储在CameraMetadatastream id信息

                camera_metadata_entry_t streams =

                    newRequest->mSettings.find(ANDROID_REQUEST_OUTPUT_STREAMS);

                    ………

for (size_t i = 0; i < streams.count; i++) {

                    //Camera3OutputStreamidmOutputStreams

                    int idx = mOutputStreams.indexOfKey(streams.data.i32[i]);

                    ………

                 }

                //返回的是Camera3OutputStreampreview/callbackstream

                spstream =

                     mOutputStreams.editValueAt(idx);

                ………

//Camera3OutputStream添加到CaptureRequestmOutputStreams

                newRequest->mOutputStreams.push(stream);

    }

                newRequest->mSettings.erase(ANDROID_REQUEST_OUTPUT_STREAMS);

                return newRequest;

}

该函数主要处理指定的这个CameraMetadata mPreviewRequest下对应所拥有的OutputInput Stream,对于Preview而言,至少存在OutPutStream包括一路StreamProcessor与一路可选的 CallbackProcessor

在构建这个PreviewRequest时,已经将ANDROID_REQUEST_OUTPUT_STREAMS这个Tag进行了初始化,相应的内容为Vector &outputStreams,包含着属于PreviewRequest这个Request所需要的输出streamID值,通过这个ID index值,可以遍历到Camera3Device下所createstream创造的Camera3OutputStream,即说明不同类型的 RequestCamera3Device端存在多个Stream,而每次不同业务下所需要Request的对应的Stream又仅是其中的个别而已。

idx = mOutputStreams.indexOfKey(streams.data.i32[i])是通过属于PreviewRequest中包含的一个 streamID值来查找到mOutputStreams这个KeyedVector中对应的标定值index。注意:两个索引值不一定是一致的。

mOutputStreams.editValueAt(idx)是获取一个与该ID(Previewstream IDCallback Stream ID等等)相对应的Camera3OutputStream

在找到了当前Request中所有的Camera3OutputStream后,将其维护在CaptureRequest:

class CaptureRequest : public LightRefBase {

      public:

        CameraMetadata                      mSettings;

        sp          mInputStream;

        Vector >

                                            mOutputStreams;

        CaptureResultExtras                 mResultExtras;

    };

mSettings是保存CameraMetadata PreviewRequestvector mOutPutStreams保存着当前Request提取出来的Camera3OutputStream,至此构建了一个CaptureRequest

           回到a.4convertMetadataListToRequestListLocked

返回到convertMetadataListToRequestListLocked中,现在已经完成了一个CameraMetadata Request的处理,生产的是一个CaptureRequest。我们将这个ANDROID_REQUEST_IDID值,保留在newRequest->mResultExtras.requestId = it->find(ANDROID_REQUEST_ID).data.i32[0]

这个值在整个Camera3的架构中,仅存在3大种Request类型,说明了整个和HAL层交互的Request类型是不多的:

预览Request mPreviewRequestmPreviewRequestId(Camera2Client::kPreviewRequestIdStart),

拍照Request mCaptureRequestmCaptureId(Camera2Client::kCaptureRequestIdStart),

录像Request mRecordingRequestmRecordingRequestId(Camera2Client::kRecordingRequestIdStart)

static const int32_t kPreviewRequestIdStart = 10000000;

static const int32_t kPreviewRequestIdEnd   = 20000000;

static const int32_t kRecordingRequestIdStart  = 20000000;

static const int32_t kRecordingRequestIdEnd    = 30000000;

static const int32_t kCaptureRequestIdStart = 30000000;

static const int32_t kCaptureRequestIdEnd   = 40000000;

           回到a.3mRequestThread->setRepeatingRequests(requestList)

对于Preview来说,一次Preview后底层硬件就该可以连续的工作,而不需要进行过多的切换,故Framework每次向HAL发送的Request均是一种repeat的操作模式,故调用了一个重复的RequestQueue来循环处理每次的Request

status_t Camera3Device::RequestThread::setRepeatingRequests(

        const RequestList &requests,

       

        int64_t *lastFrameNumber) {

    Mutex::Autolock l(mRequestLock);

    if (lastFrameNumber != NULL) {//第一次进来为null

        *lastFrameNumber = mRepeatingLastFrameNumber;

    }

    mRepeatingRequests.clear();

    mRepeatingRequests.insert(mRepeatingRequests.begin(),

            requests.begin(), requests.end());

    unpauseForNewRequests();//signal request_thread in waitfornextrequest

    mRepeatingLastFrameNumber = NO_IN_FLIGHT_REPEATING_FRAMES;

    return OK;

}

Preview线程提交的Request加入到mRepeatingRequests中后,唤醒RequestThread线程去处理当前新的Request

2.7、经过2.6步骤将开启RequestThread 请求处理线程

RequestThread::threadLoop()函数主要用于响应并处理新加入到Request队列中的请求。

代码目录-2

frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

bool Camera3Device::RequestThread::threadLoop() {

....

//返回的是mRepeatingRequestsmPreviewRequest

 sp nextRequest = waitForNextRequest();  

………

    // Create request to HAL

//CaptureRequest转为给HAL3.0camera3_capture_request_t

camera3_capture_request_t request = camera3_capture_request_t();    request.frame_number = nextRequest->mResultExtras.frameNumber;//当前帧号

    VectoroutputBuffers;

    // Get the request ID, if any

    int requestId;

    camera_metadata_entry_t requestIdEntry =

            nextRequest->mSettings.find(ANDROID_REQUEST_ID);

    if (requestIdEntry.count > 0) {

//获取requestid,这里是mPreviewRequestid

        requestId = requestIdEntry.data.i32[0];

    }

         .....

   for (size_t i = 0; i < nextRequest->mOutputStreams.size(); i++) {

         res = nextRequest->mOutputStreams.editItemAt(i)->

                 getBuffer(&outputBuffers.editItemAt(i));

.....

    // Submit request and block until ready for next one

    ATRACE_ASYNC_BEGIN(frame capture, request.frame_number);

    ATRACE_BEGIN(camera3->process_capture_request);

   //调用底层halprocess_capture_request,如antibanding参数设置

res = mHal3Device->ops->process_capture_request(mHal3Device, &request);    ATRACE_END();

     .......

}

a.1 waitForNextRequest()

    Camera3Device::RequestThread::waitForNextRequest() {

   ………

    while (mRequestQueue.empty()) {

        if (!mRepeatingRequests.empty()) {

            // Always atomically enqueue all requests in a repeating request

            // list. Guarantees a complete in-sequence set of captures to

            // application.

            const RequestList &requests = mRepeatingRequests;

            RequestList::const_iterator firstRequest =

                    requests.begin();

            nextRequest = *firstRequest;

            //把当前的mRepeatingRequests插入到mRequestQueue

            mRequestQueue.insert(mRequestQueue.end(),

                    ++firstRequest,

                    requests.end());

            // No need to wait any longer

            mRepeatingLastFrameNumber = mFrameNumber + requests.size() - 1;

            break;

        }

        //等待下一个request

        res = mRequestSignal.waitRelative(mRequestLock, kRequestTimeout);

        if ((mRequestQueue.empty() && mRepeatingRequests.empty()) ||

                exitPending()) {

            Mutex::Autolock pl(mPauseLock);

            if (mPaused == false) {

                ALOGV(%s: RequestThread: Going idle, __FUNCTION__);

                mPaused = true;

                // Let the tracker know

                spstatusTracker = mStatusTracker.promote();

                if (statusTracker != 0) {

                    statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);

                }

            }

            // Stop waiting for now and let thread management happen

            return NULL;

        }

    }

    if (nextRequest == NULL) {

        // Don't have a repeating request already in hand, so queue

        // must have an entry now.

        RequestList::iterator firstRequest =

                mRequestQueue.begin();

        nextRequest = *firstRequest;

//取一根mRequestQueue中的CaptureRequest,来自于mRepeatingRequestsnext

        mRequestQueue.erase(firstRequest);

    }

    ………

    if (nextRequest != NULL) {

        //对每一个非空的request需要帧号++

nextRequest->mResultExtras.frameNumber = mFrameNumber++       nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId;

        nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId;

    }

    return nextRequest;

}

该函数是响应RequestList的核心,通过不断的轮训休眠等待一旦mRepeatingRequestsRequest可处理时,就将他内部所有 的CaptureRequest加入到mRequestQueue 中去,理论来说每一个CaptureRequest对应着一帧的请求处理,每次响应时可能会出现mRequestQueue包含了多个 CaptureRequest

通过nextRequest->mResultExtras.frameNumber = mFrameNumber++表示当前CaptureRequest在处理的一帧图像号。

对于mRepeatingRequests而言,只有其非空,在执行完一次queue操作后,在循环进入执行时,会自动对 mRequestQueue进行erase操作,是的mRequestQueue变为empty后再次重新加载mRepeatingRequests中的 内容,从而形成一个队repeatRequest的重复响应过程。

a.2

camera_metadata_entry_t requestIdEntry = nextRequest->mSettings.find(ANDROID_REQUEST_ID);提取该CaptureRequest对应的 Request 类型值;

a.3 getBuffer操作

a.4 mHal3Device->ops->process_capture_request(mHal3Device, &request)

这里的request是已经由一个CaptureRequest转换为和HAL3.0交互的camera3_capture_request_t结构。

3、    总结

 

至此已经完成了一次向HAL3.0 Device发送一次完整的Request的请求。从最初Preview启动建立多个OutPutStream,再是将这些Stream打包成一个 mPreviewRequest来启动stream,随后将这个Request又转变为一个CaptureRequest,直到转为Capture list后交由RequestThread来处理这些请求。每一次的Request简单可以说是Camera3DeviceHAL3.0请求一帧数据, 当然每一次Request也可以包含各种控制操作,如AutoFocus等内容。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有