当前位置:   article > 正文

Android 8.0系统源码分析--Camera processCaptureResult结果回传源码分析_camera result metadata

camera result metadata

     相机,从上到下概览一下,真是太大了,上面的APP->Framework->CameraServer->CameraHAL,HAL进程中Pipeline、接各种算法的Node、再往下的ISP、3A、Driver,真是太大了,想把它搞懂真不是个简单的事情。不过我们奔着要把它搞懂的目标,一点点的啃,弄懂一点少一点,我们的功力也在不断的前进中一步步的增强。

     本节,我们就来看一下HAL层一帧处理完成,通过HIDL定义的接口processCaptureResult将数据回传的逻辑。我自己使用的Android8.0的系统源码是通过百度云盘分享的,大家可从Android 8.0系统源码分析--开篇中下载,百度云盘的下载链接和密码都有。

     Camera系统也提供了非常多的dump方式,可以dump metadata、dump buffer,对我们分析问题都有非常大的帮助。

     1、MTK系统中camera sensor的信息会通过kernal中imagesensor.c中的逻辑将所有camera sensor info写入到proc/driver/camera_info文件中,我们可以直接cat proc/driver/camera_info查看camera sensor的详细信息,其中记录了sensor类型,比如IMX386_mipi_raw;记录了sensor支持的分辨率大小,还有一些其他原始信息;

     2、我们可以执行adb shell dumpsys media.camera > camerainfo.txt收集camera metadata信息,大家可以试一下,从这里可以轻易得到很多camera metadata信息;

     3、android-8.0.0\system\media\camera\docs\docs.html文件中定义了AOSP所有的metadata,我们可以直接双击用浏览器打开它,就可以看到所有metadata,当然,每个SOC厂商肯定会自己新增一些,一般metadata的命名都是下划线拼接的,比如android.scaler.cropRegion,它的命名为ANDROID_SCALER_CROP_REGION,我们在HAL进程中就可以通过它去查询当前cropRegion的值。

     4、Google提供的基于Camera API2 Demo地址:android-Camera2Basic(普通的预览拍照功能)、android-Camera2Video(录像功能)。

     HIDL接口的定义有ICameraDevice.hal、ICameraDeviceSession.hal、ICameraDeviceCallback.hal,文件目录在hardware\interfaces\camera\device\xx目录下,xx为版本号,我所下载的源码有1.0和3.2两个版本,我们来看一下3.2版本下ICameraDeviceCallback.hal的定义,源码如下:

  1. package android.hardware.camera.device@3.2;
  2. import android.hardware.camera.common@1.0::types;
  3. /**
  4. *
  5. * Callback methods for the HAL to call into the framework.
  6. *
  7. * These methods are used to return metadata and image buffers for a completed
  8. * or failed captures, and to notify the framework of asynchronous events such
  9. * as errors.
  10. *
  11. * The framework must not call back into the HAL from within these callbacks,
  12. * and these calls must not block for extended periods.
  13. *
  14. */
  15. interface ICameraDeviceCallback {
  16. /**
  17. * processCaptureResult:
  18. *
  19. * Send results from one or more completed or partially completed captures
  20. * to the framework.
  21. * processCaptureResult() may be invoked multiple times by the HAL in
  22. * response to a single capture request. This allows, for example, the
  23. * metadata and low-resolution buffers to be returned in one call, and
  24. * post-processed JPEG buffers in a later call, once it is available. Each
  25. * call must include the frame number of the request it is returning
  26. * metadata or buffers for. Only one call to processCaptureResult
  27. * may be made at a time by the HAL although the calls may come from
  28. * different threads in the HAL.
  29. *
  30. * A component (buffer or metadata) of the complete result may only be
  31. * included in one process_capture_result call. A buffer for each stream,
  32. * and the result metadata, must be returned by the HAL for each request in
  33. * one of the processCaptureResult calls, even in case of errors producing
  34. * some of the output. A call to processCaptureResult() with neither
  35. * output buffers or result metadata is not allowed.
  36. *
  37. * The order of returning metadata and buffers for a single result does not
  38. * matter, but buffers for a given stream must be returned in FIFO order. So
  39. * the buffer for request 5 for stream A must always be returned before the
  40. * buffer for request 6 for stream A. This also applies to the result
  41. * metadata; the metadata for request 5 must be returned before the metadata
  42. * for request 6.
  43. *
  44. * However, different streams are independent of each other, so it is
  45. * acceptable and expected that the buffer for request 5 for stream A may be
  46. * returned after the buffer for request 6 for stream B is. And it is
  47. * acceptable that the result metadata for request 6 for stream B is
  48. * returned before the buffer for request 5 for stream A is. If multiple
  49. * capture results are included in a single call, camera framework must
  50. * process results sequentially from lower index to higher index, as if
  51. * these results were sent to camera framework one by one, from lower index
  52. * to higher index.
  53. *
  54. * The HAL retains ownership of result structure, which only needs to be
  55. * valid to access during this call.
  56. *
  57. * The output buffers do not need to be filled yet; the framework must wait
  58. * on the stream buffer release sync fence before reading the buffer
  59. * data. Therefore, this method should be called by the HAL as soon as
  60. * possible, even if some or all of the output buffers are still in
  61. * being filled. The HAL must include valid release sync fences into each
  62. * output_buffers stream buffer entry, or -1 if that stream buffer is
  63. * already filled.
  64. *
  65. * If the result buffer cannot be constructed for a request, the HAL must
  66. * return an empty metadata buffer, but still provide the output buffers and
  67. * their sync fences. In addition, notify() must be called with an
  68. * ERROR_RESULT message.
  69. *
  70. * If an output buffer cannot be filled, its status field must be set to
  71. * STATUS_ERROR. In addition, notify() must be called with a ERROR_BUFFER
  72. * message.
  73. *
  74. * If the entire capture has failed, then this method still needs to be
  75. * called to return the output buffers to the framework. All the buffer
  76. * statuses must be STATUS_ERROR, and the result metadata must be an
  77. * empty buffer. In addition, notify() must be called with a ERROR_REQUEST
  78. * message. In this case, individual ERROR_RESULT/ERROR_BUFFER messages
  79. * must not be sent.
  80. *
  81. * Performance requirements:
  82. *
  83. * This is a non-blocking call. The framework must handle each CaptureResult
  84. * within 5ms.
  85. *
  86. * The pipeline latency (see S7 for definition) should be less than or equal to
  87. * 4 frame intervals, and must be less than or equal to 8 frame intervals.
  88. *
  89. */
  90. processCaptureResult(vec<CaptureResult> results);
  91. /**
  92. * notify:
  93. *
  94. * Asynchronous notification callback from the HAL, fired for various
  95. * reasons. Only for information independent of frame capture, or that
  96. * require specific timing. Multiple messages may be sent in one call; a
  97. * message with a higher index must be considered to have occurred after a
  98. * message with a lower index.
  99. *
  100. * Multiple threads may call notify() simultaneously.
  101. *
  102. * Buffers delivered to the framework must not be dispatched to the
  103. * application layer until a start of exposure timestamp (or input image's
  104. * start of exposure timestamp for a reprocess request) has been received
  105. * via a SHUTTER notify() call. It is highly recommended to dispatch this
  106. * call as early as possible.
  107. *
  108. * ------------------------------------------------------------------------
  109. * Performance requirements:
  110. *
  111. * This is a non-blocking call. The framework must handle each message in 5ms.
  112. */
  113. notify(vec<NotifyMsg> msgs);
  114. };

     看到这些大段大段的注释,就能明白,这些接口肯定都是非常重要的,详细的注释也是很好的习惯,看Android的源码感觉确实很舒服,难怪人家的代码能成为标准,不管是命名,格式,注释,分包,分类,所有的地方都让人感觉舒服!!

     好了,进入到我们本节的主题吧,ICameraDeviceCallback是HIDL定义的回调接口,processCaptureResult方法就是从HAL层回调到CameraServer的接口,CameraServer这一侧的回调类就是Camera3Device,因为在openCamera时,构造出来的Camera3Device进行初始化,Camera3Device类的initialize方法中与HAL进行连接,获取session时,将自己作为callback回调类传递到了HAL,所以后续HAL就会回调到Camera3Device类的processCaptureResult方法当中。

     我们再来回顾一下Camera3Device类的initialize方法,Camera3Device文件的目录路径为frameworks\av\services\camera\libcameraservice\device3\Camera3Device.cpp,initialize方法的源码如下:

  1. status_t Camera3Device::initialize(sp<CameraProviderManager> manager) {
  2. ATRACE_CALL();
  3. Mutex::Autolock il(mInterfaceLock);
  4. Mutex::Autolock l(mLock);
  5. ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
  6. if (mStatus != STATUS_UNINITIALIZED) {
  7. CLOGE("Already initialized!");
  8. return INVALID_OPERATION;
  9. }
  10. if (manager == nullptr) return INVALID_OPERATION;
  11. sp<ICameraDeviceSession> session;
  12. ATRACE_BEGIN("CameraHal::openSession");
  13. status_t res = manager->openSession(mId.string(), this,
  14. /*out*/ &session);
  15. ATRACE_END();
  16. if (res != OK) {
  17. SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
  18. return res;
  19. }
  20. res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
  21. if (res != OK) {
  22. SET_ERR_L("Could not retrive camera characteristics: %s (%d)", strerror(-res), res);
  23. session->close();
  24. return res;
  25. }
  26. std::shared_ptr<RequestMetadataQueue> queue;
  27. auto requestQueueRet = session->getCaptureRequestMetadataQueue(
  28. [&queue](const auto& descriptor) {
  29. queue = std::make_shared<RequestMetadataQueue>(descriptor);
  30. if (!queue->isValid() || queue->availableToWrite() <= 0) {
  31. ALOGE("HAL returns empty request metadata fmq, not use it");
  32. queue = nullptr;
  33. // don't use the queue onwards.
  34. }
  35. });
  36. if (!requestQueueRet.isOk()) {
  37. ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
  38. requestQueueRet.description().c_str());
  39. return DEAD_OBJECT;
  40. }
  41. auto resultQueueRet = session->getCaptureResultMetadataQueue(
  42. [&queue = mResultMetadataQueue](const auto& descriptor) {
  43. queue = std::make_unique<ResultMetadataQueue>(descriptor);
  44. if (!queue->isValid() || queue->availableToWrite() <= 0) {
  45. ALOGE("HAL returns empty result metadata fmq, not use it");
  46. queue = nullptr;
  47. // Don't use the queue onwards.
  48. }
  49. });
  50. if (!resultQueueRet.isOk()) {
  51. ALOGE("Transaction error when getting result metadata queue from camera session: %s",
  52. resultQueueRet.description().c_str());
  53. return DEAD_OBJECT;
  54. }
  55. mInterface = std::make_unique<HalInterface>(session, queue);
  56. std::string providerType;
  57. mVendorTagId = manager->getProviderTagIdLocked(mId.string());
  58. return initializeCommonLocked();
  59. }

     该方法中就是调用manager->openSession(mId.string(), this, /*out*/ &session)来打开session的,manager是方法入参sp<CameraProviderManager>,调用openSession方法的第二个参数就是回调接口,传值为this,第三个是输出参数,当session在HAL进程中创建成功,则会通过回调赋值给这个输出参数。进一步来看一下CameraProviderManager类的openSession方法的实现,源码如下:

  1. status_t CameraProviderManager::openSession(const std::string &id,
  2. const sp<hardware::camera::device::V3_2::ICameraDeviceCallback>& callback,
  3. /*out*/
  4. sp<hardware::camera::device::V3_2::ICameraDeviceSession> *session) {
  5. std::lock_guard<std::mutex> lock(mInterfaceMutex);
  6. auto deviceInfo = findDeviceInfoLocked(id,
  7. /*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
  8. if (deviceInfo == nullptr) return NAME_NOT_FOUND;
  9. auto *deviceInfo3 = static_cast<ProviderInfo::DeviceInfo3*>(deviceInfo);
  10. Status status;
  11. hardware::Return<void> ret;
  12. ret = deviceInfo3->mInterface->open(callback, [&status, &session]
  13. (Status s, const sp<device::V3_2::ICameraDeviceSession>& cameraSession) {
  14. status = s;
  15. if (status == Status::OK) {
  16. *session = cameraSession;
  17. }
  18. });
  19. if (!ret.isOk()) {
  20. ALOGE("%s: Transaction error opening a session for camera device %s: %s",
  21. __FUNCTION__, id.c_str(), ret.description().c_str());
  22. return DEAD_OBJECT;
  23. }
  24. return mapToStatusT(status);
  25. }

     这里的deviceInfo3->mInterface->open就会通过HIDL进入到CameraHalServer进程当中了。

     好,回过头来看Camera3Device类的processCaptureResult方法,源码如下:

  1. // Only one processCaptureResult should be called at a time, so
  2. // the locks won't block. The locks are present here simply to enforce this.
  3. hardware::Return<void> Camera3Device::processCaptureResult(
  4. const hardware::hidl_vec<
  5. hardware::camera::device::V3_2::CaptureResult>& results) {
  6. if (mProcessCaptureResultLock.tryLock() != OK) {
  7. // This should never happen; it indicates a wrong client implementation
  8. // that doesn't follow the contract. But, we can be tolerant here.
  9. ALOGE("%s: callback overlapped! waiting 1s...",
  10. __FUNCTION__);
  11. if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
  12. ALOGE("%s: cannot acquire lock in 1s, dropping results",
  13. __FUNCTION__);
  14. // really don't know what to do, so bail out.
  15. return hardware::Void();
  16. }
  17. }
  18. for (const auto& result : results) {
  19. processOneCaptureResultLocked(result);
  20. }
  21. mProcessCaptureResultLock.unlock();
  22. return hardware::Void();
  23. }
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号