69. 70. 71. 72. 73. 74. mNextStreamId, strerror(-res), res); return res; } internalResumeLocked(); } ALOGV(\, mId); 75. return OK; 76. } 该函数重点是关注一个new Camera3OutputStream,在Camera3Device主要存在Camera3OutputStream和Camera3InputStream
两种stream,前者主要作为HAL的输出,是请求HAL填充数据的OutPutStream,后者是由Framework将Stream进行填充。无论是Preview、record还是capture均是从HAL层获取数据,故都会以OutPutStream的形式存在,是我们关注的重点,后面在描述Preview的数据流时还会进一步的阐述。
每当创建一个OutPutStream后,相关的stream信息被push维护在一个mOutputStreams的KeyedVector >表中,分别是该stream在Camera3Device中创建时的ID以及Camera3OutputStream的sp值。同时对mNextStreamId记录下一个Stream的ID号。
上述过程完成StreamingProcessor模块中一个PreviewStream的创建,其中Camera3OutputStream创建时的ID值被返回记录作为mPreviewStreamId的值,此外每个Stream都会有一个对应的ANativeWindow,这里称之为Consumer。
(2)mCallbackProcessor->updateStream(params)
对比StreamingProcessor模块创建previewstream的过程,很容易定位到Callback模块是需要建立一个callback流,同样需要创建一个Camera3OutputStream来接收HAL返回的每一帧帧数据,是否需要callback可以通过callbackenable来控制。一般但预览阶段可能不需要回调每一帧的数据到APP,但涉及到相应的其他业务如视频处理时,就需要进行callback的enable。
[cpp] view plaincopy
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. status_t CallbackProcessor::updateStream(const Parameters ?ms) { ATRACE_CALL(); status_t res; Mutex::Autolock l(mInputMutex); sp device = mDevice.promote(); if (device == 0) { ALOGE(\, __FUNCTION__, mId); return INVALID_OPERATION; } // 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 sp producer; sp consumer; 30. BufferQueue::createBufferQueue(&producer, &consumer);//BufferQueueProducer与BufferQueueConsumer 31. mCallbackConsumer = new CpuConsumer(consumer, kCallbackHeapCount); 32. mCallbackConsumer->setFrameAvailableListener(this);//当前CallbackProcessor继承于CpuConsumer::FrameAvailableListener 33. mCallbackConsumer->setName(String8(\)); 34. mCallbackWindow = new Surface(producer);//用于queue操作,这里直接进行本地的buffer操作 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. } if (mCallbackStreamId != NO_STREAM) { // Check if stream parameters have to change uint32_t currentWidth, currentHeight, currentFormat; res = device->getStreamInfo(mCallbackStreamId, ¤tWidth, ¤tHeight, ¤tFormat); if (res != OK) { ALOGE(\ \, __FUNCTION__, mId, strerror(-res), res); return res; } if (currentWidth != (uint32_t)params.previewWidth || currentHeight != (uint32_t)params.previewHeight || currentFormat != (uint32_t)callbackFormat) { // Since size should only change while preview is not running, // assuming that all existing use of old callback stream is // completed. ALOGV(\ \, __FUNCTION__, mId, mCallbackStreamId); res = device->deleteStream(mCallbackStreamId); if (res != OK) { ALOGE(\ \, __FUNCTION__, mId, strerror(-res), res); return res; } mCallbackStreamId = NO_STREAM; } } if (mCallbackStreamId == NO_STREAM) { ALOGV(\, params.previewWidth, params.previewHeight, callbackFormat, params.previewFormat); res = device->createStream(mCallbackWindow, params.previewWidth, params.previewHeight, callbackFormat, &mCallbackStreamId);//Creating callback stream if (res != OK) { ALOGE(\ \, __FUNCTION__, mId, strerror(-res), res); return res; } } return OK; } 对比updatePreviewStream可以发现,该函数自助创建了一套surface/BufferQueue/CpuConsumer的机制,这套类似SurfaceFlinger的buffer管理机制可参看一文Android5.1中surface生产者和消费者间的处理框架简述。此外通过
createStream请求Camera3Device建立一个Stream,其中Stream的ID值保存在mCallBackStreamId当中,并将一个CallbackWindow和当前的Stream绑定。
通过这个对比,也需要重点关注到,对于每个Camera3OutPutStream来说,每一个stream都被一个Consumer,而在此处都是Surface(ANativeWindow)所拥有,这个Consumer和HAL相匹配来说是消费者,但对于真正的处理Buffer的Consumer来说如CPUConsumer,Surface却又是以一个Product的角色存在的。
(3)updateProcessorStream(mJpegProcessor, params)
[cpp] view plaincopy
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 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模块处理一致,创建的一个OutPutStream和CaptureWindow相互绑定,同时Stream的ID保存在mCaptureStreamId中。 此外需要说明一点:
在preview模式下,就去创建一个jpeg处理的stream,目的在于启动takepicture时,可以更快的进行capture操作。是通过牺牲内存空间来提升效率。
(4)整合startPreviewL中所有的stream 到Vector outputStreams
outputStreams.push(getPreviewStreamId());//预览stream outputStreams.push(getCallbackStreamId())//Callback stream 目前一次Preview构建的stream数目至少为两个。
(5)mStreamingProcessor->updatePreviewRequest()
在创建好多路stream后,由StreamingProcessor模块来将所有的stream信息交由Camera3Device去打包成Request请求。 注意:
Camera HAL2/3的特点是:将所有stream的请求都转化为几个典型的Request请求,而这些Request需要由HAL去解析,进而处理所需的业务。这也是Camera3数据处理复杂化的原因所在。
[cpp] view plaincopy
1. 2. 3. 4. 5. 6. 7. 8. status_t StreamingProcessor::updatePreviewRequest(const Parameters ?ms) { ATRACE_CALL(); status_t res; sp device = mDevice.promote(); if (device == 0) { ALOGE(\, __FUNCTION__, mId); return INVALID_OPERATION; } 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. Mutex::Autolock m(mMutex); if (mPreviewRequest.entryCount() == 0) { sp client = mClient.promote(); if (client == 0) { ALOGE(\, __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 { res = device->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW, &mPreviewRequest);//创建一个Preview相关的request,由底层的hal来完成default创建 } if (res != OK) { ALOGE(\ \, __FUNCTION__, mId, strerror(-res), res); return res; } } res = params.updateRequest(&mPreviewRequest);//根据参数来更新CameraMetadata request 40. if (res != OK) { 41. ALOGE(\ 42. \, __FUNCTION__, mId, 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. strerror(-res), res); return res; } res = mPreviewRequest.update(ANDROID_REQUEST_ID, &mPreviewRequestId, 1);//mPreviewRequest的ANDROID_REQUEST_ID if (res != OK) { ALOGE(\, __FUNCTION__, mId, strerror(-res), res); return res; } return OK; } 该函数的处理过程是一个构建并初始化mPreviewRequest的过程,分以下几个流程来分析: a mPreviewRequest是一个CameraMetadata类型数据,用于封装当前previewRequest。
b device->createDefaultRequest(CAMERA3_TEMPLATE_PREVIEW, &mPreviewRequest)
[cpp] view plaincopy
1. 2. 3. 4. const camera_metadata_t *rawRequest; ATRACE_BEGIN(\); rawRequest = mHal3Device->ops->construct_default_request_settings( mHal3Device, templateId);