第一范文网 - 专业文章范例文档资料分享平台

Android Camera HAL3中预览preview模式下的控制流

来源:用户分享 时间:2025/5/17 2:45:11 本文由loading 分享 下载这篇文档手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xxxxxxx或QQ:xxxxxx 处理(尽可能给您提供完整文档),感谢您的支持与谅解。

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);

搜索更多关于: Android Camera HAL3中预览preview模 的文档
Android Camera HAL3中预览preview模式下的控制流.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.diyifanwen.net/c56p698pcop0wekt4q3ep_3.html(转载请注明文章来源)
热门推荐
Copyright © 2012-2023 第一范文网 版权所有 免责声明 | 联系我们
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:xxxxxx 邮箱:xxxxxx@qq.com
渝ICP备2023013149号
Top