[{"id":2616,"web_url":"https://patchwork.libcamera.org/comment/2616/","msgid":"<20190905081828.y647dyfqg2apejjp@uno.localdomain>","date":"2019-09-05T08:18:28","subject":"Re: [libcamera-devel] [PATCH v6 7/9] android: camera_device: Use\n\tthe new CameraMetadata helper class","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Laurent,\n\nOn Thu, Sep 05, 2019 at 09:47:34AM +0200, Jacopo Mondi wrote:\n> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n>\n> Simplify the implementation of metadata handling in the CameraDevice\n> class by using the new CameraMetadata helper class.\n>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  src/android/camera_device.cpp | 507 +++++++++++++---------------------\n>  src/android/camera_device.h   |  15 +-\n>  2 files changed, 198 insertions(+), 324 deletions(-)\n>\n> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n> index 5f8d19b9ef3d..475fa2404421 100644\n> --- a/src/android/camera_device.cpp\n> +++ b/src/android/camera_device.cpp\n> @@ -7,10 +7,10 @@\n>\n>  #include \"camera_device.h\"\n>\n> -#include <system/camera_metadata.h>\n> -\n>  #include \"log.h\"\n> +#include \"utils.h\"\n>\n> +#include \"camera_metadata.h\"\n>  #include \"thread_rpc.h\"\n>\n>  using namespace libcamera;\n> @@ -59,12 +59,10 @@ CameraDevice::CameraDevice(unsigned int id, const std::shared_ptr<Camera> &camer\n>  CameraDevice::~CameraDevice()\n>  {\n>  \tif (staticMetadata_)\n> -\t\tfree_camera_metadata(staticMetadata_);\n> -\tstaticMetadata_ = nullptr;\n> +\t\tdelete staticMetadata_;\n>\n>  \tif (requestTemplate_)\n> -\t\tfree_camera_metadata(requestTemplate_);\n> -\trequestTemplate_ = nullptr;\n> +\t\tdelete requestTemplate_;\n>  }\n>\n>  /*\n> @@ -117,10 +115,8 @@ void CameraDevice::setCallbacks(const camera3_callback_ops_t *callbacks)\n>   */\n>  camera_metadata_t *CameraDevice::getStaticMetadata()\n>  {\n> -\tint ret;\n> -\n>  \tif (staticMetadata_)\n> -\t\treturn staticMetadata_;\n> +\t\treturn staticMetadata_->get();\n>\n>  \t/*\n>  \t * The here reported metadata are enough to implement a basic capture\n> @@ -132,16 +128,21 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n>  \t * \\todo Keep this in sync with the actual number of entries.\n>  \t * Currently: 46 entries, 390 bytes\n>  \t */\n> -\tstaticMetadata_ = allocate_camera_metadata(50, 500);\n> +\tstaticMetadata_ = new CameraMetadata(50, 500);\n> +\tif (!staticMetadata_->isValid()) {\n> +\t\tLOG(HAL, Error) << \"Failed to allocate static metadata\";\n> +\t\tdelete staticMetadata_;\n> +\t\tstaticMetadata_ = nullptr;\n> +\t\treturn nullptr;\n\nEmpty line before return?\n\n> +\t}\n>\n>  \t/* Color correction static metadata. */\n>  \tstd::vector<uint8_t> aberrationModes = {\n>  \t\tANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> -\t\t\taberrationModes.data(), aberrationModes.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> +\t\t\t\t  aberrationModes.data(),\n> +\t\t\t\t  aberrationModes.size());\n>\n>  \t/* Control static metadata. */\n>  \tstd::vector<uint8_t> aeAvailableAntiBandingModes = {\n> @@ -150,294 +151,228 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n>  \t\tANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,\n>  \t\tANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,\n> -\t\t\taeAvailableAntiBandingModes.data(),\n> -\t\t\taeAvailableAntiBandingModes.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,\n> +\t\t\t\t  aeAvailableAntiBandingModes.data(),\n> +\t\t\t\t  aeAvailableAntiBandingModes.size());\n>\n>  \tstd::vector<uint8_t> aeAvailableModes = {\n>  \t\tANDROID_CONTROL_AE_MODE_ON,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_MODES,\n> -\t\t\taeAvailableModes.data(), aeAvailableModes.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,\n> +\t\t\t\t  aeAvailableModes.data(),\n> +\t\t\t\t  aeAvailableModes.size());\n>\n>  \tstd::vector<int32_t> availableAeFpsTarget = {\n>  \t\t15, 30,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> -\t\t\tavailableAeFpsTarget.data(),\n> -\t\t\tavailableAeFpsTarget.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> +\t\t\t\t  availableAeFpsTarget.data(),\n> +\t\t\t\t  availableAeFpsTarget.size());\n>\n>  \tstd::vector<int32_t> aeCompensationRange = {\n>  \t\t0, 0,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_AE_COMPENSATION_RANGE,\n> -\t\t\taeCompensationRange.data(),\n> -\t\t\taeCompensationRange.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_RANGE,\n> +\t\t\t\t  aeCompensationRange.data(),\n> +\t\t\t\t  aeCompensationRange.size());\n>\n>  \tconst camera_metadata_rational_t aeCompensationStep[] = {\n>  \t\t{ 0, 1 }\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_AE_COMPENSATION_STEP,\n> -\t\t\taeCompensationStep, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_STEP,\n> +\t\t\t\t  aeCompensationStep, 1);\n>\n>  \tstd::vector<uint8_t> availableAfModes = {\n>  \t\tANDROID_CONTROL_AF_MODE_OFF,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_AF_AVAILABLE_MODES,\n> -\t\t\tavailableAfModes.data(), availableAfModes.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AF_AVAILABLE_MODES,\n> +\t\t\t\t  availableAfModes.data(),\n> +\t\t\t\t  availableAfModes.size());\n>\n>  \tstd::vector<uint8_t> availableEffects = {\n>  \t\tANDROID_CONTROL_EFFECT_MODE_OFF,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_AVAILABLE_EFFECTS,\n> -\t\t\tavailableEffects.data(), availableEffects.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_EFFECTS,\n> +\t\t\t\t  availableEffects.data(),\n> +\t\t\t\t  availableEffects.size());\n>\n>  \tstd::vector<uint8_t> availableSceneModes = {\n>  \t\tANDROID_CONTROL_SCENE_MODE_DISABLED,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_AVAILABLE_SCENE_MODES,\n> -\t\t\tavailableSceneModes.data(), availableSceneModes.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,\n> +\t\t\t\t  availableSceneModes.data(),\n> +\t\t\t\t  availableSceneModes.size());\n>\n>  \tstd::vector<uint8_t> availableStabilizationModes = {\n>  \t\tANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,\n> -\t\t\tavailableStabilizationModes.data(),\n> -\t\t\tavailableStabilizationModes.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,\n> +\t\t\t\t  availableStabilizationModes.data(),\n> +\t\t\t\t  availableStabilizationModes.size());\n>\n>  \tstd::vector<uint8_t> availableAwbModes = {\n>  \t\tANDROID_CONTROL_AWB_MODE_OFF,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> -\t\t\tavailableAwbModes.data(), availableAwbModes.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> +\t\t\t\t  availableAwbModes.data(),\n> +\t\t\t\t  availableAwbModes.size());\n>\n>  \tstd::vector<int32_t> availableMaxRegions = {\n>  \t\t0, 0, 0,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_MAX_REGIONS,\n> -\t\t\tavailableMaxRegions.data(), availableMaxRegions.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_MAX_REGIONS,\n> +\t\t\t\t  availableMaxRegions.data(),\n> +\t\t\t\t  availableMaxRegions.size());\n>\n>  \tstd::vector<uint8_t> sceneModesOverride = {\n>  \t\tANDROID_CONTROL_AE_MODE_ON,\n>  \t\tANDROID_CONTROL_AWB_MODE_AUTO,\n>  \t\tANDROID_CONTROL_AF_MODE_AUTO,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_SCENE_MODE_OVERRIDES,\n> -\t\t\tsceneModesOverride.data(), sceneModesOverride.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,\n> +\t\t\t\t  sceneModesOverride.data(),\n> +\t\t\t\t  sceneModesOverride.size());\n>\n>  \tuint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> -\t\t\t&aeLockAvailable, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> +\t\t\t\t  &aeLockAvailable, 1);\n>\n>  \tuint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> -\t\t\t&awbLockAvailable, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> +\t\t\t\t  &awbLockAvailable, 1);\n>\n>  \tchar availableControlModes = ANDROID_CONTROL_MODE_AUTO;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_CONTROL_AVAILABLE_MODES,\n> -\t\t\t&availableControlModes, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,\n> +\t\t\t\t  &availableControlModes, 1);\n>\n>  \t/* JPEG static metadata. */\n>  \tstd::vector<int32_t> availableThumbnailSizes = {\n>  \t\t0, 0,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,\n> -\t\t\tavailableThumbnailSizes.data(),\n> -\t\t\tavailableThumbnailSizes.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,\n> +\t\t\t\t  availableThumbnailSizes.data(),\n> +\t\t\t\t  availableThumbnailSizes.size());\n>\n>  \t/* Sensor static metadata. */\n>  \tint32_t pixelArraySize[] = {\n>  \t\t2592, 1944,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,\n> -\t\t\t\t&pixelArraySize, 2);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,\n> +\t\t\t\t  &pixelArraySize, 2);\n>\n>  \tint32_t sensorSizes[] = {\n>  \t\t0, 0, 2560, 1920,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,\n> -\t\t\t\t&sensorSizes, 4);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,\n> +\t\t\t\t  &sensorSizes, 4);\n>\n>  \tint32_t sensitivityRange[] = {\n>  \t\t32, 2400,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_SENSOR_INFO_SENSITIVITY_RANGE,\n> -\t\t\t\t&sensitivityRange, 2);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,\n> +\t\t\t\t  &sensitivityRange, 2);\n>\n>  \tuint16_t filterArr = ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,\n> -\t\t\t\t&filterArr, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,\n> +\t\t\t\t  &filterArr, 1);\n>\n>  \tint64_t exposureTimeRange[] = {\n>  \t\t100000, 200000000,\n>  \t};\n\nI've been thinking for a while to stabilize on the use of std::vector in\nplace of arrays, so e can always use .data() and .size() and have\nguaranteed we should only change the declaration and not the\nparameters to the addEntry() operation.\n\nThis might be a good time to do so. What do you think?\n\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> -\t\t\t\t&exposureTimeRange, 2);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> +\t\t\t\t  &exposureTimeRange, 2);\n>\n>  \tint32_t orientation = 0;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_SENSOR_ORIENTATION,\n> -\t\t\t\t&orientation, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION,\n> +\t\t\t\t  &orientation, 1);\n\nFits in 1 line\n\n>\n>  \tstd::vector<int32_t> testPatterModes = {\n>  \t\tANDROID_SENSOR_TEST_PATTERN_MODE_OFF,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,\n> -\t\t\t\ttestPatterModes.data(), testPatterModes.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,\n> +\t\t\t\t  testPatterModes.data(),\n> +\t\t\t\t  testPatterModes.size());\n>\n>  \tstd::vector<float> physicalSize = {\n>  \t\t2592, 1944,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_SENSOR_INFO_PHYSICAL_SIZE,\n> -\t\t\t\tphysicalSize.data(), physicalSize.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,\n> +\t\t\t\t  physicalSize.data(),\n> +\t\t\t\t  physicalSize.size());\n\nFits in 1 line\n\n>\n>  \tuint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,\n> -\t\t\t&timestampSource, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,\n> +\t\t\t\t  &timestampSource, 1);\n>\n>  \t/* Statistics static metadata. */\n>  \tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> -\t\t\t&faceDetectMode, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> +\t\t\t\t  &faceDetectMode, 1);\n>\n>  \tint32_t maxFaceCount = 0;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> -\t\t\t&maxFaceCount, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> +\t\t\t\t  &maxFaceCount, 1);\n>\n>  \t/* Sync static metadata. */\n>  \tint32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);\n>\n>  \t/* Flash static metadata. */\n>  \tchar flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_FLASH_INFO_AVAILABLE,\n> -\t\t\t&flashAvailable, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_FLASH_INFO_AVAILABLE,\n> +\t\t\t\t  &flashAvailable, 1);\n>\n>  \t/* Lens static metadata. */\n>  \tstd::vector<float> lensApertures = {\n>  \t\t2.53 / 100,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_APERTURES,\n> -\t\t\t\tlensApertures.data(), lensApertures.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_APERTURES,\n> +\t\t\t\t  lensApertures.data(),\n> +\t\t\t\t  lensApertures.size());\n>\n>  \tuint8_t lensFacing = ANDROID_LENS_FACING_FRONT;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_LENS_FACING, &lensFacing, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_LENS_FACING, &lensFacing, 1);\n>\n>  \tstd::vector<float> lensFocalLenghts = {\n>  \t\t1,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,\n> -\t\t\t\tlensFocalLenghts.data(),\n> -\t\t\t\tlensFocalLenghts.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,\n> +\t\t\t\t  lensFocalLenghts.data(),\n> +\t\t\t\t  lensFocalLenghts.size());\n>\n>  \tstd::vector<uint8_t> opticalStabilizations = {\n>  \t\tANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,\n> -\t\t\t\topticalStabilizations.data(),\n> -\t\t\t\topticalStabilizations.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,\n> +\t\t\t\t  opticalStabilizations.data(),\n> +\t\t\t\t  opticalStabilizations.size());\n>\n>  \tfloat hypeFocalDistance = 0;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,\n> -\t\t\t\t&hypeFocalDistance, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,\n> +\t\t\t\t  &hypeFocalDistance, 1);\n>\n>  \tfloat minFocusDistance = 0;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,\n> -\t\t\t\t&minFocusDistance, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,\n> +\t\t\t\t  &minFocusDistance, 1);\n>\n>  \t/* Noise reduction modes. */\n>  \tuint8_t noiseReductionModes = ANDROID_NOISE_REDUCTION_MODE_OFF;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\t\tANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,\n> -\t\t\t\t&noiseReductionModes, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,\n> +\t\t\t\t  &noiseReductionModes, 1);\n>\n>  \t/* Scaler static metadata. */\n>  \tfloat maxDigitalZoom = 1;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,\n> -\t\t\t&maxDigitalZoom, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,\n> +\t\t\t\t  &maxDigitalZoom, 1);\n>\n>  \tstd::vector<uint32_t> availableStreamFormats = {\n>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB,\n>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888,\n>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_SCALER_AVAILABLE_FORMATS,\n> -\t\t\tavailableStreamFormats.data(),\n> -\t\t\tavailableStreamFormats.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_FORMATS,\n> +\t\t\t\t  availableStreamFormats.data(),\n> +\t\t\t\t  availableStreamFormats.size());\n>\n>  \tstd::vector<uint32_t> availableStreamConfigurations = {\n>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920,\n> @@ -447,65 +382,57 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920,\n>  \t\tANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,\n> -\t\t\tavailableStreamConfigurations.data(),\n> -\t\t\tavailableStreamConfigurations.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,\n> +\t\t\t\t  availableStreamConfigurations.data(),\n> +\t\t\t\t  availableStreamConfigurations.size());\n>\n>  \tstd::vector<int64_t> availableStallDurations = {\n>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_SCALER_AVAILABLE_STALL_DURATIONS,\n> -\t\t\tavailableStallDurations.data(),\n> -\t\t\tavailableStallDurations.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,\n> +\t\t\t\t  availableStallDurations.data(),\n> +\t\t\t\t  availableStallDurations.size());\n>\n>  \tstd::vector<int64_t> minFrameDurations = {\n>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,\n>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920, 33333333,\n>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888, 2560, 1920, 33333333,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> -\t\t\tminFrameDurations.data(), minFrameDurations.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> +\t\t\t\t  minFrameDurations.data(),\n> +\t\t\t\t  minFrameDurations.size());\n>\n>  \tuint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);\n>\n>  \t/* Info static metadata. */\n>  \tuint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> -\t\t\t&supportedHWLevel, 1);\n> +\tstaticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> +\t\t\t\t  &supportedHWLevel, 1);\n>\n>  \t/* Request static metadata. */\n>  \tint32_t partialResultCount = 1;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> -\t\t\t&partialResultCount, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> +\t\t\t\t  &partialResultCount, 1);\n>\n>  \tuint8_t maxPipelineDepth = 2;\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_REQUEST_PIPELINE_MAX_DEPTH,\n> -\t\t\t&maxPipelineDepth, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_PIPELINE_MAX_DEPTH,\n> +\t\t\t\t  &maxPipelineDepth, 1);\n>\n>  \tstd::vector<uint8_t> availableCapabilities = {\n>  \t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,\n>  \t};\n> -\tret = add_camera_metadata_entry(staticMetadata_,\n> -\t\t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> -\t\t\tavailableCapabilities.data(),\n> -\t\t\tavailableCapabilities.size());\n> -\tMETADATA_ASSERT(ret);\n> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> +\t\t\t\t  availableCapabilities.data(),\n> +\t\t\t\t  availableCapabilities.size());\n> +\n> +\tif (!staticMetadata_->isValid()) {\n> +\t\tdelete staticMetadata_;\n> +\t\tstaticMetadata_ = nullptr;\n> +\t\treturn nullptr;\n> +\t}\n>\n> -\treturn staticMetadata_;\n> +\treturn staticMetadata_->get();\n>  }\n>\n>  /*\n> @@ -513,8 +440,6 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n>   */\n>  const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)\n>  {\n> -\tint ret;\n> -\n>  \t/*\n>  \t * \\todo Inspect type and pick the right metadata pack.\n>  \t * As of now just use a single one for all templates.\n> @@ -545,89 +470,73 @@ const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)\n>  \t}\n>\n>  \tif (requestTemplate_)\n> -\t\treturn requestTemplate_;\n> +\t\treturn requestTemplate_->get();\n>\n>  \t/*\n>  \t * \\todo Keep this in sync with the actual number of entries.\n>  \t * Currently: 12 entries, 15 bytes\n>  \t */\n> -\trequestTemplate_ = allocate_camera_metadata(15, 20);\n> +\trequestTemplate_ = new CameraMetadata(15, 20);\n>  \tif (!requestTemplate_) {\n>  \t\tLOG(HAL, Error) << \"Failed to allocate template metadata\";\n> +\t\tdelete requestTemplate_;\n> +\t\trequestTemplate_ = nullptr;\n\nEmpty line before return ?\n\n>  \t\treturn nullptr;\n>  \t}\n>\n>  \tuint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;\n> -\tret = add_camera_metadata_entry(requestTemplate_,\n> -\t\t\tANDROID_CONTROL_AE_MODE,\n> -\t\t\t&aeMode, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_MODE,\n> +\t\t\t\t   &aeMode, 1);\n\nThis and many others entries here and below fit in 1 line.\n\n>\n>  \tint32_t aeExposureCompensation = 0;\n> -\tret = add_camera_metadata_entry(requestTemplate_,\n> -\t\t\tANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,\n> -\t\t\t&aeExposureCompensation, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,\n> +\t\t\t\t   &aeExposureCompensation, 1);\n>\n>  \tuint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;\n> -\tret = add_camera_metadata_entry(requestTemplate_,\n> -\t\t\tANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,\n> -\t\t\t&aePrecaptureTrigger, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,\n> +\t\t\t\t   &aePrecaptureTrigger, 1);\n>\n>  \tuint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;\n> -\tret = add_camera_metadata_entry(requestTemplate_,\n> -\t\t\tANDROID_CONTROL_AE_LOCK,\n> -\t\t\t&aeLock, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_LOCK,\n> +\t\t\t\t   &aeLock, 1);\n>\n>  \tuint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;\n> -\tret = add_camera_metadata_entry(requestTemplate_,\n> -\t\t\tANDROID_CONTROL_AF_TRIGGER,\n> -\t\t\t&afTrigger, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AF_TRIGGER,\n> +\t\t\t\t   &afTrigger, 1);\n>\n>  \tuint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;\n> -\tret = add_camera_metadata_entry(requestTemplate_,\n> -\t\t\tANDROID_CONTROL_AWB_MODE,\n> -\t\t\t&awbMode, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AWB_MODE,\n> +\t\t\t\t   &awbMode, 1);\n>\n>  \tuint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;\n> -\tret = add_camera_metadata_entry(requestTemplate_,\n> -\t\t\tANDROID_CONTROL_AWB_LOCK,\n> -\t\t\t&awbLock, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AWB_LOCK,\n> +\t\t\t\t   &awbLock, 1);\n>\n>  \tuint8_t flashMode = ANDROID_FLASH_MODE_OFF;\n> -\tret = add_camera_metadata_entry(requestTemplate_,\n> -\t\t\tANDROID_FLASH_MODE,\n> -\t\t\t&flashMode, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\trequestTemplate_->addEntry(ANDROID_FLASH_MODE,\n> +\t\t\t\t   &flashMode, 1);\n>\n>  \tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> -\tret = add_camera_metadata_entry(requestTemplate_,\n> -\t\t\tANDROID_STATISTICS_FACE_DETECT_MODE,\n> -\t\t\t&faceDetectMode, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\trequestTemplate_->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,\n> +\t\t\t\t   &faceDetectMode, 1);\n>\n>  \tuint8_t noiseReduction = ANDROID_NOISE_REDUCTION_MODE_OFF;\n> -\tret = add_camera_metadata_entry(requestTemplate_,\n> -\t\t\tANDROID_NOISE_REDUCTION_MODE, &noiseReduction, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\trequestTemplate_->addEntry(ANDROID_NOISE_REDUCTION_MODE,\n> +\t\t\t\t   &noiseReduction, 1);\n>\n>  \tuint8_t aberrationMode = ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF;\n> -\tret = add_camera_metadata_entry(requestTemplate_,\n> -\t\t\tANDROID_COLOR_CORRECTION_ABERRATION_MODE,\n> -\t\t\t&aberrationMode, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\trequestTemplate_->addEntry(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,\n> +\t\t\t\t   &aberrationMode, 1);\n> +\n> +\trequestTemplate_->addEntry(ANDROID_CONTROL_CAPTURE_INTENT,\n> +\t\t\t\t   &captureIntent, 1);\n>\n> -\tret = add_camera_metadata_entry(requestTemplate_,\n> -\t\t\tANDROID_CONTROL_CAPTURE_INTENT,\n> -\t\t\t&captureIntent, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tif (!requestTemplate_->isValid()) {\n> +\t\tdelete requestTemplate_;\n> +\t\trequestTemplate_ = nullptr;\n\nYou should return nullptr here, otherwise the below requestTemplate_->get();\nwill de-reference a nullptr.\n\n> +\t}\n>\n> -\treturn requestTemplate_;\n> +\treturn requestTemplate_->get();\n>  }\n>\n>  /*\n> @@ -799,7 +708,7 @@ void CameraDevice::requestComplete(Request *request,\n>  {\n>  \tBuffer *libcameraBuffer = buffers.begin()->second;\n>  \tcamera3_buffer_status status = CAMERA3_BUFFER_STATUS_OK;\n> -\tcamera_metadata_t *resultMetadata = nullptr;\n> +\tstd::unique_ptr<CameraMetadata> resultMetadata;\n>\n>  \tif (request->status() != Request::RequestComplete) {\n>  \t\tLOG(HAL, Error) << \"Request not succesfully completed: \"\n> @@ -837,16 +746,12 @@ void CameraDevice::requestComplete(Request *request,\n>  \t\tcaptureResult.partial_result = 1;\n>  \t\tresultMetadata = getResultMetadata(descriptor->frameNumber,\n>  \t\t\t\t\t\t   libcameraBuffer->timestamp());\n> -\t\tcaptureResult.result = resultMetadata;\n> +\t\tcaptureResult.result = resultMetadata->get();\n>  \t}\n>\n>  \tcallbacks_->process_capture_result(callbacks_, &captureResult);\n>\n>  \tdelete descriptor;\n> -\tif (resultMetadata)\n> -\t\tfree_camera_metadata(resultMetadata);\n> -\n> -\treturn;\n>  }\n>\n>  void CameraDevice::notifyShutter(uint32_t frameNumber, uint64_t timestamp)\n> @@ -875,89 +780,63 @@ void CameraDevice::notifyError(uint32_t frameNumber, camera3_stream_t *stream)\n>  /*\n>   * Produce a set of fixed result metadata.\n>   */\n> -camera_metadata_t *CameraDevice::getResultMetadata(int frame_number,\n> -\t\t\t\t\t\t   int64_t timestamp)\n> +std::unique_ptr<CameraMetadata> CameraDevice::getResultMetadata(int frame_number,\n\nNot a fan of smart pointers, you know already. How does this work?\nBecause the compiler applies copy-elision or because of the move\nsemantic applied on the return value?\n\nAnway. it saves 2 lines in the caller but makes the code more\ndifficult to follow in my opinion.\n\n> +\t\t\t\t\t\t\t\tint64_t timestamp)\n>  {\n> -\tint ret;\n> -\n>  \t/*\n>  \t * \\todo Keep this in sync with the actual number of entries.\n>  \t * Currently: 13 entries, 36 bytes\n>  \t */\n> -\tcamera_metadata_t *resultMetadata = allocate_camera_metadata(15, 50);\n> +\tstd::unique_ptr<CameraMetadata> resultMetadata =\n> +\t\tutils::make_unique<CameraMetadata>(15, 50);\n> +\tif (!resultMetadata->isValid()) {\n> +\t\tLOG(HAL, Error) << \"Failed to allocate static metadata\";\n> +\t\treturn nullptr;\n> +\t}\n>\n>  \tconst uint8_t ae_state = ANDROID_CONTROL_AE_STATE_CONVERGED;\n> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AE_STATE,\n> -\t\t\t\t\t&ae_state, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tresultMetadata->addEntry(ANDROID_CONTROL_AE_STATE, &ae_state, 1);\n>\n>  \tconst uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;\n> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AE_LOCK,\n> -\t\t\t\t\t&ae_lock, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tresultMetadata->addEntry(ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);\n>\n>  \tuint8_t af_state = ANDROID_CONTROL_AF_STATE_INACTIVE;\n> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AF_STATE,\n> -\t\t\t\t\t&af_state, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tresultMetadata->addEntry(ANDROID_CONTROL_AF_STATE, &af_state, 1);\n>\n>  \tconst uint8_t awb_state = ANDROID_CONTROL_AWB_STATE_CONVERGED;\n> -\tret = add_camera_metadata_entry(resultMetadata,\n> -\t\t\t\t\tANDROID_CONTROL_AWB_STATE,\n> -\t\t\t\t\t&awb_state, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tresultMetadata->addEntry(ANDROID_CONTROL_AWB_STATE, &awb_state, 1);\n>\n>  \tconst uint8_t awb_lock = ANDROID_CONTROL_AWB_LOCK_OFF;\n> -\tret = add_camera_metadata_entry(resultMetadata,\n> -\t\t\t\t\tANDROID_CONTROL_AWB_LOCK,\n> -\t\t\t\t\t&awb_lock, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tresultMetadata->addEntry(ANDROID_CONTROL_AWB_LOCK, &awb_lock, 1);\n>\n>  \tconst uint8_t lens_state = ANDROID_LENS_STATE_STATIONARY;\n> -\tret = add_camera_metadata_entry(resultMetadata,\n> -\t\t\t\t\tANDROID_LENS_STATE,\n> -\t\t\t\t\t&lens_state, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tresultMetadata->addEntry(ANDROID_LENS_STATE, &lens_state, 1);\n>\n>  \tint32_t sensorSizes[] = {\n>  \t\t0, 0, 2560, 1920,\n>  \t};\n> -\tret = add_camera_metadata_entry(resultMetadata,\n> -\t\t\t\t\tANDROID_SCALER_CROP_REGION,\n> -\t\t\t\t\tsensorSizes, 4);\n> -\tMETADATA_ASSERT(ret);\n> +\tresultMetadata->addEntry(ANDROID_SCALER_CROP_REGION, sensorSizes, 4);\n>\n> -\tret = add_camera_metadata_entry(resultMetadata,\n> -\t\t\t\t\tANDROID_SENSOR_TIMESTAMP,\n> -\t\t\t\t\t&timestamp, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tresultMetadata->addEntry(ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);\n>\n>  \t/* 33.3 msec */\n>  \tconst int64_t rolling_shutter_skew = 33300000;\n> -\tret = add_camera_metadata_entry(resultMetadata,\n> -\t\t\t\t\tANDROID_SENSOR_ROLLING_SHUTTER_SKEW,\n> -\t\t\t\t\t&rolling_shutter_skew, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tresultMetadata->addEntry(ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,\n> +\t\t\t\t &rolling_shutter_skew, 1);\n>\n>  \t/* 16.6 msec */\n>  \tconst int64_t exposure_time = 16600000;\n> -\tret = add_camera_metadata_entry(resultMetadata,\n> -\t\t\t\t\tANDROID_SENSOR_EXPOSURE_TIME,\n> -\t\t\t\t\t&exposure_time, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tresultMetadata->addEntry(ANDROID_SENSOR_EXPOSURE_TIME,\n> +\t\t\t\t &exposure_time, 1);\n>\n>  \tconst uint8_t lens_shading_map_mode =\n>  \t\t\t\tANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;\n> -\tret = add_camera_metadata_entry(resultMetadata,\n> -\t\t\t\t\tANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> -\t\t\t\t\t&lens_shading_map_mode, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tresultMetadata->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> +\t\t\t\t &lens_shading_map_mode, 1);\n>\n>  \tconst uint8_t scene_flicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE;\n> -\tret = add_camera_metadata_entry(resultMetadata,\n> -\t\t\t\t\tANDROID_STATISTICS_SCENE_FLICKER,\n> -\t\t\t\t\t&scene_flicker, 1);\n> -\tMETADATA_ASSERT(ret);\n> +\tresultMetadata->addEntry(ANDROID_STATISTICS_SCENE_FLICKER,\n> +\t\t\t\t &scene_flicker, 1);\n\nShouldn't you check if the metadata pack is valid ?\n\nThanks\n  j\n\n>\n>  \treturn resultMetadata;\n>  }\n> diff --git a/src/android/camera_device.h b/src/android/camera_device.h\n> index 7897ba9dc5c7..65ba877a02ea 100644\n> --- a/src/android/camera_device.h\n> +++ b/src/android/camera_device.h\n> @@ -19,13 +19,7 @@\n>\n>  #include \"message.h\"\n>\n> -#define METADATA_ASSERT(_r)\t\t\\\n> -\tdo {\t\t\t\t\\\n> -\t\tif (!(_r)) break;\t\\\n> -\t\tLOG(HAL, Error) << \"Error: \" << __func__ << \":\" << __LINE__; \\\n> -\t\treturn nullptr;\t\t\\\n> -\t} while(0);\n> -\n> +class CameraMetadata;\n>  class ThreadRpc;\n>\n>  class CameraDevice : public libcamera::Object\n> @@ -59,14 +53,15 @@ private:\n>\n>  \tvoid notifyShutter(uint32_t frameNumber, uint64_t timestamp);\n>  \tvoid notifyError(uint32_t frameNumber, camera3_stream_t *stream);\n> -\tcamera_metadata_t *getResultMetadata(int frame_number, int64_t timestamp);\n> +\tstd::unique_ptr<CameraMetadata> getResultMetadata(int frame_number,\n> +\t\t\t\t\t\t\t  int64_t timestamp);\n>\n>  \tbool running_;\n>  \tstd::shared_ptr<libcamera::Camera> camera_;\n>  \tstd::unique_ptr<libcamera::CameraConfiguration> config_;\n>\n> -\tcamera_metadata_t *staticMetadata_;\n> -\tcamera_metadata_t *requestTemplate_;\n> +\tCameraMetadata *staticMetadata_;\n> +\tCameraMetadata *requestTemplate_;\n>  \tconst camera3_callback_ops_t *callbacks_;\n>  };\n>\n> --\n> 2.23.0\n>\n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net\n\t[217.70.183.199])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C4F9B60BD9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 Sep 2019 10:16:55 +0200 (CEST)","from uno.localdomain (2-224-242-101.ip172.fastwebnet.it\n\t[2.224.242.101]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 5E1C7FF80A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 Sep 2019 08:16:55 +0000 (UTC)"],"X-Originating-IP":"2.224.242.101","Date":"Thu, 5 Sep 2019 10:18:28 +0200","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190905081828.y647dyfqg2apejjp@uno.localdomain>","References":"<20190905074737.6955-1-jacopo@jmondi.org>\n\t<20190905074737.6955-8-jacopo@jmondi.org>","MIME-Version":"1.0","Content-Type":"multipart/signed; micalg=pgp-sha256;\n\tprotocol=\"application/pgp-signature\"; boundary=\"qrr253z3alcto2kh\"","Content-Disposition":"inline","In-Reply-To":"<20190905074737.6955-8-jacopo@jmondi.org>","User-Agent":"NeoMutt/20180716","Subject":"Re: [libcamera-devel] [PATCH v6 7/9] android: camera_device: Use\n\tthe new CameraMetadata helper class","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Thu, 05 Sep 2019 08:16:56 -0000"}},{"id":2617,"web_url":"https://patchwork.libcamera.org/comment/2617/","msgid":"<20190905093657.GA5035@pendragon.ideasonboard.com>","date":"2019-09-05T09:36:57","subject":"Re: [libcamera-devel] [PATCH v6 7/9] android: camera_device: Use\n\tthe new CameraMetadata helper class","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nOn Thu, Sep 05, 2019 at 10:18:28AM +0200, Jacopo Mondi wrote:\n> On Thu, Sep 05, 2019 at 09:47:34AM +0200, Jacopo Mondi wrote:\n> > From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> >\n> > Simplify the implementation of metadata handling in the CameraDevice\n> > class by using the new CameraMetadata helper class.\n> >\n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >  src/android/camera_device.cpp | 507 +++++++++++++---------------------\n> >  src/android/camera_device.h   |  15 +-\n> >  2 files changed, 198 insertions(+), 324 deletions(-)\n> >\n> > diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n> > index 5f8d19b9ef3d..475fa2404421 100644\n> > --- a/src/android/camera_device.cpp\n> > +++ b/src/android/camera_device.cpp\n> > @@ -7,10 +7,10 @@\n> >\n> >  #include \"camera_device.h\"\n> >\n> > -#include <system/camera_metadata.h>\n> > -\n> >  #include \"log.h\"\n> > +#include \"utils.h\"\n> >\n> > +#include \"camera_metadata.h\"\n> >  #include \"thread_rpc.h\"\n> >\n> >  using namespace libcamera;\n> > @@ -59,12 +59,10 @@ CameraDevice::CameraDevice(unsigned int id, const std::shared_ptr<Camera> &camer\n> >  CameraDevice::~CameraDevice()\n> >  {\n> >  \tif (staticMetadata_)\n> > -\t\tfree_camera_metadata(staticMetadata_);\n> > -\tstaticMetadata_ = nullptr;\n> > +\t\tdelete staticMetadata_;\n> >\n> >  \tif (requestTemplate_)\n> > -\t\tfree_camera_metadata(requestTemplate_);\n> > -\trequestTemplate_ = nullptr;\n> > +\t\tdelete requestTemplate_;\n> >  }\n> >\n> >  /*\n> > @@ -117,10 +115,8 @@ void CameraDevice::setCallbacks(const camera3_callback_ops_t *callbacks)\n> >   */\n> >  camera_metadata_t *CameraDevice::getStaticMetadata()\n> >  {\n> > -\tint ret;\n> > -\n> >  \tif (staticMetadata_)\n> > -\t\treturn staticMetadata_;\n> > +\t\treturn staticMetadata_->get();\n> >\n> >  \t/*\n> >  \t * The here reported metadata are enough to implement a basic capture\n> > @@ -132,16 +128,21 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> >  \t * \\todo Keep this in sync with the actual number of entries.\n> >  \t * Currently: 46 entries, 390 bytes\n> >  \t */\n> > -\tstaticMetadata_ = allocate_camera_metadata(50, 500);\n> > +\tstaticMetadata_ = new CameraMetadata(50, 500);\n> > +\tif (!staticMetadata_->isValid()) {\n> > +\t\tLOG(HAL, Error) << \"Failed to allocate static metadata\";\n> > +\t\tdelete staticMetadata_;\n> > +\t\tstaticMetadata_ = nullptr;\n> > +\t\treturn nullptr;\n> \n> Empty line before return?\n\nI don't mind either way, but I haven't added one as the delete,\nassignment to nullptr and return nullptr are logically grouped in my\nopinion. Feel free to add a blank line if you prefer.\n\n> > +\t}\n> >\n> >  \t/* Color correction static metadata. */\n> >  \tstd::vector<uint8_t> aberrationModes = {\n> >  \t\tANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> > -\t\t\taberrationModes.data(), aberrationModes.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> > +\t\t\t\t  aberrationModes.data(),\n> > +\t\t\t\t  aberrationModes.size());\n> >\n> >  \t/* Control static metadata. */\n> >  \tstd::vector<uint8_t> aeAvailableAntiBandingModes = {\n> > @@ -150,294 +151,228 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> >  \t\tANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,\n> >  \t\tANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,\n> > -\t\t\taeAvailableAntiBandingModes.data(),\n> > -\t\t\taeAvailableAntiBandingModes.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,\n> > +\t\t\t\t  aeAvailableAntiBandingModes.data(),\n> > +\t\t\t\t  aeAvailableAntiBandingModes.size());\n> >\n> >  \tstd::vector<uint8_t> aeAvailableModes = {\n> >  \t\tANDROID_CONTROL_AE_MODE_ON,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_AE_AVAILABLE_MODES,\n> > -\t\t\taeAvailableModes.data(), aeAvailableModes.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,\n> > +\t\t\t\t  aeAvailableModes.data(),\n> > +\t\t\t\t  aeAvailableModes.size());\n> >\n> >  \tstd::vector<int32_t> availableAeFpsTarget = {\n> >  \t\t15, 30,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> > -\t\t\tavailableAeFpsTarget.data(),\n> > -\t\t\tavailableAeFpsTarget.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> > +\t\t\t\t  availableAeFpsTarget.data(),\n> > +\t\t\t\t  availableAeFpsTarget.size());\n> >\n> >  \tstd::vector<int32_t> aeCompensationRange = {\n> >  \t\t0, 0,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_AE_COMPENSATION_RANGE,\n> > -\t\t\taeCompensationRange.data(),\n> > -\t\t\taeCompensationRange.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_RANGE,\n> > +\t\t\t\t  aeCompensationRange.data(),\n> > +\t\t\t\t  aeCompensationRange.size());\n> >\n> >  \tconst camera_metadata_rational_t aeCompensationStep[] = {\n> >  \t\t{ 0, 1 }\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_AE_COMPENSATION_STEP,\n> > -\t\t\taeCompensationStep, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_STEP,\n> > +\t\t\t\t  aeCompensationStep, 1);\n> >\n> >  \tstd::vector<uint8_t> availableAfModes = {\n> >  \t\tANDROID_CONTROL_AF_MODE_OFF,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_AF_AVAILABLE_MODES,\n> > -\t\t\tavailableAfModes.data(), availableAfModes.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AF_AVAILABLE_MODES,\n> > +\t\t\t\t  availableAfModes.data(),\n> > +\t\t\t\t  availableAfModes.size());\n> >\n> >  \tstd::vector<uint8_t> availableEffects = {\n> >  \t\tANDROID_CONTROL_EFFECT_MODE_OFF,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_AVAILABLE_EFFECTS,\n> > -\t\t\tavailableEffects.data(), availableEffects.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_EFFECTS,\n> > +\t\t\t\t  availableEffects.data(),\n> > +\t\t\t\t  availableEffects.size());\n> >\n> >  \tstd::vector<uint8_t> availableSceneModes = {\n> >  \t\tANDROID_CONTROL_SCENE_MODE_DISABLED,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_AVAILABLE_SCENE_MODES,\n> > -\t\t\tavailableSceneModes.data(), availableSceneModes.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,\n> > +\t\t\t\t  availableSceneModes.data(),\n> > +\t\t\t\t  availableSceneModes.size());\n> >\n> >  \tstd::vector<uint8_t> availableStabilizationModes = {\n> >  \t\tANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,\n> > -\t\t\tavailableStabilizationModes.data(),\n> > -\t\t\tavailableStabilizationModes.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,\n> > +\t\t\t\t  availableStabilizationModes.data(),\n> > +\t\t\t\t  availableStabilizationModes.size());\n> >\n> >  \tstd::vector<uint8_t> availableAwbModes = {\n> >  \t\tANDROID_CONTROL_AWB_MODE_OFF,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> > -\t\t\tavailableAwbModes.data(), availableAwbModes.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> > +\t\t\t\t  availableAwbModes.data(),\n> > +\t\t\t\t  availableAwbModes.size());\n> >\n> >  \tstd::vector<int32_t> availableMaxRegions = {\n> >  \t\t0, 0, 0,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_MAX_REGIONS,\n> > -\t\t\tavailableMaxRegions.data(), availableMaxRegions.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_MAX_REGIONS,\n> > +\t\t\t\t  availableMaxRegions.data(),\n> > +\t\t\t\t  availableMaxRegions.size());\n> >\n> >  \tstd::vector<uint8_t> sceneModesOverride = {\n> >  \t\tANDROID_CONTROL_AE_MODE_ON,\n> >  \t\tANDROID_CONTROL_AWB_MODE_AUTO,\n> >  \t\tANDROID_CONTROL_AF_MODE_AUTO,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_SCENE_MODE_OVERRIDES,\n> > -\t\t\tsceneModesOverride.data(), sceneModesOverride.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,\n> > +\t\t\t\t  sceneModesOverride.data(),\n> > +\t\t\t\t  sceneModesOverride.size());\n> >\n> >  \tuint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> > -\t\t\t&aeLockAvailable, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> > +\t\t\t\t  &aeLockAvailable, 1);\n> >\n> >  \tuint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> > -\t\t\t&awbLockAvailable, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> > +\t\t\t\t  &awbLockAvailable, 1);\n> >\n> >  \tchar availableControlModes = ANDROID_CONTROL_MODE_AUTO;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_CONTROL_AVAILABLE_MODES,\n> > -\t\t\t&availableControlModes, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,\n> > +\t\t\t\t  &availableControlModes, 1);\n> >\n> >  \t/* JPEG static metadata. */\n> >  \tstd::vector<int32_t> availableThumbnailSizes = {\n> >  \t\t0, 0,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,\n> > -\t\t\tavailableThumbnailSizes.data(),\n> > -\t\t\tavailableThumbnailSizes.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,\n> > +\t\t\t\t  availableThumbnailSizes.data(),\n> > +\t\t\t\t  availableThumbnailSizes.size());\n> >\n> >  \t/* Sensor static metadata. */\n> >  \tint32_t pixelArraySize[] = {\n> >  \t\t2592, 1944,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,\n> > -\t\t\t\t&pixelArraySize, 2);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,\n> > +\t\t\t\t  &pixelArraySize, 2);\n> >\n> >  \tint32_t sensorSizes[] = {\n> >  \t\t0, 0, 2560, 1920,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,\n> > -\t\t\t\t&sensorSizes, 4);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,\n> > +\t\t\t\t  &sensorSizes, 4);\n> >\n> >  \tint32_t sensitivityRange[] = {\n> >  \t\t32, 2400,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_SENSOR_INFO_SENSITIVITY_RANGE,\n> > -\t\t\t\t&sensitivityRange, 2);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,\n> > +\t\t\t\t  &sensitivityRange, 2);\n> >\n> >  \tuint16_t filterArr = ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,\n> > -\t\t\t\t&filterArr, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,\n> > +\t\t\t\t  &filterArr, 1);\n> >\n> >  \tint64_t exposureTimeRange[] = {\n> >  \t\t100000, 200000000,\n> >  \t};\n> \n> I've been thinking for a while to stabilize on the use of std::vector in\n> place of arrays, so e can always use .data() and .size() and have\n> guaranteed we should only change the declaration and not the\n> parameters to the addEntry() operation.\n> \n> This might be a good time to do so. What do you think?\n\nI've thought about it, and constructing a vector is a bit costly\ncompared to arrays. I'd rather used std::array<>, but that requires\nspecifying the size explicitly :-S I've been thinking about overloading\nthe addEntry() method, in order to be able to write\n\n\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n\t\t\t\t  { 100000, 200000000 });\n\nI'm not sure if that will be possible as we need to handle different\ndata types, but I think it's worth a try. Other overloaded methods\nshould also be added for the arrays of a single element:\n\n\tstaticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION, 0);\n\nI would prefer handling the standardisation of vector vs. array in a\nseparate patch, when dealing with overloaded versions of addEntry(), as\nthis patch is big enough already.\n\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> > -\t\t\t\t&exposureTimeRange, 2);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> > +\t\t\t\t  &exposureTimeRange, 2);\n> >\n> >  \tint32_t orientation = 0;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_SENSOR_ORIENTATION,\n> > -\t\t\t\t&orientation, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION,\n> > +\t\t\t\t  &orientation, 1);\n> \n> Fits in 1 line\n\nI've kept it on two lines to use similar constructs through the whole\nfunction, but I don't mind much, so please feel free to change it if you\nprefer.\n\n> >\n> >  \tstd::vector<int32_t> testPatterModes = {\n> >  \t\tANDROID_SENSOR_TEST_PATTERN_MODE_OFF,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,\n> > -\t\t\t\ttestPatterModes.data(), testPatterModes.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,\n> > +\t\t\t\t  testPatterModes.data(),\n> > +\t\t\t\t  testPatterModes.size());\n> >\n> >  \tstd::vector<float> physicalSize = {\n> >  \t\t2592, 1944,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_SENSOR_INFO_PHYSICAL_SIZE,\n> > -\t\t\t\tphysicalSize.data(), physicalSize.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,\n> > +\t\t\t\t  physicalSize.data(),\n> > +\t\t\t\t  physicalSize.size());\n> \n> Fits in 1 line\n> \n> >\n> >  \tuint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,\n> > -\t\t\t&timestampSource, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,\n> > +\t\t\t\t  &timestampSource, 1);\n> >\n> >  \t/* Statistics static metadata. */\n> >  \tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> > -\t\t\t&faceDetectMode, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> > +\t\t\t\t  &faceDetectMode, 1);\n> >\n> >  \tint32_t maxFaceCount = 0;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> > -\t\t\t&maxFaceCount, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> > +\t\t\t\t  &maxFaceCount, 1);\n> >\n> >  \t/* Sync static metadata. */\n> >  \tint32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);\n> >\n> >  \t/* Flash static metadata. */\n> >  \tchar flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_FLASH_INFO_AVAILABLE,\n> > -\t\t\t&flashAvailable, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_FLASH_INFO_AVAILABLE,\n> > +\t\t\t\t  &flashAvailable, 1);\n> >\n> >  \t/* Lens static metadata. */\n> >  \tstd::vector<float> lensApertures = {\n> >  \t\t2.53 / 100,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_APERTURES,\n> > -\t\t\t\tlensApertures.data(), lensApertures.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_APERTURES,\n> > +\t\t\t\t  lensApertures.data(),\n> > +\t\t\t\t  lensApertures.size());\n> >\n> >  \tuint8_t lensFacing = ANDROID_LENS_FACING_FRONT;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_LENS_FACING, &lensFacing, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_LENS_FACING, &lensFacing, 1);\n> >\n> >  \tstd::vector<float> lensFocalLenghts = {\n> >  \t\t1,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,\n> > -\t\t\t\tlensFocalLenghts.data(),\n> > -\t\t\t\tlensFocalLenghts.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,\n> > +\t\t\t\t  lensFocalLenghts.data(),\n> > +\t\t\t\t  lensFocalLenghts.size());\n> >\n> >  \tstd::vector<uint8_t> opticalStabilizations = {\n> >  \t\tANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,\n> > -\t\t\t\topticalStabilizations.data(),\n> > -\t\t\t\topticalStabilizations.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,\n> > +\t\t\t\t  opticalStabilizations.data(),\n> > +\t\t\t\t  opticalStabilizations.size());\n> >\n> >  \tfloat hypeFocalDistance = 0;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,\n> > -\t\t\t\t&hypeFocalDistance, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,\n> > +\t\t\t\t  &hypeFocalDistance, 1);\n> >\n> >  \tfloat minFocusDistance = 0;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,\n> > -\t\t\t\t&minFocusDistance, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,\n> > +\t\t\t\t  &minFocusDistance, 1);\n> >\n> >  \t/* Noise reduction modes. */\n> >  \tuint8_t noiseReductionModes = ANDROID_NOISE_REDUCTION_MODE_OFF;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\t\tANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,\n> > -\t\t\t\t&noiseReductionModes, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,\n> > +\t\t\t\t  &noiseReductionModes, 1);\n> >\n> >  \t/* Scaler static metadata. */\n> >  \tfloat maxDigitalZoom = 1;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,\n> > -\t\t\t&maxDigitalZoom, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,\n> > +\t\t\t\t  &maxDigitalZoom, 1);\n> >\n> >  \tstd::vector<uint32_t> availableStreamFormats = {\n> >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB,\n> >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888,\n> >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_SCALER_AVAILABLE_FORMATS,\n> > -\t\t\tavailableStreamFormats.data(),\n> > -\t\t\tavailableStreamFormats.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_FORMATS,\n> > +\t\t\t\t  availableStreamFormats.data(),\n> > +\t\t\t\t  availableStreamFormats.size());\n> >\n> >  \tstd::vector<uint32_t> availableStreamConfigurations = {\n> >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920,\n> > @@ -447,65 +382,57 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920,\n> >  \t\tANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,\n> > -\t\t\tavailableStreamConfigurations.data(),\n> > -\t\t\tavailableStreamConfigurations.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,\n> > +\t\t\t\t  availableStreamConfigurations.data(),\n> > +\t\t\t\t  availableStreamConfigurations.size());\n> >\n> >  \tstd::vector<int64_t> availableStallDurations = {\n> >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_SCALER_AVAILABLE_STALL_DURATIONS,\n> > -\t\t\tavailableStallDurations.data(),\n> > -\t\t\tavailableStallDurations.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,\n> > +\t\t\t\t  availableStallDurations.data(),\n> > +\t\t\t\t  availableStallDurations.size());\n> >\n> >  \tstd::vector<int64_t> minFrameDurations = {\n> >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,\n> >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920, 33333333,\n> >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888, 2560, 1920, 33333333,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> > -\t\t\tminFrameDurations.data(), minFrameDurations.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> > +\t\t\t\t  minFrameDurations.data(),\n> > +\t\t\t\t  minFrameDurations.size());\n> >\n> >  \tuint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);\n> >\n> >  \t/* Info static metadata. */\n> >  \tuint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> > -\t\t\t&supportedHWLevel, 1);\n> > +\tstaticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> > +\t\t\t\t  &supportedHWLevel, 1);\n> >\n> >  \t/* Request static metadata. */\n> >  \tint32_t partialResultCount = 1;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> > -\t\t\t&partialResultCount, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> > +\t\t\t\t  &partialResultCount, 1);\n> >\n> >  \tuint8_t maxPipelineDepth = 2;\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_REQUEST_PIPELINE_MAX_DEPTH,\n> > -\t\t\t&maxPipelineDepth, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_REQUEST_PIPELINE_MAX_DEPTH,\n> > +\t\t\t\t  &maxPipelineDepth, 1);\n> >\n> >  \tstd::vector<uint8_t> availableCapabilities = {\n> >  \t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > -\t\t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> > -\t\t\tavailableCapabilities.data(),\n> > -\t\t\tavailableCapabilities.size());\n> > -\tMETADATA_ASSERT(ret);\n> > +\tstaticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> > +\t\t\t\t  availableCapabilities.data(),\n> > +\t\t\t\t  availableCapabilities.size());\n> > +\n> > +\tif (!staticMetadata_->isValid()) {\n> > +\t\tdelete staticMetadata_;\n> > +\t\tstaticMetadata_ = nullptr;\n> > +\t\treturn nullptr;\n> > +\t}\n> >\n> > -\treturn staticMetadata_;\n> > +\treturn staticMetadata_->get();\n> >  }\n> >\n> >  /*\n> > @@ -513,8 +440,6 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> >   */\n> >  const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)\n> >  {\n> > -\tint ret;\n> > -\n> >  \t/*\n> >  \t * \\todo Inspect type and pick the right metadata pack.\n> >  \t * As of now just use a single one for all templates.\n> > @@ -545,89 +470,73 @@ const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)\n> >  \t}\n> >\n> >  \tif (requestTemplate_)\n> > -\t\treturn requestTemplate_;\n> > +\t\treturn requestTemplate_->get();\n> >\n> >  \t/*\n> >  \t * \\todo Keep this in sync with the actual number of entries.\n> >  \t * Currently: 12 entries, 15 bytes\n> >  \t */\n> > -\trequestTemplate_ = allocate_camera_metadata(15, 20);\n> > +\trequestTemplate_ = new CameraMetadata(15, 20);\n> >  \tif (!requestTemplate_) {\n> >  \t\tLOG(HAL, Error) << \"Failed to allocate template metadata\";\n> > +\t\tdelete requestTemplate_;\n> > +\t\trequestTemplate_ = nullptr;\n> \n> Empty line before return ?\n> \n> >  \t\treturn nullptr;\n> >  \t}\n> >\n> >  \tuint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;\n> > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > -\t\t\tANDROID_CONTROL_AE_MODE,\n> > -\t\t\t&aeMode, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_MODE,\n> > +\t\t\t\t   &aeMode, 1);\n> \n> This and many others entries here and below fit in 1 line.\n> \n> >\n> >  \tint32_t aeExposureCompensation = 0;\n> > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > -\t\t\tANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,\n> > -\t\t\t&aeExposureCompensation, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,\n> > +\t\t\t\t   &aeExposureCompensation, 1);\n> >\n> >  \tuint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;\n> > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > -\t\t\tANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,\n> > -\t\t\t&aePrecaptureTrigger, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,\n> > +\t\t\t\t   &aePrecaptureTrigger, 1);\n> >\n> >  \tuint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;\n> > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > -\t\t\tANDROID_CONTROL_AE_LOCK,\n> > -\t\t\t&aeLock, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_LOCK,\n> > +\t\t\t\t   &aeLock, 1);\n> >\n> >  \tuint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;\n> > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > -\t\t\tANDROID_CONTROL_AF_TRIGGER,\n> > -\t\t\t&afTrigger, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\trequestTemplate_->addEntry(ANDROID_CONTROL_AF_TRIGGER,\n> > +\t\t\t\t   &afTrigger, 1);\n> >\n> >  \tuint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;\n> > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > -\t\t\tANDROID_CONTROL_AWB_MODE,\n> > -\t\t\t&awbMode, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\trequestTemplate_->addEntry(ANDROID_CONTROL_AWB_MODE,\n> > +\t\t\t\t   &awbMode, 1);\n> >\n> >  \tuint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;\n> > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > -\t\t\tANDROID_CONTROL_AWB_LOCK,\n> > -\t\t\t&awbLock, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\trequestTemplate_->addEntry(ANDROID_CONTROL_AWB_LOCK,\n> > +\t\t\t\t   &awbLock, 1);\n> >\n> >  \tuint8_t flashMode = ANDROID_FLASH_MODE_OFF;\n> > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > -\t\t\tANDROID_FLASH_MODE,\n> > -\t\t\t&flashMode, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\trequestTemplate_->addEntry(ANDROID_FLASH_MODE,\n> > +\t\t\t\t   &flashMode, 1);\n> >\n> >  \tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > -\t\t\tANDROID_STATISTICS_FACE_DETECT_MODE,\n> > -\t\t\t&faceDetectMode, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\trequestTemplate_->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,\n> > +\t\t\t\t   &faceDetectMode, 1);\n> >\n> >  \tuint8_t noiseReduction = ANDROID_NOISE_REDUCTION_MODE_OFF;\n> > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > -\t\t\tANDROID_NOISE_REDUCTION_MODE, &noiseReduction, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\trequestTemplate_->addEntry(ANDROID_NOISE_REDUCTION_MODE,\n> > +\t\t\t\t   &noiseReduction, 1);\n> >\n> >  \tuint8_t aberrationMode = ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF;\n> > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > -\t\t\tANDROID_COLOR_CORRECTION_ABERRATION_MODE,\n> > -\t\t\t&aberrationMode, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\trequestTemplate_->addEntry(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,\n> > +\t\t\t\t   &aberrationMode, 1);\n> > +\n> > +\trequestTemplate_->addEntry(ANDROID_CONTROL_CAPTURE_INTENT,\n> > +\t\t\t\t   &captureIntent, 1);\n> >\n> > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > -\t\t\tANDROID_CONTROL_CAPTURE_INTENT,\n> > -\t\t\t&captureIntent, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tif (!requestTemplate_->isValid()) {\n> > +\t\tdelete requestTemplate_;\n> > +\t\trequestTemplate_ = nullptr;\n> \n> You should return nullptr here, otherwise the below requestTemplate_->get();\n> will de-reference a nullptr.\n\nAbsolutely, my bad.\n\n> > +\t}\n> >\n> > -\treturn requestTemplate_;\n> > +\treturn requestTemplate_->get();\n> >  }\n> >\n> >  /*\n> > @@ -799,7 +708,7 @@ void CameraDevice::requestComplete(Request *request,\n> >  {\n> >  \tBuffer *libcameraBuffer = buffers.begin()->second;\n> >  \tcamera3_buffer_status status = CAMERA3_BUFFER_STATUS_OK;\n> > -\tcamera_metadata_t *resultMetadata = nullptr;\n> > +\tstd::unique_ptr<CameraMetadata> resultMetadata;\n> >\n> >  \tif (request->status() != Request::RequestComplete) {\n> >  \t\tLOG(HAL, Error) << \"Request not succesfully completed: \"\n> > @@ -837,16 +746,12 @@ void CameraDevice::requestComplete(Request *request,\n> >  \t\tcaptureResult.partial_result = 1;\n> >  \t\tresultMetadata = getResultMetadata(descriptor->frameNumber,\n> >  \t\t\t\t\t\t   libcameraBuffer->timestamp());\n> > -\t\tcaptureResult.result = resultMetadata;\n> > +\t\tcaptureResult.result = resultMetadata->get();\n> >  \t}\n> >\n> >  \tcallbacks_->process_capture_result(callbacks_, &captureResult);\n> >\n> >  \tdelete descriptor;\n> > -\tif (resultMetadata)\n> > -\t\tfree_camera_metadata(resultMetadata);\n> > -\n> > -\treturn;\n> >  }\n> >\n> >  void CameraDevice::notifyShutter(uint32_t frameNumber, uint64_t timestamp)\n> > @@ -875,89 +780,63 @@ void CameraDevice::notifyError(uint32_t frameNumber, camera3_stream_t *stream)\n> >  /*\n> >   * Produce a set of fixed result metadata.\n> >   */\n> > -camera_metadata_t *CameraDevice::getResultMetadata(int frame_number,\n> > -\t\t\t\t\t\t   int64_t timestamp)\n> > +std::unique_ptr<CameraMetadata> CameraDevice::getResultMetadata(int frame_number,\n> \n> Not a fan of smart pointers, you know already. How does this work?\n> Because the compiler applies copy-elision or because of the move\n> semantic applied on the return value?\n\nstd::unique_ptr<> has an operator= that takes an rvalue reference to\nanother std::unique_ptr<>, and uses move semantic. As explained in\nhttps://en.cppreference.com/w/cpp/language/value_category, an rvalue is\neither a prvalue or an xvalue, and a prvalue can be \"a function call or\nan overloaded operator expression, whose return type is non-reference\".\nAs far as I can tell, that's why we don't need an std::move() in the\ncaller.\n\n> Anway. it saves 2 lines in the caller but makes the code more\n> difficult to follow in my opinion.\n\nI think we should standardise as much as possible on std::unique_ptr<>\nwhen passing ownership of a returned pointer. That's documented in\nDocumentation/coding-style.rst.\n\n> > +\t\t\t\t\t\t\t\tint64_t timestamp)\n> >  {\n> > -\tint ret;\n> > -\n> >  \t/*\n> >  \t * \\todo Keep this in sync with the actual number of entries.\n> >  \t * Currently: 13 entries, 36 bytes\n> >  \t */\n> > -\tcamera_metadata_t *resultMetadata = allocate_camera_metadata(15, 50);\n> > +\tstd::unique_ptr<CameraMetadata> resultMetadata =\n> > +\t\tutils::make_unique<CameraMetadata>(15, 50);\n> > +\tif (!resultMetadata->isValid()) {\n> > +\t\tLOG(HAL, Error) << \"Failed to allocate static metadata\";\n> > +\t\treturn nullptr;\n> > +\t}\n> >\n> >  \tconst uint8_t ae_state = ANDROID_CONTROL_AE_STATE_CONVERGED;\n> > -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AE_STATE,\n> > -\t\t\t\t\t&ae_state, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tresultMetadata->addEntry(ANDROID_CONTROL_AE_STATE, &ae_state, 1);\n> >\n> >  \tconst uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;\n> > -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AE_LOCK,\n> > -\t\t\t\t\t&ae_lock, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tresultMetadata->addEntry(ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);\n> >\n> >  \tuint8_t af_state = ANDROID_CONTROL_AF_STATE_INACTIVE;\n> > -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AF_STATE,\n> > -\t\t\t\t\t&af_state, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tresultMetadata->addEntry(ANDROID_CONTROL_AF_STATE, &af_state, 1);\n> >\n> >  \tconst uint8_t awb_state = ANDROID_CONTROL_AWB_STATE_CONVERGED;\n> > -\tret = add_camera_metadata_entry(resultMetadata,\n> > -\t\t\t\t\tANDROID_CONTROL_AWB_STATE,\n> > -\t\t\t\t\t&awb_state, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tresultMetadata->addEntry(ANDROID_CONTROL_AWB_STATE, &awb_state, 1);\n> >\n> >  \tconst uint8_t awb_lock = ANDROID_CONTROL_AWB_LOCK_OFF;\n> > -\tret = add_camera_metadata_entry(resultMetadata,\n> > -\t\t\t\t\tANDROID_CONTROL_AWB_LOCK,\n> > -\t\t\t\t\t&awb_lock, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tresultMetadata->addEntry(ANDROID_CONTROL_AWB_LOCK, &awb_lock, 1);\n> >\n> >  \tconst uint8_t lens_state = ANDROID_LENS_STATE_STATIONARY;\n> > -\tret = add_camera_metadata_entry(resultMetadata,\n> > -\t\t\t\t\tANDROID_LENS_STATE,\n> > -\t\t\t\t\t&lens_state, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tresultMetadata->addEntry(ANDROID_LENS_STATE, &lens_state, 1);\n> >\n> >  \tint32_t sensorSizes[] = {\n> >  \t\t0, 0, 2560, 1920,\n> >  \t};\n> > -\tret = add_camera_metadata_entry(resultMetadata,\n> > -\t\t\t\t\tANDROID_SCALER_CROP_REGION,\n> > -\t\t\t\t\tsensorSizes, 4);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tresultMetadata->addEntry(ANDROID_SCALER_CROP_REGION, sensorSizes, 4);\n> >\n> > -\tret = add_camera_metadata_entry(resultMetadata,\n> > -\t\t\t\t\tANDROID_SENSOR_TIMESTAMP,\n> > -\t\t\t\t\t&timestamp, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tresultMetadata->addEntry(ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);\n> >\n> >  \t/* 33.3 msec */\n> >  \tconst int64_t rolling_shutter_skew = 33300000;\n> > -\tret = add_camera_metadata_entry(resultMetadata,\n> > -\t\t\t\t\tANDROID_SENSOR_ROLLING_SHUTTER_SKEW,\n> > -\t\t\t\t\t&rolling_shutter_skew, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tresultMetadata->addEntry(ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,\n> > +\t\t\t\t &rolling_shutter_skew, 1);\n> >\n> >  \t/* 16.6 msec */\n> >  \tconst int64_t exposure_time = 16600000;\n> > -\tret = add_camera_metadata_entry(resultMetadata,\n> > -\t\t\t\t\tANDROID_SENSOR_EXPOSURE_TIME,\n> > -\t\t\t\t\t&exposure_time, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tresultMetadata->addEntry(ANDROID_SENSOR_EXPOSURE_TIME,\n> > +\t\t\t\t &exposure_time, 1);\n> >\n> >  \tconst uint8_t lens_shading_map_mode =\n> >  \t\t\t\tANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;\n> > -\tret = add_camera_metadata_entry(resultMetadata,\n> > -\t\t\t\t\tANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> > -\t\t\t\t\t&lens_shading_map_mode, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tresultMetadata->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> > +\t\t\t\t &lens_shading_map_mode, 1);\n> >\n> >  \tconst uint8_t scene_flicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE;\n> > -\tret = add_camera_metadata_entry(resultMetadata,\n> > -\t\t\t\t\tANDROID_STATISTICS_SCENE_FLICKER,\n> > -\t\t\t\t\t&scene_flicker, 1);\n> > -\tMETADATA_ASSERT(ret);\n> > +\tresultMetadata->addEntry(ANDROID_STATISTICS_SCENE_FLICKER,\n> > +\t\t\t\t &scene_flicker, 1);\n> \n> Shouldn't you check if the metadata pack is valid ?\n\nGood point. Should we check here or in the caller ? As the caller would\nthen need a nullptr check I'm tempted to do so in the caller. Actually,\nwithout a change to the code, the caller will operate correctly I\nbelieve\n\n                resultMetadata = getResultMetadata(descriptor->frameNumber,\n                                                   libcameraBuffer->timestamp());\n                captureResult.result = resultMetadata->get();\n\nwhich will set captureResult.result to nullptr if resultMetadata is not\nvalid.\n\n> >\n> >  \treturn resultMetadata;\n> >  }\n> > diff --git a/src/android/camera_device.h b/src/android/camera_device.h\n> > index 7897ba9dc5c7..65ba877a02ea 100644\n> > --- a/src/android/camera_device.h\n> > +++ b/src/android/camera_device.h\n> > @@ -19,13 +19,7 @@\n> >\n> >  #include \"message.h\"\n> >\n> > -#define METADATA_ASSERT(_r)\t\t\\\n> > -\tdo {\t\t\t\t\\\n> > -\t\tif (!(_r)) break;\t\\\n> > -\t\tLOG(HAL, Error) << \"Error: \" << __func__ << \":\" << __LINE__; \\\n> > -\t\treturn nullptr;\t\t\\\n> > -\t} while(0);\n> > -\n> > +class CameraMetadata;\n> >  class ThreadRpc;\n> >\n> >  class CameraDevice : public libcamera::Object\n> > @@ -59,14 +53,15 @@ private:\n> >\n> >  \tvoid notifyShutter(uint32_t frameNumber, uint64_t timestamp);\n> >  \tvoid notifyError(uint32_t frameNumber, camera3_stream_t *stream);\n> > -\tcamera_metadata_t *getResultMetadata(int frame_number, int64_t timestamp);\n> > +\tstd::unique_ptr<CameraMetadata> getResultMetadata(int frame_number,\n> > +\t\t\t\t\t\t\t  int64_t timestamp);\n> >\n> >  \tbool running_;\n> >  \tstd::shared_ptr<libcamera::Camera> camera_;\n> >  \tstd::unique_ptr<libcamera::CameraConfiguration> config_;\n> >\n> > -\tcamera_metadata_t *staticMetadata_;\n> > -\tcamera_metadata_t *requestTemplate_;\n> > +\tCameraMetadata *staticMetadata_;\n> > +\tCameraMetadata *requestTemplate_;\n> >  \tconst camera3_callback_ops_t *callbacks_;\n> >  };\n> >","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C6AE960BD9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 Sep 2019 11:37:04 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(dfj612yhrgyx302h3jwwy-3.rev.dnainternet.fi\n\t[IPv6:2001:14ba:21f5:5b00:ce28:277f:58d7:3ca4])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 29C9026D;\n\tThu,  5 Sep 2019 11:37:04 +0200 (CEST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1567676224;\n\tbh=bzXsNyP3iXZOttNpC7le1pQFiVCRphlyuovrER71vpw=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=omkT4DOroNkhblJw83+ZkjKbPFg2+8VNkEVdBqlaQtwWpzYRQjxApwywK2auu4MjC\n\tkixBpgxXykCn1DScjif3dt/Oh4l+ZGkiYYbCh/HYfV5ONg+yGdVH6qdK3CxEEDnyRs\n\tzNdn9kKleJaM/r17K5qQ4Kqe6jT81nne+CJDQe7s=","Date":"Thu, 5 Sep 2019 12:36:57 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190905093657.GA5035@pendragon.ideasonboard.com>","References":"<20190905074737.6955-1-jacopo@jmondi.org>\n\t<20190905074737.6955-8-jacopo@jmondi.org>\n\t<20190905081828.y647dyfqg2apejjp@uno.localdomain>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20190905081828.y647dyfqg2apejjp@uno.localdomain>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH v6 7/9] android: camera_device: Use\n\tthe new CameraMetadata helper class","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Thu, 05 Sep 2019 09:37:05 -0000"}},{"id":2619,"web_url":"https://patchwork.libcamera.org/comment/2619/","msgid":"<20190905095205.333n5sof5rjimsaf@uno.localdomain>","date":"2019-09-05T09:52:05","subject":"Re: [libcamera-devel] [PATCH v6 7/9] android: camera_device: Use\n\tthe new CameraMetadata helper class","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Laurent,\n\nOn Thu, Sep 05, 2019 at 12:36:57PM +0300, Laurent Pinchart wrote:\n> Hi Jacopo,\n>\n> On Thu, Sep 05, 2019 at 10:18:28AM +0200, Jacopo Mondi wrote:\n> > On Thu, Sep 05, 2019 at 09:47:34AM +0200, Jacopo Mondi wrote:\n> > > From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > >\n> > > Simplify the implementation of metadata handling in the CameraDevice\n> > > class by using the new CameraMetadata helper class.\n> > >\n> > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > > ---\n> > >  src/android/camera_device.cpp | 507 +++++++++++++---------------------\n> > >  src/android/camera_device.h   |  15 +-\n> > >  2 files changed, 198 insertions(+), 324 deletions(-)\n> > >\n> > > diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n> > > index 5f8d19b9ef3d..475fa2404421 100644\n> > > --- a/src/android/camera_device.cpp\n> > > +++ b/src/android/camera_device.cpp\n> > > @@ -7,10 +7,10 @@\n> > >\n> > >  #include \"camera_device.h\"\n> > >\n> > > -#include <system/camera_metadata.h>\n> > > -\n> > >  #include \"log.h\"\n> > > +#include \"utils.h\"\n> > >\n> > > +#include \"camera_metadata.h\"\n> > >  #include \"thread_rpc.h\"\n> > >\n> > >  using namespace libcamera;\n> > > @@ -59,12 +59,10 @@ CameraDevice::CameraDevice(unsigned int id, const std::shared_ptr<Camera> &camer\n> > >  CameraDevice::~CameraDevice()\n> > >  {\n> > >  \tif (staticMetadata_)\n> > > -\t\tfree_camera_metadata(staticMetadata_);\n> > > -\tstaticMetadata_ = nullptr;\n> > > +\t\tdelete staticMetadata_;\n> > >\n> > >  \tif (requestTemplate_)\n> > > -\t\tfree_camera_metadata(requestTemplate_);\n> > > -\trequestTemplate_ = nullptr;\n> > > +\t\tdelete requestTemplate_;\n> > >  }\n> > >\n> > >  /*\n> > > @@ -117,10 +115,8 @@ void CameraDevice::setCallbacks(const camera3_callback_ops_t *callbacks)\n> > >   */\n> > >  camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >  {\n> > > -\tint ret;\n> > > -\n> > >  \tif (staticMetadata_)\n> > > -\t\treturn staticMetadata_;\n> > > +\t\treturn staticMetadata_->get();\n> > >\n> > >  \t/*\n> > >  \t * The here reported metadata are enough to implement a basic capture\n> > > @@ -132,16 +128,21 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >  \t * \\todo Keep this in sync with the actual number of entries.\n> > >  \t * Currently: 46 entries, 390 bytes\n> > >  \t */\n> > > -\tstaticMetadata_ = allocate_camera_metadata(50, 500);\n> > > +\tstaticMetadata_ = new CameraMetadata(50, 500);\n> > > +\tif (!staticMetadata_->isValid()) {\n> > > +\t\tLOG(HAL, Error) << \"Failed to allocate static metadata\";\n> > > +\t\tdelete staticMetadata_;\n> > > +\t\tstaticMetadata_ = nullptr;\n> > > +\t\treturn nullptr;\n> >\n> > Empty line before return?\n>\n> I don't mind either way, but I haven't added one as the delete,\n> assignment to nullptr and return nullptr are logically grouped in my\n> opinion. Feel free to add a blank line if you prefer.\n>\n\nOk, if this was intentional let's keep it the way it is.\n\n> > > +\t}\n> > >\n> > >  \t/* Color correction static metadata. */\n> > >  \tstd::vector<uint8_t> aberrationModes = {\n> > >  \t\tANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> > > -\t\t\taberrationModes.data(), aberrationModes.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> > > +\t\t\t\t  aberrationModes.data(),\n> > > +\t\t\t\t  aberrationModes.size());\n> > >\n> > >  \t/* Control static metadata. */\n> > >  \tstd::vector<uint8_t> aeAvailableAntiBandingModes = {\n> > > @@ -150,294 +151,228 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >  \t\tANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,\n> > >  \t\tANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,\n> > > -\t\t\taeAvailableAntiBandingModes.data(),\n> > > -\t\t\taeAvailableAntiBandingModes.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,\n> > > +\t\t\t\t  aeAvailableAntiBandingModes.data(),\n> > > +\t\t\t\t  aeAvailableAntiBandingModes.size());\n> > >\n> > >  \tstd::vector<uint8_t> aeAvailableModes = {\n> > >  \t\tANDROID_CONTROL_AE_MODE_ON,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_AE_AVAILABLE_MODES,\n> > > -\t\t\taeAvailableModes.data(), aeAvailableModes.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,\n> > > +\t\t\t\t  aeAvailableModes.data(),\n> > > +\t\t\t\t  aeAvailableModes.size());\n> > >\n> > >  \tstd::vector<int32_t> availableAeFpsTarget = {\n> > >  \t\t15, 30,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> > > -\t\t\tavailableAeFpsTarget.data(),\n> > > -\t\t\tavailableAeFpsTarget.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> > > +\t\t\t\t  availableAeFpsTarget.data(),\n> > > +\t\t\t\t  availableAeFpsTarget.size());\n> > >\n> > >  \tstd::vector<int32_t> aeCompensationRange = {\n> > >  \t\t0, 0,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_AE_COMPENSATION_RANGE,\n> > > -\t\t\taeCompensationRange.data(),\n> > > -\t\t\taeCompensationRange.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_RANGE,\n> > > +\t\t\t\t  aeCompensationRange.data(),\n> > > +\t\t\t\t  aeCompensationRange.size());\n> > >\n> > >  \tconst camera_metadata_rational_t aeCompensationStep[] = {\n> > >  \t\t{ 0, 1 }\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_AE_COMPENSATION_STEP,\n> > > -\t\t\taeCompensationStep, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_STEP,\n> > > +\t\t\t\t  aeCompensationStep, 1);\n> > >\n> > >  \tstd::vector<uint8_t> availableAfModes = {\n> > >  \t\tANDROID_CONTROL_AF_MODE_OFF,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_AF_AVAILABLE_MODES,\n> > > -\t\t\tavailableAfModes.data(), availableAfModes.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AF_AVAILABLE_MODES,\n> > > +\t\t\t\t  availableAfModes.data(),\n> > > +\t\t\t\t  availableAfModes.size());\n> > >\n> > >  \tstd::vector<uint8_t> availableEffects = {\n> > >  \t\tANDROID_CONTROL_EFFECT_MODE_OFF,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_AVAILABLE_EFFECTS,\n> > > -\t\t\tavailableEffects.data(), availableEffects.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_EFFECTS,\n> > > +\t\t\t\t  availableEffects.data(),\n> > > +\t\t\t\t  availableEffects.size());\n> > >\n> > >  \tstd::vector<uint8_t> availableSceneModes = {\n> > >  \t\tANDROID_CONTROL_SCENE_MODE_DISABLED,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_AVAILABLE_SCENE_MODES,\n> > > -\t\t\tavailableSceneModes.data(), availableSceneModes.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,\n> > > +\t\t\t\t  availableSceneModes.data(),\n> > > +\t\t\t\t  availableSceneModes.size());\n> > >\n> > >  \tstd::vector<uint8_t> availableStabilizationModes = {\n> > >  \t\tANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,\n> > > -\t\t\tavailableStabilizationModes.data(),\n> > > -\t\t\tavailableStabilizationModes.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,\n> > > +\t\t\t\t  availableStabilizationModes.data(),\n> > > +\t\t\t\t  availableStabilizationModes.size());\n> > >\n> > >  \tstd::vector<uint8_t> availableAwbModes = {\n> > >  \t\tANDROID_CONTROL_AWB_MODE_OFF,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> > > -\t\t\tavailableAwbModes.data(), availableAwbModes.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> > > +\t\t\t\t  availableAwbModes.data(),\n> > > +\t\t\t\t  availableAwbModes.size());\n> > >\n> > >  \tstd::vector<int32_t> availableMaxRegions = {\n> > >  \t\t0, 0, 0,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_MAX_REGIONS,\n> > > -\t\t\tavailableMaxRegions.data(), availableMaxRegions.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_MAX_REGIONS,\n> > > +\t\t\t\t  availableMaxRegions.data(),\n> > > +\t\t\t\t  availableMaxRegions.size());\n> > >\n> > >  \tstd::vector<uint8_t> sceneModesOverride = {\n> > >  \t\tANDROID_CONTROL_AE_MODE_ON,\n> > >  \t\tANDROID_CONTROL_AWB_MODE_AUTO,\n> > >  \t\tANDROID_CONTROL_AF_MODE_AUTO,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_SCENE_MODE_OVERRIDES,\n> > > -\t\t\tsceneModesOverride.data(), sceneModesOverride.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,\n> > > +\t\t\t\t  sceneModesOverride.data(),\n> > > +\t\t\t\t  sceneModesOverride.size());\n> > >\n> > >  \tuint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> > > -\t\t\t&aeLockAvailable, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> > > +\t\t\t\t  &aeLockAvailable, 1);\n> > >\n> > >  \tuint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> > > -\t\t\t&awbLockAvailable, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> > > +\t\t\t\t  &awbLockAvailable, 1);\n> > >\n> > >  \tchar availableControlModes = ANDROID_CONTROL_MODE_AUTO;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_CONTROL_AVAILABLE_MODES,\n> > > -\t\t\t&availableControlModes, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,\n> > > +\t\t\t\t  &availableControlModes, 1);\n> > >\n> > >  \t/* JPEG static metadata. */\n> > >  \tstd::vector<int32_t> availableThumbnailSizes = {\n> > >  \t\t0, 0,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,\n> > > -\t\t\tavailableThumbnailSizes.data(),\n> > > -\t\t\tavailableThumbnailSizes.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,\n> > > +\t\t\t\t  availableThumbnailSizes.data(),\n> > > +\t\t\t\t  availableThumbnailSizes.size());\n> > >\n> > >  \t/* Sensor static metadata. */\n> > >  \tint32_t pixelArraySize[] = {\n> > >  \t\t2592, 1944,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,\n> > > -\t\t\t\t&pixelArraySize, 2);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,\n> > > +\t\t\t\t  &pixelArraySize, 2);\n> > >\n> > >  \tint32_t sensorSizes[] = {\n> > >  \t\t0, 0, 2560, 1920,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,\n> > > -\t\t\t\t&sensorSizes, 4);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,\n> > > +\t\t\t\t  &sensorSizes, 4);\n> > >\n> > >  \tint32_t sensitivityRange[] = {\n> > >  \t\t32, 2400,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_SENSOR_INFO_SENSITIVITY_RANGE,\n> > > -\t\t\t\t&sensitivityRange, 2);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,\n> > > +\t\t\t\t  &sensitivityRange, 2);\n> > >\n> > >  \tuint16_t filterArr = ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,\n> > > -\t\t\t\t&filterArr, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,\n> > > +\t\t\t\t  &filterArr, 1);\n> > >\n> > >  \tint64_t exposureTimeRange[] = {\n> > >  \t\t100000, 200000000,\n> > >  \t};\n> >\n> > I've been thinking for a while to stabilize on the use of std::vector in\n> > place of arrays, so e can always use .data() and .size() and have\n> > guaranteed we should only change the declaration and not the\n> > parameters to the addEntry() operation.\n> >\n> > This might be a good time to do so. What do you think?\n>\n> I've thought about it, and constructing a vector is a bit costly\n> compared to arrays. I'd rather used std::array<>, but that requires\n> specifying the size explicitly :-S I've been thinking about overloading\n> the addEntry() method, in order to be able to write\n>\n> \tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> \t\t\t\t  { 100000, 200000000 });\n>\n> I'm not sure if that will be possible as we need to handle different\n> data types, but I think it's worth a try. Other overloaded methods\n> should also be added for the arrays of a single element:\n>\n> \tstaticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION, 0);\n>\n> I would prefer handling the standardisation of vector vs. array in a\n> separate patch, when dealing with overloaded versions of addEntry(), as\n> this patch is big enough already.\n>\n\nAgreed\n\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> > > -\t\t\t\t&exposureTimeRange, 2);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> > > +\t\t\t\t  &exposureTimeRange, 2);\n> > >\n> > >  \tint32_t orientation = 0;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_SENSOR_ORIENTATION,\n> > > -\t\t\t\t&orientation, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION,\n> > > +\t\t\t\t  &orientation, 1);\n> >\n> > Fits in 1 line\n>\n> I've kept it on two lines to use similar constructs through the whole\n> function, but I don't mind much, so please feel free to change it if you\n> prefer.\n>\n\nIf it was intentional, let's keep it the way it is\n\n> > >\n> > >  \tstd::vector<int32_t> testPatterModes = {\n> > >  \t\tANDROID_SENSOR_TEST_PATTERN_MODE_OFF,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,\n> > > -\t\t\t\ttestPatterModes.data(), testPatterModes.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,\n> > > +\t\t\t\t  testPatterModes.data(),\n> > > +\t\t\t\t  testPatterModes.size());\n> > >\n> > >  \tstd::vector<float> physicalSize = {\n> > >  \t\t2592, 1944,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_SENSOR_INFO_PHYSICAL_SIZE,\n> > > -\t\t\t\tphysicalSize.data(), physicalSize.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,\n> > > +\t\t\t\t  physicalSize.data(),\n> > > +\t\t\t\t  physicalSize.size());\n> >\n> > Fits in 1 line\n> >\n> > >\n> > >  \tuint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,\n> > > -\t\t\t&timestampSource, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,\n> > > +\t\t\t\t  &timestampSource, 1);\n> > >\n> > >  \t/* Statistics static metadata. */\n> > >  \tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> > > -\t\t\t&faceDetectMode, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> > > +\t\t\t\t  &faceDetectMode, 1);\n> > >\n> > >  \tint32_t maxFaceCount = 0;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> > > -\t\t\t&maxFaceCount, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> > > +\t\t\t\t  &maxFaceCount, 1);\n> > >\n> > >  \t/* Sync static metadata. */\n> > >  \tint32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);\n> > >\n> > >  \t/* Flash static metadata. */\n> > >  \tchar flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_FLASH_INFO_AVAILABLE,\n> > > -\t\t\t&flashAvailable, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_FLASH_INFO_AVAILABLE,\n> > > +\t\t\t\t  &flashAvailable, 1);\n> > >\n> > >  \t/* Lens static metadata. */\n> > >  \tstd::vector<float> lensApertures = {\n> > >  \t\t2.53 / 100,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_APERTURES,\n> > > -\t\t\t\tlensApertures.data(), lensApertures.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_APERTURES,\n> > > +\t\t\t\t  lensApertures.data(),\n> > > +\t\t\t\t  lensApertures.size());\n> > >\n> > >  \tuint8_t lensFacing = ANDROID_LENS_FACING_FRONT;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_LENS_FACING, &lensFacing, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_LENS_FACING, &lensFacing, 1);\n> > >\n> > >  \tstd::vector<float> lensFocalLenghts = {\n> > >  \t\t1,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,\n> > > -\t\t\t\tlensFocalLenghts.data(),\n> > > -\t\t\t\tlensFocalLenghts.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,\n> > > +\t\t\t\t  lensFocalLenghts.data(),\n> > > +\t\t\t\t  lensFocalLenghts.size());\n> > >\n> > >  \tstd::vector<uint8_t> opticalStabilizations = {\n> > >  \t\tANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,\n> > > -\t\t\t\topticalStabilizations.data(),\n> > > -\t\t\t\topticalStabilizations.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,\n> > > +\t\t\t\t  opticalStabilizations.data(),\n> > > +\t\t\t\t  opticalStabilizations.size());\n> > >\n> > >  \tfloat hypeFocalDistance = 0;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,\n> > > -\t\t\t\t&hypeFocalDistance, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,\n> > > +\t\t\t\t  &hypeFocalDistance, 1);\n> > >\n> > >  \tfloat minFocusDistance = 0;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,\n> > > -\t\t\t\t&minFocusDistance, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,\n> > > +\t\t\t\t  &minFocusDistance, 1);\n> > >\n> > >  \t/* Noise reduction modes. */\n> > >  \tuint8_t noiseReductionModes = ANDROID_NOISE_REDUCTION_MODE_OFF;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\t\tANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,\n> > > -\t\t\t\t&noiseReductionModes, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,\n> > > +\t\t\t\t  &noiseReductionModes, 1);\n> > >\n> > >  \t/* Scaler static metadata. */\n> > >  \tfloat maxDigitalZoom = 1;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,\n> > > -\t\t\t&maxDigitalZoom, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,\n> > > +\t\t\t\t  &maxDigitalZoom, 1);\n> > >\n> > >  \tstd::vector<uint32_t> availableStreamFormats = {\n> > >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB,\n> > >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888,\n> > >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_SCALER_AVAILABLE_FORMATS,\n> > > -\t\t\tavailableStreamFormats.data(),\n> > > -\t\t\tavailableStreamFormats.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_FORMATS,\n> > > +\t\t\t\t  availableStreamFormats.data(),\n> > > +\t\t\t\t  availableStreamFormats.size());\n> > >\n> > >  \tstd::vector<uint32_t> availableStreamConfigurations = {\n> > >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920,\n> > > @@ -447,65 +382,57 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920,\n> > >  \t\tANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,\n> > > -\t\t\tavailableStreamConfigurations.data(),\n> > > -\t\t\tavailableStreamConfigurations.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,\n> > > +\t\t\t\t  availableStreamConfigurations.data(),\n> > > +\t\t\t\t  availableStreamConfigurations.size());\n> > >\n> > >  \tstd::vector<int64_t> availableStallDurations = {\n> > >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_SCALER_AVAILABLE_STALL_DURATIONS,\n> > > -\t\t\tavailableStallDurations.data(),\n> > > -\t\t\tavailableStallDurations.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,\n> > > +\t\t\t\t  availableStallDurations.data(),\n> > > +\t\t\t\t  availableStallDurations.size());\n> > >\n> > >  \tstd::vector<int64_t> minFrameDurations = {\n> > >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,\n> > >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920, 33333333,\n> > >  \t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888, 2560, 1920, 33333333,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> > > -\t\t\tminFrameDurations.data(), minFrameDurations.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> > > +\t\t\t\t  minFrameDurations.data(),\n> > > +\t\t\t\t  minFrameDurations.size());\n> > >\n> > >  \tuint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);\n> > >\n> > >  \t/* Info static metadata. */\n> > >  \tuint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> > > -\t\t\t&supportedHWLevel, 1);\n> > > +\tstaticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> > > +\t\t\t\t  &supportedHWLevel, 1);\n> > >\n> > >  \t/* Request static metadata. */\n> > >  \tint32_t partialResultCount = 1;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> > > -\t\t\t&partialResultCount, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> > > +\t\t\t\t  &partialResultCount, 1);\n> > >\n> > >  \tuint8_t maxPipelineDepth = 2;\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_REQUEST_PIPELINE_MAX_DEPTH,\n> > > -\t\t\t&maxPipelineDepth, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_REQUEST_PIPELINE_MAX_DEPTH,\n> > > +\t\t\t\t  &maxPipelineDepth, 1);\n> > >\n> > >  \tstd::vector<uint8_t> availableCapabilities = {\n> > >  \t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(staticMetadata_,\n> > > -\t\t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> > > -\t\t\tavailableCapabilities.data(),\n> > > -\t\t\tavailableCapabilities.size());\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tstaticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> > > +\t\t\t\t  availableCapabilities.data(),\n> > > +\t\t\t\t  availableCapabilities.size());\n> > > +\n> > > +\tif (!staticMetadata_->isValid()) {\n> > > +\t\tdelete staticMetadata_;\n> > > +\t\tstaticMetadata_ = nullptr;\n> > > +\t\treturn nullptr;\n> > > +\t}\n> > >\n> > > -\treturn staticMetadata_;\n> > > +\treturn staticMetadata_->get();\n> > >  }\n> > >\n> > >  /*\n> > > @@ -513,8 +440,6 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >   */\n> > >  const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)\n> > >  {\n> > > -\tint ret;\n> > > -\n> > >  \t/*\n> > >  \t * \\todo Inspect type and pick the right metadata pack.\n> > >  \t * As of now just use a single one for all templates.\n> > > @@ -545,89 +470,73 @@ const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)\n> > >  \t}\n> > >\n> > >  \tif (requestTemplate_)\n> > > -\t\treturn requestTemplate_;\n> > > +\t\treturn requestTemplate_->get();\n> > >\n> > >  \t/*\n> > >  \t * \\todo Keep this in sync with the actual number of entries.\n> > >  \t * Currently: 12 entries, 15 bytes\n> > >  \t */\n> > > -\trequestTemplate_ = allocate_camera_metadata(15, 20);\n> > > +\trequestTemplate_ = new CameraMetadata(15, 20);\n> > >  \tif (!requestTemplate_) {\n> > >  \t\tLOG(HAL, Error) << \"Failed to allocate template metadata\";\n> > > +\t\tdelete requestTemplate_;\n> > > +\t\trequestTemplate_ = nullptr;\n> >\n> > Empty line before return ?\n> >\n> > >  \t\treturn nullptr;\n> > >  \t}\n> > >\n> > >  \tuint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;\n> > > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > > -\t\t\tANDROID_CONTROL_AE_MODE,\n> > > -\t\t\t&aeMode, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_MODE,\n> > > +\t\t\t\t   &aeMode, 1);\n> >\n> > This and many others entries here and below fit in 1 line.\n> >\n> > >\n> > >  \tint32_t aeExposureCompensation = 0;\n> > > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > > -\t\t\tANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,\n> > > -\t\t\t&aeExposureCompensation, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,\n> > > +\t\t\t\t   &aeExposureCompensation, 1);\n> > >\n> > >  \tuint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;\n> > > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > > -\t\t\tANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,\n> > > -\t\t\t&aePrecaptureTrigger, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,\n> > > +\t\t\t\t   &aePrecaptureTrigger, 1);\n> > >\n> > >  \tuint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;\n> > > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > > -\t\t\tANDROID_CONTROL_AE_LOCK,\n> > > -\t\t\t&aeLock, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_LOCK,\n> > > +\t\t\t\t   &aeLock, 1);\n> > >\n> > >  \tuint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;\n> > > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > > -\t\t\tANDROID_CONTROL_AF_TRIGGER,\n> > > -\t\t\t&afTrigger, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\trequestTemplate_->addEntry(ANDROID_CONTROL_AF_TRIGGER,\n> > > +\t\t\t\t   &afTrigger, 1);\n> > >\n> > >  \tuint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;\n> > > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > > -\t\t\tANDROID_CONTROL_AWB_MODE,\n> > > -\t\t\t&awbMode, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\trequestTemplate_->addEntry(ANDROID_CONTROL_AWB_MODE,\n> > > +\t\t\t\t   &awbMode, 1);\n> > >\n> > >  \tuint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;\n> > > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > > -\t\t\tANDROID_CONTROL_AWB_LOCK,\n> > > -\t\t\t&awbLock, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\trequestTemplate_->addEntry(ANDROID_CONTROL_AWB_LOCK,\n> > > +\t\t\t\t   &awbLock, 1);\n> > >\n> > >  \tuint8_t flashMode = ANDROID_FLASH_MODE_OFF;\n> > > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > > -\t\t\tANDROID_FLASH_MODE,\n> > > -\t\t\t&flashMode, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\trequestTemplate_->addEntry(ANDROID_FLASH_MODE,\n> > > +\t\t\t\t   &flashMode, 1);\n> > >\n> > >  \tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > > -\t\t\tANDROID_STATISTICS_FACE_DETECT_MODE,\n> > > -\t\t\t&faceDetectMode, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\trequestTemplate_->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,\n> > > +\t\t\t\t   &faceDetectMode, 1);\n> > >\n> > >  \tuint8_t noiseReduction = ANDROID_NOISE_REDUCTION_MODE_OFF;\n> > > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > > -\t\t\tANDROID_NOISE_REDUCTION_MODE, &noiseReduction, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\trequestTemplate_->addEntry(ANDROID_NOISE_REDUCTION_MODE,\n> > > +\t\t\t\t   &noiseReduction, 1);\n> > >\n> > >  \tuint8_t aberrationMode = ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF;\n> > > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > > -\t\t\tANDROID_COLOR_CORRECTION_ABERRATION_MODE,\n> > > -\t\t\t&aberrationMode, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\trequestTemplate_->addEntry(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,\n> > > +\t\t\t\t   &aberrationMode, 1);\n> > > +\n> > > +\trequestTemplate_->addEntry(ANDROID_CONTROL_CAPTURE_INTENT,\n> > > +\t\t\t\t   &captureIntent, 1);\n> > >\n> > > -\tret = add_camera_metadata_entry(requestTemplate_,\n> > > -\t\t\tANDROID_CONTROL_CAPTURE_INTENT,\n> > > -\t\t\t&captureIntent, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tif (!requestTemplate_->isValid()) {\n> > > +\t\tdelete requestTemplate_;\n> > > +\t\trequestTemplate_ = nullptr;\n> >\n> > You should return nullptr here, otherwise the below requestTemplate_->get();\n> > will de-reference a nullptr.\n>\n> Absolutely, my bad.\n>\n> > > +\t}\n> > >\n> > > -\treturn requestTemplate_;\n> > > +\treturn requestTemplate_->get();\n> > >  }\n> > >\n> > >  /*\n> > > @@ -799,7 +708,7 @@ void CameraDevice::requestComplete(Request *request,\n> > >  {\n> > >  \tBuffer *libcameraBuffer = buffers.begin()->second;\n> > >  \tcamera3_buffer_status status = CAMERA3_BUFFER_STATUS_OK;\n> > > -\tcamera_metadata_t *resultMetadata = nullptr;\n> > > +\tstd::unique_ptr<CameraMetadata> resultMetadata;\n> > >\n> > >  \tif (request->status() != Request::RequestComplete) {\n> > >  \t\tLOG(HAL, Error) << \"Request not succesfully completed: \"\n> > > @@ -837,16 +746,12 @@ void CameraDevice::requestComplete(Request *request,\n> > >  \t\tcaptureResult.partial_result = 1;\n> > >  \t\tresultMetadata = getResultMetadata(descriptor->frameNumber,\n> > >  \t\t\t\t\t\t   libcameraBuffer->timestamp());\n> > > -\t\tcaptureResult.result = resultMetadata;\n> > > +\t\tcaptureResult.result = resultMetadata->get();\n> > >  \t}\n> > >\n> > >  \tcallbacks_->process_capture_result(callbacks_, &captureResult);\n> > >\n> > >  \tdelete descriptor;\n> > > -\tif (resultMetadata)\n> > > -\t\tfree_camera_metadata(resultMetadata);\n> > > -\n> > > -\treturn;\n> > >  }\n> > >\n> > >  void CameraDevice::notifyShutter(uint32_t frameNumber, uint64_t timestamp)\n> > > @@ -875,89 +780,63 @@ void CameraDevice::notifyError(uint32_t frameNumber, camera3_stream_t *stream)\n> > >  /*\n> > >   * Produce a set of fixed result metadata.\n> > >   */\n> > > -camera_metadata_t *CameraDevice::getResultMetadata(int frame_number,\n> > > -\t\t\t\t\t\t   int64_t timestamp)\n> > > +std::unique_ptr<CameraMetadata> CameraDevice::getResultMetadata(int frame_number,\n> >\n> > Not a fan of smart pointers, you know already. How does this work?\n> > Because the compiler applies copy-elision or because of the move\n> > semantic applied on the return value?\n>\n> std::unique_ptr<> has an operator= that takes an rvalue reference to\n> another std::unique_ptr<>, and uses move semantic. As explained in\n> https://en.cppreference.com/w/cpp/language/value_category, an rvalue is\n> either a prvalue or an xvalue, and a prvalue can be \"a function call or\n> an overloaded operator expression, whose return type is non-reference\".\n> As far as I can tell, that's why we don't need an std::move() in the\n> caller.\n>\n\nI see.. This seems to suggest both RVO and move semantic can play a\nrole https://stackoverflow.com/a/46571941\n\nAh, c++\n\n> > difficult to follow in my opinion.\n>\n> I think we should standardise as much as possible on std::unique_ptr<>\n> when passing ownership of a returned pointer. That's documented in\n> Documentation/coding-style.rst.\n>\n\nAck, let's keep it the way it is then.\n\n> > > +\t\t\t\t\t\t\t\tint64_t timestamp)\n> > >  {\n> > > -\tint ret;\n> > > -\n> > >  \t/*\n> > >  \t * \\todo Keep this in sync with the actual number of entries.\n> > >  \t * Currently: 13 entries, 36 bytes\n> > >  \t */\n> > > -\tcamera_metadata_t *resultMetadata = allocate_camera_metadata(15, 50);\n> > > +\tstd::unique_ptr<CameraMetadata> resultMetadata =\n> > > +\t\tutils::make_unique<CameraMetadata>(15, 50);\n> > > +\tif (!resultMetadata->isValid()) {\n> > > +\t\tLOG(HAL, Error) << \"Failed to allocate static metadata\";\n> > > +\t\treturn nullptr;\n> > > +\t}\n> > >\n> > >  \tconst uint8_t ae_state = ANDROID_CONTROL_AE_STATE_CONVERGED;\n> > > -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AE_STATE,\n> > > -\t\t\t\t\t&ae_state, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tresultMetadata->addEntry(ANDROID_CONTROL_AE_STATE, &ae_state, 1);\n> > >\n> > >  \tconst uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;\n> > > -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AE_LOCK,\n> > > -\t\t\t\t\t&ae_lock, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tresultMetadata->addEntry(ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);\n> > >\n> > >  \tuint8_t af_state = ANDROID_CONTROL_AF_STATE_INACTIVE;\n> > > -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AF_STATE,\n> > > -\t\t\t\t\t&af_state, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tresultMetadata->addEntry(ANDROID_CONTROL_AF_STATE, &af_state, 1);\n> > >\n> > >  \tconst uint8_t awb_state = ANDROID_CONTROL_AWB_STATE_CONVERGED;\n> > > -\tret = add_camera_metadata_entry(resultMetadata,\n> > > -\t\t\t\t\tANDROID_CONTROL_AWB_STATE,\n> > > -\t\t\t\t\t&awb_state, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tresultMetadata->addEntry(ANDROID_CONTROL_AWB_STATE, &awb_state, 1);\n> > >\n> > >  \tconst uint8_t awb_lock = ANDROID_CONTROL_AWB_LOCK_OFF;\n> > > -\tret = add_camera_metadata_entry(resultMetadata,\n> > > -\t\t\t\t\tANDROID_CONTROL_AWB_LOCK,\n> > > -\t\t\t\t\t&awb_lock, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tresultMetadata->addEntry(ANDROID_CONTROL_AWB_LOCK, &awb_lock, 1);\n> > >\n> > >  \tconst uint8_t lens_state = ANDROID_LENS_STATE_STATIONARY;\n> > > -\tret = add_camera_metadata_entry(resultMetadata,\n> > > -\t\t\t\t\tANDROID_LENS_STATE,\n> > > -\t\t\t\t\t&lens_state, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tresultMetadata->addEntry(ANDROID_LENS_STATE, &lens_state, 1);\n> > >\n> > >  \tint32_t sensorSizes[] = {\n> > >  \t\t0, 0, 2560, 1920,\n> > >  \t};\n> > > -\tret = add_camera_metadata_entry(resultMetadata,\n> > > -\t\t\t\t\tANDROID_SCALER_CROP_REGION,\n> > > -\t\t\t\t\tsensorSizes, 4);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tresultMetadata->addEntry(ANDROID_SCALER_CROP_REGION, sensorSizes, 4);\n> > >\n> > > -\tret = add_camera_metadata_entry(resultMetadata,\n> > > -\t\t\t\t\tANDROID_SENSOR_TIMESTAMP,\n> > > -\t\t\t\t\t&timestamp, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tresultMetadata->addEntry(ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);\n> > >\n> > >  \t/* 33.3 msec */\n> > >  \tconst int64_t rolling_shutter_skew = 33300000;\n> > > -\tret = add_camera_metadata_entry(resultMetadata,\n> > > -\t\t\t\t\tANDROID_SENSOR_ROLLING_SHUTTER_SKEW,\n> > > -\t\t\t\t\t&rolling_shutter_skew, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tresultMetadata->addEntry(ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,\n> > > +\t\t\t\t &rolling_shutter_skew, 1);\n> > >\n> > >  \t/* 16.6 msec */\n> > >  \tconst int64_t exposure_time = 16600000;\n> > > -\tret = add_camera_metadata_entry(resultMetadata,\n> > > -\t\t\t\t\tANDROID_SENSOR_EXPOSURE_TIME,\n> > > -\t\t\t\t\t&exposure_time, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tresultMetadata->addEntry(ANDROID_SENSOR_EXPOSURE_TIME,\n> > > +\t\t\t\t &exposure_time, 1);\n> > >\n> > >  \tconst uint8_t lens_shading_map_mode =\n> > >  \t\t\t\tANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;\n> > > -\tret = add_camera_metadata_entry(resultMetadata,\n> > > -\t\t\t\t\tANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> > > -\t\t\t\t\t&lens_shading_map_mode, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tresultMetadata->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> > > +\t\t\t\t &lens_shading_map_mode, 1);\n> > >\n> > >  \tconst uint8_t scene_flicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE;\n> > > -\tret = add_camera_metadata_entry(resultMetadata,\n> > > -\t\t\t\t\tANDROID_STATISTICS_SCENE_FLICKER,\n> > > -\t\t\t\t\t&scene_flicker, 1);\n> > > -\tMETADATA_ASSERT(ret);\n> > > +\tresultMetadata->addEntry(ANDROID_STATISTICS_SCENE_FLICKER,\n> > > +\t\t\t\t &scene_flicker, 1);\n> >\n> > Shouldn't you check if the metadata pack is valid ?\n>\n> Good point. Should we check here or in the caller ? As the caller would\n> then need a nullptr check I'm tempted to do so in the caller. Actually,\n> without a change to the code, the caller will operate correctly I\n> believe\n>\n>                 resultMetadata = getResultMetadata(descriptor->frameNumber,\n>                                                    libcameraBuffer->timestamp());\n>                 captureResult.result = resultMetadata->get();\n>\n> which will set captureResult.result to nullptr if resultMetadata is not\n> valid.\n\nYeah, but in that case we should notify an error back to the stack.\n\nWhat about:\n\n        resultMetadata = getResultMetadata(descriptor->frameNumber,\n                                           libcameraBuffer->timestamp());\n\tif (status == CAMERA3_BUFFER_STATUS_ERROR || !resultMetadata) {\n\t\t/* \\todo Improve error handling. */\n\t\tnotifyError(descriptor->frameNumber,\n\t\t\t    descriptor->buffers[0].stream);\n\t} else {\n\t\tnotifyShutter(descriptor->frameNumber,\n\t\t\t      libcameraBuffer->timestamp());\n\n\t\tcaptureResult.partial_result = 1;\n\t\tcaptureResult.result = resultMetadata->get();\n\t}\n\nThe drawback is that we're generating the result metadata even if\nstatus is set to CAMERA3_BUFFER_STATUS_ERROR.\n\nThanks\n   j\n\n> > >\n> > >  \treturn resultMetadata;\n> > >  }\n> > > diff --git a/src/android/camera_device.h b/src/android/camera_device.h\n> > > index 7897ba9dc5c7..65ba877a02ea 100644\n> > > --- a/src/android/camera_device.h\n> > > +++ b/src/android/camera_device.h\n> > > @@ -19,13 +19,7 @@\n> > >\n> > >  #include \"message.h\"\n> > >\n> > > -#define METADATA_ASSERT(_r)\t\t\\\n> > > -\tdo {\t\t\t\t\\\n> > > -\t\tif (!(_r)) break;\t\\\n> > > -\t\tLOG(HAL, Error) << \"Error: \" << __func__ << \":\" << __LINE__; \\\n> > > -\t\treturn nullptr;\t\t\\\n> > > -\t} while(0);\n> > > -\n> > > +class CameraMetadata;\n> > >  class ThreadRpc;\n> > >\n> > >  class CameraDevice : public libcamera::Object\n> > > @@ -59,14 +53,15 @@ private:\n> > >\n> > >  \tvoid notifyShutter(uint32_t frameNumber, uint64_t timestamp);\n> > >  \tvoid notifyError(uint32_t frameNumber, camera3_stream_t *stream);\n> > > -\tcamera_metadata_t *getResultMetadata(int frame_number, int64_t timestamp);\n> > > +\tstd::unique_ptr<CameraMetadata> getResultMetadata(int frame_number,\n> > > +\t\t\t\t\t\t\t  int64_t timestamp);\n> > >\n> > >  \tbool running_;\n> > >  \tstd::shared_ptr<libcamera::Camera> camera_;\n> > >  \tstd::unique_ptr<libcamera::CameraConfiguration> config_;\n> > >\n> > > -\tcamera_metadata_t *staticMetadata_;\n> > > -\tcamera_metadata_t *requestTemplate_;\n> > > +\tCameraMetadata *staticMetadata_;\n> > > +\tCameraMetadata *requestTemplate_;\n> > >  \tconst camera3_callback_ops_t *callbacks_;\n> > >  };\n> > >\n>\n> --\n> Regards,\n>\n> Laurent Pinchart","headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay12.mail.gandi.net (relay12.mail.gandi.net\n\t[217.70.178.232])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 16C1860C18\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 Sep 2019 11:50:38 +0200 (CEST)","from uno.localdomain (2-224-242-101.ip172.fastwebnet.it\n\t[2.224.242.101]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay12.mail.gandi.net (Postfix) with ESMTPSA id 14116200019;\n\tThu,  5 Sep 2019 09:50:36 +0000 (UTC)"],"Date":"Thu, 5 Sep 2019 11:52:05 +0200","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190905095205.333n5sof5rjimsaf@uno.localdomain>","References":"<20190905074737.6955-1-jacopo@jmondi.org>\n\t<20190905074737.6955-8-jacopo@jmondi.org>\n\t<20190905081828.y647dyfqg2apejjp@uno.localdomain>\n\t<20190905093657.GA5035@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Type":"multipart/signed; micalg=pgp-sha256;\n\tprotocol=\"application/pgp-signature\"; boundary=\"yj4tetyqswbnn3y3\"","Content-Disposition":"inline","In-Reply-To":"<20190905093657.GA5035@pendragon.ideasonboard.com>","User-Agent":"NeoMutt/20180716","Subject":"Re: [libcamera-devel] [PATCH v6 7/9] android: camera_device: Use\n\tthe new CameraMetadata helper class","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Thu, 05 Sep 2019 09:50:38 -0000"}},{"id":2620,"web_url":"https://patchwork.libcamera.org/comment/2620/","msgid":"<20190905100259.GE5035@pendragon.ideasonboard.com>","date":"2019-09-05T10:02:59","subject":"Re: [libcamera-devel] [PATCH v6 7/9] android: camera_device: Use\n\tthe new CameraMetadata helper class","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nThank you for the patch.\n\nOn Thu, Sep 05, 2019 at 11:52:05AM +0200, Jacopo Mondi wrote:\n> On Thu, Sep 05, 2019 at 12:36:57PM +0300, Laurent Pinchart wrote:\n> > On Thu, Sep 05, 2019 at 10:18:28AM +0200, Jacopo Mondi wrote:\n> >> On Thu, Sep 05, 2019 at 09:47:34AM +0200, Jacopo Mondi wrote:\n> >>> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> >>>\n> >>> Simplify the implementation of metadata handling in the CameraDevice\n> >>> class by using the new CameraMetadata helper class.\n> >>>\n> >>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> >>> ---\n> >>>  src/android/camera_device.cpp | 507 +++++++++++++---------------------\n> >>>  src/android/camera_device.h   |  15 +-\n> >>>  2 files changed, 198 insertions(+), 324 deletions(-)\n> >>>\n> >>> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n> >>> index 5f8d19b9ef3d..475fa2404421 100644\n> >>> --- a/src/android/camera_device.cpp\n> >>> +++ b/src/android/camera_device.cpp\n> >>> @@ -7,10 +7,10 @@\n> >>>\n> >>>  #include \"camera_device.h\"\n> >>>\n> >>> -#include <system/camera_metadata.h>\n> >>> -\n> >>>  #include \"log.h\"\n> >>> +#include \"utils.h\"\n> >>>\n> >>> +#include \"camera_metadata.h\"\n> >>>  #include \"thread_rpc.h\"\n> >>>\n> >>>  using namespace libcamera;\n> >>> @@ -59,12 +59,10 @@ CameraDevice::CameraDevice(unsigned int id, const std::shared_ptr<Camera> &camer\n> >>>  CameraDevice::~CameraDevice()\n> >>>  {\n> >>>  \tif (staticMetadata_)\n> >>> -\t\tfree_camera_metadata(staticMetadata_);\n> >>> -\tstaticMetadata_ = nullptr;\n> >>> +\t\tdelete staticMetadata_;\n> >>>\n> >>>  \tif (requestTemplate_)\n> >>> -\t\tfree_camera_metadata(requestTemplate_);\n> >>> -\trequestTemplate_ = nullptr;\n> >>> +\t\tdelete requestTemplate_;\n> >>>  }\n> >>>\n> >>>  /*\n> >>> @@ -117,10 +115,8 @@ void CameraDevice::setCallbacks(const camera3_callback_ops_t *callbacks)\n> >>>   */\n> >>>  camera_metadata_t *CameraDevice::getStaticMetadata()\n> >>>  {\n> >>> -\tint ret;\n> >>> -\n> >>>  \tif (staticMetadata_)\n> >>> -\t\treturn staticMetadata_;\n> >>> +\t\treturn staticMetadata_->get();\n> >>>\n> >>>  \t/*\n> >>>  \t * The here reported metadata are enough to implement a basic capture\n> >>> @@ -132,16 +128,21 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> >>>  \t * \\todo Keep this in sync with the actual number of entries.\n> >>>  \t * Currently: 46 entries, 390 bytes\n> >>>  \t */\n> >>> -\tstaticMetadata_ = allocate_camera_metadata(50, 500);\n> >>> +\tstaticMetadata_ = new CameraMetadata(50, 500);\n> >>> +\tif (!staticMetadata_->isValid()) {\n> >>> +\t\tLOG(HAL, Error) << \"Failed to allocate static metadata\";\n> >>> +\t\tdelete staticMetadata_;\n> >>> +\t\tstaticMetadata_ = nullptr;\n> >>> +\t\treturn nullptr;\n> >>\n> >> Empty line before return?\n> >\n> > I don't mind either way, but I haven't added one as the delete,\n> > assignment to nullptr and return nullptr are logically grouped in my\n> > opinion. Feel free to add a blank line if you prefer.\n> \n> Ok, if this was intentional let's keep it the way it is.\n> \n> >>> +\t}\n> >>>\n> >>>  \t/* Color correction static metadata. */\n> >>>  \tstd::vector<uint8_t> aberrationModes = {\n> >>>  \t\tANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> >>> -\t\t\taberrationModes.data(), aberrationModes.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> >>> +\t\t\t\t  aberrationModes.data(),\n> >>> +\t\t\t\t  aberrationModes.size());\n> >>>\n> >>>  \t/* Control static metadata. */\n> >>>  \tstd::vector<uint8_t> aeAvailableAntiBandingModes = {\n> >>> @@ -150,294 +151,228 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> >>>  \t\tANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,\n> >>>  \t\tANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,\n> >>> -\t\t\taeAvailableAntiBandingModes.data(),\n> >>> -\t\t\taeAvailableAntiBandingModes.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,\n> >>> +\t\t\t\t  aeAvailableAntiBandingModes.data(),\n> >>> +\t\t\t\t  aeAvailableAntiBandingModes.size());\n> >>>\n> >>>  \tstd::vector<uint8_t> aeAvailableModes = {\n> >>>  \t\tANDROID_CONTROL_AE_MODE_ON,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_MODES,\n> >>> -\t\t\taeAvailableModes.data(), aeAvailableModes.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,\n> >>> +\t\t\t\t  aeAvailableModes.data(),\n> >>> +\t\t\t\t  aeAvailableModes.size());\n> >>>\n> >>>  \tstd::vector<int32_t> availableAeFpsTarget = {\n> >>>  \t\t15, 30,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> >>> -\t\t\tavailableAeFpsTarget.data(),\n> >>> -\t\t\tavailableAeFpsTarget.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> >>> +\t\t\t\t  availableAeFpsTarget.data(),\n> >>> +\t\t\t\t  availableAeFpsTarget.size());\n> >>>\n> >>>  \tstd::vector<int32_t> aeCompensationRange = {\n> >>>  \t\t0, 0,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_AE_COMPENSATION_RANGE,\n> >>> -\t\t\taeCompensationRange.data(),\n> >>> -\t\t\taeCompensationRange.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_RANGE,\n> >>> +\t\t\t\t  aeCompensationRange.data(),\n> >>> +\t\t\t\t  aeCompensationRange.size());\n> >>>\n> >>>  \tconst camera_metadata_rational_t aeCompensationStep[] = {\n> >>>  \t\t{ 0, 1 }\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_AE_COMPENSATION_STEP,\n> >>> -\t\t\taeCompensationStep, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_STEP,\n> >>> +\t\t\t\t  aeCompensationStep, 1);\n> >>>\n> >>>  \tstd::vector<uint8_t> availableAfModes = {\n> >>>  \t\tANDROID_CONTROL_AF_MODE_OFF,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_AF_AVAILABLE_MODES,\n> >>> -\t\t\tavailableAfModes.data(), availableAfModes.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AF_AVAILABLE_MODES,\n> >>> +\t\t\t\t  availableAfModes.data(),\n> >>> +\t\t\t\t  availableAfModes.size());\n> >>>\n> >>>  \tstd::vector<uint8_t> availableEffects = {\n> >>>  \t\tANDROID_CONTROL_EFFECT_MODE_OFF,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_AVAILABLE_EFFECTS,\n> >>> -\t\t\tavailableEffects.data(), availableEffects.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_EFFECTS,\n> >>> +\t\t\t\t  availableEffects.data(),\n> >>> +\t\t\t\t  availableEffects.size());\n> >>>\n> >>>  \tstd::vector<uint8_t> availableSceneModes = {\n> >>>  \t\tANDROID_CONTROL_SCENE_MODE_DISABLED,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_AVAILABLE_SCENE_MODES,\n> >>> -\t\t\tavailableSceneModes.data(), availableSceneModes.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,\n> >>> +\t\t\t\t  availableSceneModes.data(),\n> >>> +\t\t\t\t  availableSceneModes.size());\n> >>>\n> >>>  \tstd::vector<uint8_t> availableStabilizationModes = {\n> >>>  \t\tANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,\n> >>> -\t\t\tavailableStabilizationModes.data(),\n> >>> -\t\t\tavailableStabilizationModes.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,\n> >>> +\t\t\t\t  availableStabilizationModes.data(),\n> >>> +\t\t\t\t  availableStabilizationModes.size());\n> >>>\n> >>>  \tstd::vector<uint8_t> availableAwbModes = {\n> >>>  \t\tANDROID_CONTROL_AWB_MODE_OFF,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> >>> -\t\t\tavailableAwbModes.data(), availableAwbModes.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> >>> +\t\t\t\t  availableAwbModes.data(),\n> >>> +\t\t\t\t  availableAwbModes.size());\n> >>>\n> >>>  \tstd::vector<int32_t> availableMaxRegions = {\n> >>>  \t\t0, 0, 0,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_MAX_REGIONS,\n> >>> -\t\t\tavailableMaxRegions.data(), availableMaxRegions.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_MAX_REGIONS,\n> >>> +\t\t\t\t  availableMaxRegions.data(),\n> >>> +\t\t\t\t  availableMaxRegions.size());\n> >>>\n> >>>  \tstd::vector<uint8_t> sceneModesOverride = {\n> >>>  \t\tANDROID_CONTROL_AE_MODE_ON,\n> >>>  \t\tANDROID_CONTROL_AWB_MODE_AUTO,\n> >>>  \t\tANDROID_CONTROL_AF_MODE_AUTO,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_SCENE_MODE_OVERRIDES,\n> >>> -\t\t\tsceneModesOverride.data(), sceneModesOverride.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,\n> >>> +\t\t\t\t  sceneModesOverride.data(),\n> >>> +\t\t\t\t  sceneModesOverride.size());\n> >>>\n> >>>  \tuint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> >>> -\t\t\t&aeLockAvailable, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> >>> +\t\t\t\t  &aeLockAvailable, 1);\n> >>>\n> >>>  \tuint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> >>> -\t\t\t&awbLockAvailable, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> >>> +\t\t\t\t  &awbLockAvailable, 1);\n> >>>\n> >>>  \tchar availableControlModes = ANDROID_CONTROL_MODE_AUTO;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_CONTROL_AVAILABLE_MODES,\n> >>> -\t\t\t&availableControlModes, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,\n> >>> +\t\t\t\t  &availableControlModes, 1);\n> >>>\n> >>>  \t/* JPEG static metadata. */\n> >>>  \tstd::vector<int32_t> availableThumbnailSizes = {\n> >>>  \t\t0, 0,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,\n> >>> -\t\t\tavailableThumbnailSizes.data(),\n> >>> -\t\t\tavailableThumbnailSizes.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,\n> >>> +\t\t\t\t  availableThumbnailSizes.data(),\n> >>> +\t\t\t\t  availableThumbnailSizes.size());\n> >>>\n> >>>  \t/* Sensor static metadata. */\n> >>>  \tint32_t pixelArraySize[] = {\n> >>>  \t\t2592, 1944,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,\n> >>> -\t\t\t\t&pixelArraySize, 2);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,\n> >>> +\t\t\t\t  &pixelArraySize, 2);\n> >>>\n> >>>  \tint32_t sensorSizes[] = {\n> >>>  \t\t0, 0, 2560, 1920,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,\n> >>> -\t\t\t\t&sensorSizes, 4);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,\n> >>> +\t\t\t\t  &sensorSizes, 4);\n> >>>\n> >>>  \tint32_t sensitivityRange[] = {\n> >>>  \t\t32, 2400,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_SENSOR_INFO_SENSITIVITY_RANGE,\n> >>> -\t\t\t\t&sensitivityRange, 2);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,\n> >>> +\t\t\t\t  &sensitivityRange, 2);\n> >>>\n> >>>  \tuint16_t filterArr = ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,\n> >>> -\t\t\t\t&filterArr, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,\n> >>> +\t\t\t\t  &filterArr, 1);\n> >>>\n> >>>  \tint64_t exposureTimeRange[] = {\n> >>>  \t\t100000, 200000000,\n> >>>  \t};\n> >>\n> >> I've been thinking for a while to stabilize on the use of std::vector in\n> >> place of arrays, so e can always use .data() and .size() and have\n> >> guaranteed we should only change the declaration and not the\n> >> parameters to the addEntry() operation.\n> >>\n> >> This might be a good time to do so. What do you think?\n> >\n> > I've thought about it, and constructing a vector is a bit costly\n> > compared to arrays. I'd rather used std::array<>, but that requires\n> > specifying the size explicitly :-S I've been thinking about overloading\n> > the addEntry() method, in order to be able to write\n> >\n> > \tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> > \t\t\t\t  { 100000, 200000000 });\n> >\n> > I'm not sure if that will be possible as we need to handle different\n> > data types, but I think it's worth a try. Other overloaded methods\n> > should also be added for the arrays of a single element:\n> >\n> > \tstaticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION, 0);\n> >\n> > I would prefer handling the standardisation of vector vs. array in a\n> > separate patch, when dealing with overloaded versions of addEntry(), as\n> > this patch is big enough already.\n> \n> Agreed\n> \n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> >>> -\t\t\t\t&exposureTimeRange, 2);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> >>> +\t\t\t\t  &exposureTimeRange, 2);\n> >>>\n> >>>  \tint32_t orientation = 0;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_SENSOR_ORIENTATION,\n> >>> -\t\t\t\t&orientation, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION,\n> >>> +\t\t\t\t  &orientation, 1);\n> >>\n> >> Fits in 1 line\n> >\n> > I've kept it on two lines to use similar constructs through the whole\n> > function, but I don't mind much, so please feel free to change it if you\n> > prefer.\n> \n> If it was intentional, let's keep it the way it is\n> \n> >>>\n> >>>  \tstd::vector<int32_t> testPatterModes = {\n> >>>  \t\tANDROID_SENSOR_TEST_PATTERN_MODE_OFF,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,\n> >>> -\t\t\t\ttestPatterModes.data(), testPatterModes.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,\n> >>> +\t\t\t\t  testPatterModes.data(),\n> >>> +\t\t\t\t  testPatterModes.size());\n> >>>\n> >>>  \tstd::vector<float> physicalSize = {\n> >>>  \t\t2592, 1944,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_SENSOR_INFO_PHYSICAL_SIZE,\n> >>> -\t\t\t\tphysicalSize.data(), physicalSize.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,\n> >>> +\t\t\t\t  physicalSize.data(),\n> >>> +\t\t\t\t  physicalSize.size());\n> >>\n> >> Fits in 1 line\n> >>\n> >>>\n> >>>  \tuint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,\n> >>> -\t\t\t&timestampSource, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,\n> >>> +\t\t\t\t  &timestampSource, 1);\n> >>>\n> >>>  \t/* Statistics static metadata. */\n> >>>  \tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> >>> -\t\t\t&faceDetectMode, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> >>> +\t\t\t\t  &faceDetectMode, 1);\n> >>>\n> >>>  \tint32_t maxFaceCount = 0;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> >>> -\t\t\t&maxFaceCount, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> >>> +\t\t\t\t  &maxFaceCount, 1);\n> >>>\n> >>>  \t/* Sync static metadata. */\n> >>>  \tint32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);\n> >>>\n> >>>  \t/* Flash static metadata. */\n> >>>  \tchar flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_FLASH_INFO_AVAILABLE,\n> >>> -\t\t\t&flashAvailable, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_FLASH_INFO_AVAILABLE,\n> >>> +\t\t\t\t  &flashAvailable, 1);\n> >>>\n> >>>  \t/* Lens static metadata. */\n> >>>  \tstd::vector<float> lensApertures = {\n> >>>  \t\t2.53 / 100,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_APERTURES,\n> >>> -\t\t\t\tlensApertures.data(), lensApertures.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_APERTURES,\n> >>> +\t\t\t\t  lensApertures.data(),\n> >>> +\t\t\t\t  lensApertures.size());\n> >>>\n> >>>  \tuint8_t lensFacing = ANDROID_LENS_FACING_FRONT;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_LENS_FACING, &lensFacing, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_LENS_FACING, &lensFacing, 1);\n> >>>\n> >>>  \tstd::vector<float> lensFocalLenghts = {\n> >>>  \t\t1,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,\n> >>> -\t\t\t\tlensFocalLenghts.data(),\n> >>> -\t\t\t\tlensFocalLenghts.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,\n> >>> +\t\t\t\t  lensFocalLenghts.data(),\n> >>> +\t\t\t\t  lensFocalLenghts.size());\n> >>>\n> >>>  \tstd::vector<uint8_t> opticalStabilizations = {\n> >>>  \t\tANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,\n> >>> -\t\t\t\topticalStabilizations.data(),\n> >>> -\t\t\t\topticalStabilizations.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,\n> >>> +\t\t\t\t  opticalStabilizations.data(),\n> >>> +\t\t\t\t  opticalStabilizations.size());\n> >>>\n> >>>  \tfloat hypeFocalDistance = 0;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,\n> >>> -\t\t\t\t&hypeFocalDistance, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,\n> >>> +\t\t\t\t  &hypeFocalDistance, 1);\n> >>>\n> >>>  \tfloat minFocusDistance = 0;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,\n> >>> -\t\t\t\t&minFocusDistance, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,\n> >>> +\t\t\t\t  &minFocusDistance, 1);\n> >>>\n> >>>  \t/* Noise reduction modes. */\n> >>>  \tuint8_t noiseReductionModes = ANDROID_NOISE_REDUCTION_MODE_OFF;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\t\tANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,\n> >>> -\t\t\t\t&noiseReductionModes, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,\n> >>> +\t\t\t\t  &noiseReductionModes, 1);\n> >>>\n> >>>  \t/* Scaler static metadata. */\n> >>>  \tfloat maxDigitalZoom = 1;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,\n> >>> -\t\t\t&maxDigitalZoom, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,\n> >>> +\t\t\t\t  &maxDigitalZoom, 1);\n> >>>\n> >>>  \tstd::vector<uint32_t> availableStreamFormats = {\n> >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB,\n> >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888,\n> >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_SCALER_AVAILABLE_FORMATS,\n> >>> -\t\t\tavailableStreamFormats.data(),\n> >>> -\t\t\tavailableStreamFormats.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_FORMATS,\n> >>> +\t\t\t\t  availableStreamFormats.data(),\n> >>> +\t\t\t\t  availableStreamFormats.size());\n> >>>\n> >>>  \tstd::vector<uint32_t> availableStreamConfigurations = {\n> >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920,\n> >>> @@ -447,65 +382,57 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920,\n> >>>  \t\tANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,\n> >>> -\t\t\tavailableStreamConfigurations.data(),\n> >>> -\t\t\tavailableStreamConfigurations.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,\n> >>> +\t\t\t\t  availableStreamConfigurations.data(),\n> >>> +\t\t\t\t  availableStreamConfigurations.size());\n> >>>\n> >>>  \tstd::vector<int64_t> availableStallDurations = {\n> >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_SCALER_AVAILABLE_STALL_DURATIONS,\n> >>> -\t\t\tavailableStallDurations.data(),\n> >>> -\t\t\tavailableStallDurations.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,\n> >>> +\t\t\t\t  availableStallDurations.data(),\n> >>> +\t\t\t\t  availableStallDurations.size());\n> >>>\n> >>>  \tstd::vector<int64_t> minFrameDurations = {\n> >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,\n> >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920, 33333333,\n> >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888, 2560, 1920, 33333333,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> >>> -\t\t\tminFrameDurations.data(), minFrameDurations.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> >>> +\t\t\t\t  minFrameDurations.data(),\n> >>> +\t\t\t\t  minFrameDurations.size());\n> >>>\n> >>>  \tuint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);\n> >>>\n> >>>  \t/* Info static metadata. */\n> >>>  \tuint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> >>> -\t\t\t&supportedHWLevel, 1);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> >>> +\t\t\t\t  &supportedHWLevel, 1);\n> >>>\n> >>>  \t/* Request static metadata. */\n> >>>  \tint32_t partialResultCount = 1;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> >>> -\t\t\t&partialResultCount, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> >>> +\t\t\t\t  &partialResultCount, 1);\n> >>>\n> >>>  \tuint8_t maxPipelineDepth = 2;\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_REQUEST_PIPELINE_MAX_DEPTH,\n> >>> -\t\t\t&maxPipelineDepth, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_PIPELINE_MAX_DEPTH,\n> >>> +\t\t\t\t  &maxPipelineDepth, 1);\n> >>>\n> >>>  \tstd::vector<uint8_t> availableCapabilities = {\n> >>>  \t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>> -\t\t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> >>> -\t\t\tavailableCapabilities.data(),\n> >>> -\t\t\tavailableCapabilities.size());\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> >>> +\t\t\t\t  availableCapabilities.data(),\n> >>> +\t\t\t\t  availableCapabilities.size());\n> >>> +\n> >>> +\tif (!staticMetadata_->isValid()) {\n> >>> +\t\tdelete staticMetadata_;\n> >>> +\t\tstaticMetadata_ = nullptr;\n> >>> +\t\treturn nullptr;\n> >>> +\t}\n> >>>\n> >>> -\treturn staticMetadata_;\n> >>> +\treturn staticMetadata_->get();\n> >>>  }\n> >>>\n> >>>  /*\n> >>> @@ -513,8 +440,6 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> >>>   */\n> >>>  const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)\n> >>>  {\n> >>> -\tint ret;\n> >>> -\n> >>>  \t/*\n> >>>  \t * \\todo Inspect type and pick the right metadata pack.\n> >>>  \t * As of now just use a single one for all templates.\n> >>> @@ -545,89 +470,73 @@ const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)\n> >>>  \t}\n> >>>\n> >>>  \tif (requestTemplate_)\n> >>> -\t\treturn requestTemplate_;\n> >>> +\t\treturn requestTemplate_->get();\n> >>>\n> >>>  \t/*\n> >>>  \t * \\todo Keep this in sync with the actual number of entries.\n> >>>  \t * Currently: 12 entries, 15 bytes\n> >>>  \t */\n> >>> -\trequestTemplate_ = allocate_camera_metadata(15, 20);\n> >>> +\trequestTemplate_ = new CameraMetadata(15, 20);\n> >>>  \tif (!requestTemplate_) {\n> >>>  \t\tLOG(HAL, Error) << \"Failed to allocate template metadata\";\n> >>> +\t\tdelete requestTemplate_;\n> >>> +\t\trequestTemplate_ = nullptr;\n> >>\n> >> Empty line before return ?\n> >>\n> >>>  \t\treturn nullptr;\n> >>>  \t}\n> >>>\n> >>>  \tuint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;\n> >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>> -\t\t\tANDROID_CONTROL_AE_MODE,\n> >>> -\t\t\t&aeMode, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_MODE,\n> >>> +\t\t\t\t   &aeMode, 1);\n> >>\n> >> This and many others entries here and below fit in 1 line.\n> >>\n> >>>\n> >>>  \tint32_t aeExposureCompensation = 0;\n> >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>> -\t\t\tANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,\n> >>> -\t\t\t&aeExposureCompensation, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,\n> >>> +\t\t\t\t   &aeExposureCompensation, 1);\n> >>>\n> >>>  \tuint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;\n> >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>> -\t\t\tANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,\n> >>> -\t\t\t&aePrecaptureTrigger, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,\n> >>> +\t\t\t\t   &aePrecaptureTrigger, 1);\n> >>>\n> >>>  \tuint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;\n> >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>> -\t\t\tANDROID_CONTROL_AE_LOCK,\n> >>> -\t\t\t&aeLock, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_LOCK,\n> >>> +\t\t\t\t   &aeLock, 1);\n> >>>\n> >>>  \tuint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;\n> >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>> -\t\t\tANDROID_CONTROL_AF_TRIGGER,\n> >>> -\t\t\t&afTrigger, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AF_TRIGGER,\n> >>> +\t\t\t\t   &afTrigger, 1);\n> >>>\n> >>>  \tuint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;\n> >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>> -\t\t\tANDROID_CONTROL_AWB_MODE,\n> >>> -\t\t\t&awbMode, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AWB_MODE,\n> >>> +\t\t\t\t   &awbMode, 1);\n> >>>\n> >>>  \tuint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;\n> >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>> -\t\t\tANDROID_CONTROL_AWB_LOCK,\n> >>> -\t\t\t&awbLock, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AWB_LOCK,\n> >>> +\t\t\t\t   &awbLock, 1);\n> >>>\n> >>>  \tuint8_t flashMode = ANDROID_FLASH_MODE_OFF;\n> >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>> -\t\t\tANDROID_FLASH_MODE,\n> >>> -\t\t\t&flashMode, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\trequestTemplate_->addEntry(ANDROID_FLASH_MODE,\n> >>> +\t\t\t\t   &flashMode, 1);\n> >>>\n> >>>  \tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>> -\t\t\tANDROID_STATISTICS_FACE_DETECT_MODE,\n> >>> -\t\t\t&faceDetectMode, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\trequestTemplate_->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,\n> >>> +\t\t\t\t   &faceDetectMode, 1);\n> >>>\n> >>>  \tuint8_t noiseReduction = ANDROID_NOISE_REDUCTION_MODE_OFF;\n> >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>> -\t\t\tANDROID_NOISE_REDUCTION_MODE, &noiseReduction, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\trequestTemplate_->addEntry(ANDROID_NOISE_REDUCTION_MODE,\n> >>> +\t\t\t\t   &noiseReduction, 1);\n> >>>\n> >>>  \tuint8_t aberrationMode = ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF;\n> >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>> -\t\t\tANDROID_COLOR_CORRECTION_ABERRATION_MODE,\n> >>> -\t\t\t&aberrationMode, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\trequestTemplate_->addEntry(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,\n> >>> +\t\t\t\t   &aberrationMode, 1);\n> >>> +\n> >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_CAPTURE_INTENT,\n> >>> +\t\t\t\t   &captureIntent, 1);\n> >>>\n> >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>> -\t\t\tANDROID_CONTROL_CAPTURE_INTENT,\n> >>> -\t\t\t&captureIntent, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tif (!requestTemplate_->isValid()) {\n> >>> +\t\tdelete requestTemplate_;\n> >>> +\t\trequestTemplate_ = nullptr;\n> >>\n> >> You should return nullptr here, otherwise the below requestTemplate_->get();\n> >> will de-reference a nullptr.\n> >\n> > Absolutely, my bad.\n> >\n> >>> +\t}\n> >>>\n> >>> -\treturn requestTemplate_;\n> >>> +\treturn requestTemplate_->get();\n> >>>  }\n> >>>\n> >>>  /*\n> >>> @@ -799,7 +708,7 @@ void CameraDevice::requestComplete(Request *request,\n> >>>  {\n> >>>  \tBuffer *libcameraBuffer = buffers.begin()->second;\n> >>>  \tcamera3_buffer_status status = CAMERA3_BUFFER_STATUS_OK;\n> >>> -\tcamera_metadata_t *resultMetadata = nullptr;\n> >>> +\tstd::unique_ptr<CameraMetadata> resultMetadata;\n> >>>\n> >>>  \tif (request->status() != Request::RequestComplete) {\n> >>>  \t\tLOG(HAL, Error) << \"Request not succesfully completed: \"\n> >>> @@ -837,16 +746,12 @@ void CameraDevice::requestComplete(Request *request,\n> >>>  \t\tcaptureResult.partial_result = 1;\n> >>>  \t\tresultMetadata = getResultMetadata(descriptor->frameNumber,\n> >>>  \t\t\t\t\t\t   libcameraBuffer->timestamp());\n> >>> -\t\tcaptureResult.result = resultMetadata;\n> >>> +\t\tcaptureResult.result = resultMetadata->get();\n> >>>  \t}\n> >>>\n> >>>  \tcallbacks_->process_capture_result(callbacks_, &captureResult);\n> >>>\n> >>>  \tdelete descriptor;\n> >>> -\tif (resultMetadata)\n> >>> -\t\tfree_camera_metadata(resultMetadata);\n> >>> -\n> >>> -\treturn;\n> >>>  }\n> >>>\n> >>>  void CameraDevice::notifyShutter(uint32_t frameNumber, uint64_t timestamp)\n> >>> @@ -875,89 +780,63 @@ void CameraDevice::notifyError(uint32_t frameNumber, camera3_stream_t *stream)\n> >>>  /*\n> >>>   * Produce a set of fixed result metadata.\n> >>>   */\n> >>> -camera_metadata_t *CameraDevice::getResultMetadata(int frame_number,\n> >>> -\t\t\t\t\t\t   int64_t timestamp)\n> >>> +std::unique_ptr<CameraMetadata> CameraDevice::getResultMetadata(int frame_number,\n> >>\n> >> Not a fan of smart pointers, you know already. How does this work?\n> >> Because the compiler applies copy-elision or because of the move\n> >> semantic applied on the return value?\n> >\n> > std::unique_ptr<> has an operator= that takes an rvalue reference to\n> > another std::unique_ptr<>, and uses move semantic. As explained in\n> > https://en.cppreference.com/w/cpp/language/value_category, an rvalue is\n> > either a prvalue or an xvalue, and a prvalue can be \"a function call or\n> > an overloaded operator expression, whose return type is non-reference\".\n> > As far as I can tell, that's why we don't need an std::move() in the\n> > caller.\n> \n> I see.. This seems to suggest both RVO and move semantic can play a\n> role https://stackoverflow.com/a/46571941\n> \n> Ah, c++\n> \n> >> difficult to follow in my opinion.\n> >\n> > I think we should standardise as much as possible on std::unique_ptr<>\n> > when passing ownership of a returned pointer. That's documented in\n> > Documentation/coding-style.rst.\n> \n> Ack, let's keep it the way it is then.\n> \n> >>> +\t\t\t\t\t\t\t\tint64_t timestamp)\n> >>>  {\n> >>> -\tint ret;\n> >>> -\n> >>>  \t/*\n> >>>  \t * \\todo Keep this in sync with the actual number of entries.\n> >>>  \t * Currently: 13 entries, 36 bytes\n> >>>  \t */\n> >>> -\tcamera_metadata_t *resultMetadata = allocate_camera_metadata(15, 50);\n> >>> +\tstd::unique_ptr<CameraMetadata> resultMetadata =\n> >>> +\t\tutils::make_unique<CameraMetadata>(15, 50);\n> >>> +\tif (!resultMetadata->isValid()) {\n> >>> +\t\tLOG(HAL, Error) << \"Failed to allocate static metadata\";\n> >>> +\t\treturn nullptr;\n> >>> +\t}\n> >>>\n> >>>  \tconst uint8_t ae_state = ANDROID_CONTROL_AE_STATE_CONVERGED;\n> >>> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AE_STATE,\n> >>> -\t\t\t\t\t&ae_state, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AE_STATE, &ae_state, 1);\n> >>>\n> >>>  \tconst uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;\n> >>> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AE_LOCK,\n> >>> -\t\t\t\t\t&ae_lock, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);\n> >>>\n> >>>  \tuint8_t af_state = ANDROID_CONTROL_AF_STATE_INACTIVE;\n> >>> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AF_STATE,\n> >>> -\t\t\t\t\t&af_state, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AF_STATE, &af_state, 1);\n> >>>\n> >>>  \tconst uint8_t awb_state = ANDROID_CONTROL_AWB_STATE_CONVERGED;\n> >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>> -\t\t\t\t\tANDROID_CONTROL_AWB_STATE,\n> >>> -\t\t\t\t\t&awb_state, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AWB_STATE, &awb_state, 1);\n> >>>\n> >>>  \tconst uint8_t awb_lock = ANDROID_CONTROL_AWB_LOCK_OFF;\n> >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>> -\t\t\t\t\tANDROID_CONTROL_AWB_LOCK,\n> >>> -\t\t\t\t\t&awb_lock, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AWB_LOCK, &awb_lock, 1);\n> >>>\n> >>>  \tconst uint8_t lens_state = ANDROID_LENS_STATE_STATIONARY;\n> >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>> -\t\t\t\t\tANDROID_LENS_STATE,\n> >>> -\t\t\t\t\t&lens_state, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tresultMetadata->addEntry(ANDROID_LENS_STATE, &lens_state, 1);\n> >>>\n> >>>  \tint32_t sensorSizes[] = {\n> >>>  \t\t0, 0, 2560, 1920,\n> >>>  \t};\n> >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>> -\t\t\t\t\tANDROID_SCALER_CROP_REGION,\n> >>> -\t\t\t\t\tsensorSizes, 4);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tresultMetadata->addEntry(ANDROID_SCALER_CROP_REGION, sensorSizes, 4);\n> >>>\n> >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>> -\t\t\t\t\tANDROID_SENSOR_TIMESTAMP,\n> >>> -\t\t\t\t\t&timestamp, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tresultMetadata->addEntry(ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);\n> >>>\n> >>>  \t/* 33.3 msec */\n> >>>  \tconst int64_t rolling_shutter_skew = 33300000;\n> >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>> -\t\t\t\t\tANDROID_SENSOR_ROLLING_SHUTTER_SKEW,\n> >>> -\t\t\t\t\t&rolling_shutter_skew, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tresultMetadata->addEntry(ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,\n> >>> +\t\t\t\t &rolling_shutter_skew, 1);\n> >>>\n> >>>  \t/* 16.6 msec */\n> >>>  \tconst int64_t exposure_time = 16600000;\n> >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>> -\t\t\t\t\tANDROID_SENSOR_EXPOSURE_TIME,\n> >>> -\t\t\t\t\t&exposure_time, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tresultMetadata->addEntry(ANDROID_SENSOR_EXPOSURE_TIME,\n> >>> +\t\t\t\t &exposure_time, 1);\n> >>>\n> >>>  \tconst uint8_t lens_shading_map_mode =\n> >>>  \t\t\t\tANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;\n> >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>> -\t\t\t\t\tANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> >>> -\t\t\t\t\t&lens_shading_map_mode, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tresultMetadata->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> >>> +\t\t\t\t &lens_shading_map_mode, 1);\n> >>>\n> >>>  \tconst uint8_t scene_flicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE;\n> >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>> -\t\t\t\t\tANDROID_STATISTICS_SCENE_FLICKER,\n> >>> -\t\t\t\t\t&scene_flicker, 1);\n> >>> -\tMETADATA_ASSERT(ret);\n> >>> +\tresultMetadata->addEntry(ANDROID_STATISTICS_SCENE_FLICKER,\n> >>> +\t\t\t\t &scene_flicker, 1);\n> >>\n> >> Shouldn't you check if the metadata pack is valid ?\n> >\n> > Good point. Should we check here or in the caller ? As the caller would\n> > then need a nullptr check I'm tempted to do so in the caller. Actually,\n> > without a change to the code, the caller will operate correctly I\n> > believe\n> >\n> >                 resultMetadata = getResultMetadata(descriptor->frameNumber,\n> >                                                    libcameraBuffer->timestamp());\n> >                 captureResult.result = resultMetadata->get();\n> >\n> > which will set captureResult.result to nullptr if resultMetadata is not\n> > valid.\n> \n> Yeah, but in that case we should notify an error back to the stack.\n\nThat makes sense. It should be a faily uncommon case though, is it would\nbe the result of a bug in our code, but bugs happen. I wonder what the\nproper error recovery would be in that case.\n\n> What about:\n> \n>         resultMetadata = getResultMetadata(descriptor->frameNumber,\n>                                            libcameraBuffer->timestamp());\n> \tif (status == CAMERA3_BUFFER_STATUS_ERROR || !resultMetadata) {\n> \t\t/* \\todo Improve error handling. */\n> \t\tnotifyError(descriptor->frameNumber,\n> \t\t\t    descriptor->buffers[0].stream);\n> \t} else {\n> \t\tnotifyShutter(descriptor->frameNumber,\n> \t\t\t      libcameraBuffer->timestamp());\n> \n> \t\tcaptureResult.partial_result = 1;\n> \t\tcaptureResult.result = resultMetadata->get();\n> \t}\n> \n> The drawback is that we're generating the result metadata even if\n> status is set to CAMERA3_BUFFER_STATUS_ERROR.\n\nThat I don't think we should do, as I expect the result metadata\ngeneration will not be possible in case of CAMERA3_BUFFER_STATUS_ERROR\nwhen we'll stop generating fake metadata.\n\nHow about this ?\n\n\tif (status == CAMERA3_BUFFER_STATUS_OK) {\n\t\tnotifyShutter(descriptor->frameNumber,\n\t\t\t      libcameraBuffer->timestamp());\n\n\t\tcaptureResult.partial_result = 1;\n\t\tresultMetadata = getResultMetadata(descriptor->frameNumber,\n\t\t\t\t\t\t   libcameraBuffer->timestamp());\n\t\tcaptureResult.result = resultMetadata->get();\n\t}\n\n\tif (status == CAMERA3_BUFFER_STATUS_ERROR || !captureResult.result) {\n\t\t/* \\todo Improve error handling. */\n\t\tnotifyError(descriptor->frameNumber,\n\t\t\t    descriptor->buffers[0].stream);\n\t}\n\nThe last condition could be written if (!captureResult.result) as\nCAMERA3_BUFFER_STATUS_ERROR implies !captureResult.result, but I'd\nrather have both to make it explicit.\n\n> >>>\n> >>>  \treturn resultMetadata;\n> >>>  }\n> >>> diff --git a/src/android/camera_device.h b/src/android/camera_device.h\n> >>> index 7897ba9dc5c7..65ba877a02ea 100644\n> >>> --- a/src/android/camera_device.h\n> >>> +++ b/src/android/camera_device.h\n> >>> @@ -19,13 +19,7 @@\n> >>>\n> >>>  #include \"message.h\"\n> >>>\n> >>> -#define METADATA_ASSERT(_r)\t\t\\\n> >>> -\tdo {\t\t\t\t\\\n> >>> -\t\tif (!(_r)) break;\t\\\n> >>> -\t\tLOG(HAL, Error) << \"Error: \" << __func__ << \":\" << __LINE__; \\\n> >>> -\t\treturn nullptr;\t\t\\\n> >>> -\t} while(0);\n> >>> -\n> >>> +class CameraMetadata;\n> >>>  class ThreadRpc;\n> >>>\n> >>>  class CameraDevice : public libcamera::Object\n> >>> @@ -59,14 +53,15 @@ private:\n> >>>\n> >>>  \tvoid notifyShutter(uint32_t frameNumber, uint64_t timestamp);\n> >>>  \tvoid notifyError(uint32_t frameNumber, camera3_stream_t *stream);\n> >>> -\tcamera_metadata_t *getResultMetadata(int frame_number, int64_t timestamp);\n> >>> +\tstd::unique_ptr<CameraMetadata> getResultMetadata(int frame_number,\n> >>> +\t\t\t\t\t\t\t  int64_t timestamp);\n> >>>\n> >>>  \tbool running_;\n> >>>  \tstd::shared_ptr<libcamera::Camera> camera_;\n> >>>  \tstd::unique_ptr<libcamera::CameraConfiguration> config_;\n> >>>\n> >>> -\tcamera_metadata_t *staticMetadata_;\n> >>> -\tcamera_metadata_t *requestTemplate_;\n> >>> +\tCameraMetadata *staticMetadata_;\n> >>> +\tCameraMetadata *requestTemplate_;\n> >>>  \tconst camera3_callback_ops_t *callbacks_;\n> >>>  };\n> >>>","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 1D78560BF6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 Sep 2019 12:03:06 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(dfj612yhrgyx302h3jwwy-3.rev.dnainternet.fi\n\t[IPv6:2001:14ba:21f5:5b00:ce28:277f:58d7:3ca4])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 74F6E26D;\n\tThu,  5 Sep 2019 12:03:05 +0200 (CEST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1567677785;\n\tbh=X75DeIbVY1iaEtcXCKGyMMP1/vhiyvy+jNB60pX8A5E=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=Q30fQXZd+PNGsfHdylE4+Yv5WJZBKp0P23oIgEdnQm9RAi5wXqdb192vxdBwtl1EF\n\txV7ixjw18uq1S2iISI4OuVqllL7PfP5Vg/LlvPIyMgQgHK/PMZrB9MXZrx7SFHtKdU\n\tdUSY99iZYX/AkIhpot9R5HFopuFG7djoxyAN+r4k=","Date":"Thu, 5 Sep 2019 13:02:59 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190905100259.GE5035@pendragon.ideasonboard.com>","References":"<20190905074737.6955-1-jacopo@jmondi.org>\n\t<20190905074737.6955-8-jacopo@jmondi.org>\n\t<20190905081828.y647dyfqg2apejjp@uno.localdomain>\n\t<20190905093657.GA5035@pendragon.ideasonboard.com>\n\t<20190905095205.333n5sof5rjimsaf@uno.localdomain>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20190905095205.333n5sof5rjimsaf@uno.localdomain>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH v6 7/9] android: camera_device: Use\n\tthe new CameraMetadata helper class","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Thu, 05 Sep 2019 10:03:06 -0000"}},{"id":2621,"web_url":"https://patchwork.libcamera.org/comment/2621/","msgid":"<20190905202503.bv3uwn66fdetfvii@uno.localdomain>","date":"2019-09-05T20:25:03","subject":"Re: [libcamera-devel] [PATCH v6 7/9] android: camera_device: Use\n\tthe new CameraMetadata helper class","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"HI Laurent,\n\nOn Thu, Sep 05, 2019 at 01:02:59PM +0300, Laurent Pinchart wrote:\n> Hi Jacopo,\n>\n> Thank you for the patch.\n>\n> On Thu, Sep 05, 2019 at 11:52:05AM +0200, Jacopo Mondi wrote:\n> > On Thu, Sep 05, 2019 at 12:36:57PM +0300, Laurent Pinchart wrote:\n> > > On Thu, Sep 05, 2019 at 10:18:28AM +0200, Jacopo Mondi wrote:\n> > >> On Thu, Sep 05, 2019 at 09:47:34AM +0200, Jacopo Mondi wrote:\n> > >>> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > >>>\n> > >>> Simplify the implementation of metadata handling in the CameraDevice\n> > >>> class by using the new CameraMetadata helper class.\n> > >>>\n> > >>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > >>> ---\n> > >>>  src/android/camera_device.cpp | 507 +++++++++++++---------------------\n> > >>>  src/android/camera_device.h   |  15 +-\n> > >>>  2 files changed, 198 insertions(+), 324 deletions(-)\n> > >>>\n> > >>> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n> > >>> index 5f8d19b9ef3d..475fa2404421 100644\n> > >>> --- a/src/android/camera_device.cpp\n> > >>> +++ b/src/android/camera_device.cpp\n> > >>> @@ -7,10 +7,10 @@\n> > >>>\n> > >>>  #include \"camera_device.h\"\n> > >>>\n> > >>> -#include <system/camera_metadata.h>\n> > >>> -\n> > >>>  #include \"log.h\"\n> > >>> +#include \"utils.h\"\n> > >>>\n> > >>> +#include \"camera_metadata.h\"\n> > >>>  #include \"thread_rpc.h\"\n> > >>>\n> > >>>  using namespace libcamera;\n> > >>> @@ -59,12 +59,10 @@ CameraDevice::CameraDevice(unsigned int id, const std::shared_ptr<Camera> &camer\n> > >>>  CameraDevice::~CameraDevice()\n> > >>>  {\n> > >>>  \tif (staticMetadata_)\n> > >>> -\t\tfree_camera_metadata(staticMetadata_);\n> > >>> -\tstaticMetadata_ = nullptr;\n> > >>> +\t\tdelete staticMetadata_;\n> > >>>\n> > >>>  \tif (requestTemplate_)\n> > >>> -\t\tfree_camera_metadata(requestTemplate_);\n> > >>> -\trequestTemplate_ = nullptr;\n> > >>> +\t\tdelete requestTemplate_;\n> > >>>  }\n> > >>>\n> > >>>  /*\n> > >>> @@ -117,10 +115,8 @@ void CameraDevice::setCallbacks(const camera3_callback_ops_t *callbacks)\n> > >>>   */\n> > >>>  camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >>>  {\n> > >>> -\tint ret;\n> > >>> -\n> > >>>  \tif (staticMetadata_)\n> > >>> -\t\treturn staticMetadata_;\n> > >>> +\t\treturn staticMetadata_->get();\n> > >>>\n> > >>>  \t/*\n> > >>>  \t * The here reported metadata are enough to implement a basic capture\n> > >>> @@ -132,16 +128,21 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >>>  \t * \\todo Keep this in sync with the actual number of entries.\n> > >>>  \t * Currently: 46 entries, 390 bytes\n> > >>>  \t */\n> > >>> -\tstaticMetadata_ = allocate_camera_metadata(50, 500);\n> > >>> +\tstaticMetadata_ = new CameraMetadata(50, 500);\n> > >>> +\tif (!staticMetadata_->isValid()) {\n> > >>> +\t\tLOG(HAL, Error) << \"Failed to allocate static metadata\";\n> > >>> +\t\tdelete staticMetadata_;\n> > >>> +\t\tstaticMetadata_ = nullptr;\n> > >>> +\t\treturn nullptr;\n> > >>\n> > >> Empty line before return?\n> > >\n> > > I don't mind either way, but I haven't added one as the delete,\n> > > assignment to nullptr and return nullptr are logically grouped in my\n> > > opinion. Feel free to add a blank line if you prefer.\n> >\n> > Ok, if this was intentional let's keep it the way it is.\n> >\n> > >>> +\t}\n> > >>>\n> > >>>  \t/* Color correction static metadata. */\n> > >>>  \tstd::vector<uint8_t> aberrationModes = {\n> > >>>  \t\tANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> > >>> -\t\t\taberrationModes.data(), aberrationModes.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> > >>> +\t\t\t\t  aberrationModes.data(),\n> > >>> +\t\t\t\t  aberrationModes.size());\n> > >>>\n> > >>>  \t/* Control static metadata. */\n> > >>>  \tstd::vector<uint8_t> aeAvailableAntiBandingModes = {\n> > >>> @@ -150,294 +151,228 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >>>  \t\tANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,\n> > >>>  \t\tANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,\n> > >>> -\t\t\taeAvailableAntiBandingModes.data(),\n> > >>> -\t\t\taeAvailableAntiBandingModes.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,\n> > >>> +\t\t\t\t  aeAvailableAntiBandingModes.data(),\n> > >>> +\t\t\t\t  aeAvailableAntiBandingModes.size());\n> > >>>\n> > >>>  \tstd::vector<uint8_t> aeAvailableModes = {\n> > >>>  \t\tANDROID_CONTROL_AE_MODE_ON,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_MODES,\n> > >>> -\t\t\taeAvailableModes.data(), aeAvailableModes.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,\n> > >>> +\t\t\t\t  aeAvailableModes.data(),\n> > >>> +\t\t\t\t  aeAvailableModes.size());\n> > >>>\n> > >>>  \tstd::vector<int32_t> availableAeFpsTarget = {\n> > >>>  \t\t15, 30,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> > >>> -\t\t\tavailableAeFpsTarget.data(),\n> > >>> -\t\t\tavailableAeFpsTarget.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> > >>> +\t\t\t\t  availableAeFpsTarget.data(),\n> > >>> +\t\t\t\t  availableAeFpsTarget.size());\n> > >>>\n> > >>>  \tstd::vector<int32_t> aeCompensationRange = {\n> > >>>  \t\t0, 0,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_AE_COMPENSATION_RANGE,\n> > >>> -\t\t\taeCompensationRange.data(),\n> > >>> -\t\t\taeCompensationRange.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_RANGE,\n> > >>> +\t\t\t\t  aeCompensationRange.data(),\n> > >>> +\t\t\t\t  aeCompensationRange.size());\n> > >>>\n> > >>>  \tconst camera_metadata_rational_t aeCompensationStep[] = {\n> > >>>  \t\t{ 0, 1 }\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_AE_COMPENSATION_STEP,\n> > >>> -\t\t\taeCompensationStep, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_STEP,\n> > >>> +\t\t\t\t  aeCompensationStep, 1);\n> > >>>\n> > >>>  \tstd::vector<uint8_t> availableAfModes = {\n> > >>>  \t\tANDROID_CONTROL_AF_MODE_OFF,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_AF_AVAILABLE_MODES,\n> > >>> -\t\t\tavailableAfModes.data(), availableAfModes.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AF_AVAILABLE_MODES,\n> > >>> +\t\t\t\t  availableAfModes.data(),\n> > >>> +\t\t\t\t  availableAfModes.size());\n> > >>>\n> > >>>  \tstd::vector<uint8_t> availableEffects = {\n> > >>>  \t\tANDROID_CONTROL_EFFECT_MODE_OFF,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_AVAILABLE_EFFECTS,\n> > >>> -\t\t\tavailableEffects.data(), availableEffects.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_EFFECTS,\n> > >>> +\t\t\t\t  availableEffects.data(),\n> > >>> +\t\t\t\t  availableEffects.size());\n> > >>>\n> > >>>  \tstd::vector<uint8_t> availableSceneModes = {\n> > >>>  \t\tANDROID_CONTROL_SCENE_MODE_DISABLED,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_AVAILABLE_SCENE_MODES,\n> > >>> -\t\t\tavailableSceneModes.data(), availableSceneModes.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,\n> > >>> +\t\t\t\t  availableSceneModes.data(),\n> > >>> +\t\t\t\t  availableSceneModes.size());\n> > >>>\n> > >>>  \tstd::vector<uint8_t> availableStabilizationModes = {\n> > >>>  \t\tANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,\n> > >>> -\t\t\tavailableStabilizationModes.data(),\n> > >>> -\t\t\tavailableStabilizationModes.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,\n> > >>> +\t\t\t\t  availableStabilizationModes.data(),\n> > >>> +\t\t\t\t  availableStabilizationModes.size());\n> > >>>\n> > >>>  \tstd::vector<uint8_t> availableAwbModes = {\n> > >>>  \t\tANDROID_CONTROL_AWB_MODE_OFF,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> > >>> -\t\t\tavailableAwbModes.data(), availableAwbModes.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> > >>> +\t\t\t\t  availableAwbModes.data(),\n> > >>> +\t\t\t\t  availableAwbModes.size());\n> > >>>\n> > >>>  \tstd::vector<int32_t> availableMaxRegions = {\n> > >>>  \t\t0, 0, 0,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_MAX_REGIONS,\n> > >>> -\t\t\tavailableMaxRegions.data(), availableMaxRegions.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_MAX_REGIONS,\n> > >>> +\t\t\t\t  availableMaxRegions.data(),\n> > >>> +\t\t\t\t  availableMaxRegions.size());\n> > >>>\n> > >>>  \tstd::vector<uint8_t> sceneModesOverride = {\n> > >>>  \t\tANDROID_CONTROL_AE_MODE_ON,\n> > >>>  \t\tANDROID_CONTROL_AWB_MODE_AUTO,\n> > >>>  \t\tANDROID_CONTROL_AF_MODE_AUTO,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_SCENE_MODE_OVERRIDES,\n> > >>> -\t\t\tsceneModesOverride.data(), sceneModesOverride.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,\n> > >>> +\t\t\t\t  sceneModesOverride.data(),\n> > >>> +\t\t\t\t  sceneModesOverride.size());\n> > >>>\n> > >>>  \tuint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> > >>> -\t\t\t&aeLockAvailable, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> > >>> +\t\t\t\t  &aeLockAvailable, 1);\n> > >>>\n> > >>>  \tuint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> > >>> -\t\t\t&awbLockAvailable, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> > >>> +\t\t\t\t  &awbLockAvailable, 1);\n> > >>>\n> > >>>  \tchar availableControlModes = ANDROID_CONTROL_MODE_AUTO;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_CONTROL_AVAILABLE_MODES,\n> > >>> -\t\t\t&availableControlModes, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,\n> > >>> +\t\t\t\t  &availableControlModes, 1);\n> > >>>\n> > >>>  \t/* JPEG static metadata. */\n> > >>>  \tstd::vector<int32_t> availableThumbnailSizes = {\n> > >>>  \t\t0, 0,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,\n> > >>> -\t\t\tavailableThumbnailSizes.data(),\n> > >>> -\t\t\tavailableThumbnailSizes.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,\n> > >>> +\t\t\t\t  availableThumbnailSizes.data(),\n> > >>> +\t\t\t\t  availableThumbnailSizes.size());\n> > >>>\n> > >>>  \t/* Sensor static metadata. */\n> > >>>  \tint32_t pixelArraySize[] = {\n> > >>>  \t\t2592, 1944,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,\n> > >>> -\t\t\t\t&pixelArraySize, 2);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,\n> > >>> +\t\t\t\t  &pixelArraySize, 2);\n> > >>>\n> > >>>  \tint32_t sensorSizes[] = {\n> > >>>  \t\t0, 0, 2560, 1920,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,\n> > >>> -\t\t\t\t&sensorSizes, 4);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,\n> > >>> +\t\t\t\t  &sensorSizes, 4);\n> > >>>\n> > >>>  \tint32_t sensitivityRange[] = {\n> > >>>  \t\t32, 2400,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_SENSOR_INFO_SENSITIVITY_RANGE,\n> > >>> -\t\t\t\t&sensitivityRange, 2);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,\n> > >>> +\t\t\t\t  &sensitivityRange, 2);\n> > >>>\n> > >>>  \tuint16_t filterArr = ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,\n> > >>> -\t\t\t\t&filterArr, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,\n> > >>> +\t\t\t\t  &filterArr, 1);\n> > >>>\n> > >>>  \tint64_t exposureTimeRange[] = {\n> > >>>  \t\t100000, 200000000,\n> > >>>  \t};\n> > >>\n> > >> I've been thinking for a while to stabilize on the use of std::vector in\n> > >> place of arrays, so e can always use .data() and .size() and have\n> > >> guaranteed we should only change the declaration and not the\n> > >> parameters to the addEntry() operation.\n> > >>\n> > >> This might be a good time to do so. What do you think?\n> > >\n> > > I've thought about it, and constructing a vector is a bit costly\n> > > compared to arrays. I'd rather used std::array<>, but that requires\n> > > specifying the size explicitly :-S I've been thinking about overloading\n> > > the addEntry() method, in order to be able to write\n> > >\n> > > \tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> > > \t\t\t\t  { 100000, 200000000 });\n> > >\n> > > I'm not sure if that will be possible as we need to handle different\n> > > data types, but I think it's worth a try. Other overloaded methods\n> > > should also be added for the arrays of a single element:\n> > >\n> > > \tstaticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION, 0);\n> > >\n> > > I would prefer handling the standardisation of vector vs. array in a\n> > > separate patch, when dealing with overloaded versions of addEntry(), as\n> > > this patch is big enough already.\n> >\n> > Agreed\n> >\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> > >>> -\t\t\t\t&exposureTimeRange, 2);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> > >>> +\t\t\t\t  &exposureTimeRange, 2);\n> > >>>\n> > >>>  \tint32_t orientation = 0;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_SENSOR_ORIENTATION,\n> > >>> -\t\t\t\t&orientation, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION,\n> > >>> +\t\t\t\t  &orientation, 1);\n> > >>\n> > >> Fits in 1 line\n> > >\n> > > I've kept it on two lines to use similar constructs through the whole\n> > > function, but I don't mind much, so please feel free to change it if you\n> > > prefer.\n> >\n> > If it was intentional, let's keep it the way it is\n> >\n> > >>>\n> > >>>  \tstd::vector<int32_t> testPatterModes = {\n> > >>>  \t\tANDROID_SENSOR_TEST_PATTERN_MODE_OFF,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,\n> > >>> -\t\t\t\ttestPatterModes.data(), testPatterModes.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,\n> > >>> +\t\t\t\t  testPatterModes.data(),\n> > >>> +\t\t\t\t  testPatterModes.size());\n> > >>>\n> > >>>  \tstd::vector<float> physicalSize = {\n> > >>>  \t\t2592, 1944,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_SENSOR_INFO_PHYSICAL_SIZE,\n> > >>> -\t\t\t\tphysicalSize.data(), physicalSize.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,\n> > >>> +\t\t\t\t  physicalSize.data(),\n> > >>> +\t\t\t\t  physicalSize.size());\n> > >>\n> > >> Fits in 1 line\n> > >>\n> > >>>\n> > >>>  \tuint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,\n> > >>> -\t\t\t&timestampSource, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,\n> > >>> +\t\t\t\t  &timestampSource, 1);\n> > >>>\n> > >>>  \t/* Statistics static metadata. */\n> > >>>  \tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> > >>> -\t\t\t&faceDetectMode, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> > >>> +\t\t\t\t  &faceDetectMode, 1);\n> > >>>\n> > >>>  \tint32_t maxFaceCount = 0;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> > >>> -\t\t\t&maxFaceCount, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> > >>> +\t\t\t\t  &maxFaceCount, 1);\n> > >>>\n> > >>>  \t/* Sync static metadata. */\n> > >>>  \tint32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);\n> > >>>\n> > >>>  \t/* Flash static metadata. */\n> > >>>  \tchar flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_FLASH_INFO_AVAILABLE,\n> > >>> -\t\t\t&flashAvailable, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_FLASH_INFO_AVAILABLE,\n> > >>> +\t\t\t\t  &flashAvailable, 1);\n> > >>>\n> > >>>  \t/* Lens static metadata. */\n> > >>>  \tstd::vector<float> lensApertures = {\n> > >>>  \t\t2.53 / 100,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_APERTURES,\n> > >>> -\t\t\t\tlensApertures.data(), lensApertures.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_APERTURES,\n> > >>> +\t\t\t\t  lensApertures.data(),\n> > >>> +\t\t\t\t  lensApertures.size());\n> > >>>\n> > >>>  \tuint8_t lensFacing = ANDROID_LENS_FACING_FRONT;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_LENS_FACING, &lensFacing, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_LENS_FACING, &lensFacing, 1);\n> > >>>\n> > >>>  \tstd::vector<float> lensFocalLenghts = {\n> > >>>  \t\t1,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,\n> > >>> -\t\t\t\tlensFocalLenghts.data(),\n> > >>> -\t\t\t\tlensFocalLenghts.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,\n> > >>> +\t\t\t\t  lensFocalLenghts.data(),\n> > >>> +\t\t\t\t  lensFocalLenghts.size());\n> > >>>\n> > >>>  \tstd::vector<uint8_t> opticalStabilizations = {\n> > >>>  \t\tANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,\n> > >>> -\t\t\t\topticalStabilizations.data(),\n> > >>> -\t\t\t\topticalStabilizations.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,\n> > >>> +\t\t\t\t  opticalStabilizations.data(),\n> > >>> +\t\t\t\t  opticalStabilizations.size());\n> > >>>\n> > >>>  \tfloat hypeFocalDistance = 0;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,\n> > >>> -\t\t\t\t&hypeFocalDistance, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,\n> > >>> +\t\t\t\t  &hypeFocalDistance, 1);\n> > >>>\n> > >>>  \tfloat minFocusDistance = 0;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,\n> > >>> -\t\t\t\t&minFocusDistance, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,\n> > >>> +\t\t\t\t  &minFocusDistance, 1);\n> > >>>\n> > >>>  \t/* Noise reduction modes. */\n> > >>>  \tuint8_t noiseReductionModes = ANDROID_NOISE_REDUCTION_MODE_OFF;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\t\tANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,\n> > >>> -\t\t\t\t&noiseReductionModes, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,\n> > >>> +\t\t\t\t  &noiseReductionModes, 1);\n> > >>>\n> > >>>  \t/* Scaler static metadata. */\n> > >>>  \tfloat maxDigitalZoom = 1;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,\n> > >>> -\t\t\t&maxDigitalZoom, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,\n> > >>> +\t\t\t\t  &maxDigitalZoom, 1);\n> > >>>\n> > >>>  \tstd::vector<uint32_t> availableStreamFormats = {\n> > >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB,\n> > >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888,\n> > >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_SCALER_AVAILABLE_FORMATS,\n> > >>> -\t\t\tavailableStreamFormats.data(),\n> > >>> -\t\t\tavailableStreamFormats.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_FORMATS,\n> > >>> +\t\t\t\t  availableStreamFormats.data(),\n> > >>> +\t\t\t\t  availableStreamFormats.size());\n> > >>>\n> > >>>  \tstd::vector<uint32_t> availableStreamConfigurations = {\n> > >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920,\n> > >>> @@ -447,65 +382,57 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920,\n> > >>>  \t\tANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,\n> > >>> -\t\t\tavailableStreamConfigurations.data(),\n> > >>> -\t\t\tavailableStreamConfigurations.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,\n> > >>> +\t\t\t\t  availableStreamConfigurations.data(),\n> > >>> +\t\t\t\t  availableStreamConfigurations.size());\n> > >>>\n> > >>>  \tstd::vector<int64_t> availableStallDurations = {\n> > >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_SCALER_AVAILABLE_STALL_DURATIONS,\n> > >>> -\t\t\tavailableStallDurations.data(),\n> > >>> -\t\t\tavailableStallDurations.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,\n> > >>> +\t\t\t\t  availableStallDurations.data(),\n> > >>> +\t\t\t\t  availableStallDurations.size());\n> > >>>\n> > >>>  \tstd::vector<int64_t> minFrameDurations = {\n> > >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,\n> > >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920, 33333333,\n> > >>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888, 2560, 1920, 33333333,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> > >>> -\t\t\tminFrameDurations.data(), minFrameDurations.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> > >>> +\t\t\t\t  minFrameDurations.data(),\n> > >>> +\t\t\t\t  minFrameDurations.size());\n> > >>>\n> > >>>  \tuint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);\n> > >>>\n> > >>>  \t/* Info static metadata. */\n> > >>>  \tuint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> > >>> -\t\t\t&supportedHWLevel, 1);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> > >>> +\t\t\t\t  &supportedHWLevel, 1);\n> > >>>\n> > >>>  \t/* Request static metadata. */\n> > >>>  \tint32_t partialResultCount = 1;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> > >>> -\t\t\t&partialResultCount, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> > >>> +\t\t\t\t  &partialResultCount, 1);\n> > >>>\n> > >>>  \tuint8_t maxPipelineDepth = 2;\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_REQUEST_PIPELINE_MAX_DEPTH,\n> > >>> -\t\t\t&maxPipelineDepth, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_PIPELINE_MAX_DEPTH,\n> > >>> +\t\t\t\t  &maxPipelineDepth, 1);\n> > >>>\n> > >>>  \tstd::vector<uint8_t> availableCapabilities = {\n> > >>>  \t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>> -\t\t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> > >>> -\t\t\tavailableCapabilities.data(),\n> > >>> -\t\t\tavailableCapabilities.size());\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> > >>> +\t\t\t\t  availableCapabilities.data(),\n> > >>> +\t\t\t\t  availableCapabilities.size());\n> > >>> +\n> > >>> +\tif (!staticMetadata_->isValid()) {\n> > >>> +\t\tdelete staticMetadata_;\n> > >>> +\t\tstaticMetadata_ = nullptr;\n> > >>> +\t\treturn nullptr;\n> > >>> +\t}\n> > >>>\n> > >>> -\treturn staticMetadata_;\n> > >>> +\treturn staticMetadata_->get();\n> > >>>  }\n> > >>>\n> > >>>  /*\n> > >>> @@ -513,8 +440,6 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >>>   */\n> > >>>  const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)\n> > >>>  {\n> > >>> -\tint ret;\n> > >>> -\n> > >>>  \t/*\n> > >>>  \t * \\todo Inspect type and pick the right metadata pack.\n> > >>>  \t * As of now just use a single one for all templates.\n> > >>> @@ -545,89 +470,73 @@ const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)\n> > >>>  \t}\n> > >>>\n> > >>>  \tif (requestTemplate_)\n> > >>> -\t\treturn requestTemplate_;\n> > >>> +\t\treturn requestTemplate_->get();\n> > >>>\n> > >>>  \t/*\n> > >>>  \t * \\todo Keep this in sync with the actual number of entries.\n> > >>>  \t * Currently: 12 entries, 15 bytes\n> > >>>  \t */\n> > >>> -\trequestTemplate_ = allocate_camera_metadata(15, 20);\n> > >>> +\trequestTemplate_ = new CameraMetadata(15, 20);\n> > >>>  \tif (!requestTemplate_) {\n> > >>>  \t\tLOG(HAL, Error) << \"Failed to allocate template metadata\";\n> > >>> +\t\tdelete requestTemplate_;\n> > >>> +\t\trequestTemplate_ = nullptr;\n> > >>\n> > >> Empty line before return ?\n> > >>\n> > >>>  \t\treturn nullptr;\n> > >>>  \t}\n> > >>>\n> > >>>  \tuint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;\n> > >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>> -\t\t\tANDROID_CONTROL_AE_MODE,\n> > >>> -\t\t\t&aeMode, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_MODE,\n> > >>> +\t\t\t\t   &aeMode, 1);\n> > >>\n> > >> This and many others entries here and below fit in 1 line.\n> > >>\n> > >>>\n> > >>>  \tint32_t aeExposureCompensation = 0;\n> > >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>> -\t\t\tANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,\n> > >>> -\t\t\t&aeExposureCompensation, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,\n> > >>> +\t\t\t\t   &aeExposureCompensation, 1);\n> > >>>\n> > >>>  \tuint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;\n> > >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>> -\t\t\tANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,\n> > >>> -\t\t\t&aePrecaptureTrigger, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,\n> > >>> +\t\t\t\t   &aePrecaptureTrigger, 1);\n> > >>>\n> > >>>  \tuint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;\n> > >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>> -\t\t\tANDROID_CONTROL_AE_LOCK,\n> > >>> -\t\t\t&aeLock, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_LOCK,\n> > >>> +\t\t\t\t   &aeLock, 1);\n> > >>>\n> > >>>  \tuint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;\n> > >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>> -\t\t\tANDROID_CONTROL_AF_TRIGGER,\n> > >>> -\t\t\t&afTrigger, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AF_TRIGGER,\n> > >>> +\t\t\t\t   &afTrigger, 1);\n> > >>>\n> > >>>  \tuint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;\n> > >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>> -\t\t\tANDROID_CONTROL_AWB_MODE,\n> > >>> -\t\t\t&awbMode, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AWB_MODE,\n> > >>> +\t\t\t\t   &awbMode, 1);\n> > >>>\n> > >>>  \tuint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;\n> > >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>> -\t\t\tANDROID_CONTROL_AWB_LOCK,\n> > >>> -\t\t\t&awbLock, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AWB_LOCK,\n> > >>> +\t\t\t\t   &awbLock, 1);\n> > >>>\n> > >>>  \tuint8_t flashMode = ANDROID_FLASH_MODE_OFF;\n> > >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>> -\t\t\tANDROID_FLASH_MODE,\n> > >>> -\t\t\t&flashMode, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\trequestTemplate_->addEntry(ANDROID_FLASH_MODE,\n> > >>> +\t\t\t\t   &flashMode, 1);\n> > >>>\n> > >>>  \tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>> -\t\t\tANDROID_STATISTICS_FACE_DETECT_MODE,\n> > >>> -\t\t\t&faceDetectMode, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\trequestTemplate_->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,\n> > >>> +\t\t\t\t   &faceDetectMode, 1);\n> > >>>\n> > >>>  \tuint8_t noiseReduction = ANDROID_NOISE_REDUCTION_MODE_OFF;\n> > >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>> -\t\t\tANDROID_NOISE_REDUCTION_MODE, &noiseReduction, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\trequestTemplate_->addEntry(ANDROID_NOISE_REDUCTION_MODE,\n> > >>> +\t\t\t\t   &noiseReduction, 1);\n> > >>>\n> > >>>  \tuint8_t aberrationMode = ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF;\n> > >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>> -\t\t\tANDROID_COLOR_CORRECTION_ABERRATION_MODE,\n> > >>> -\t\t\t&aberrationMode, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\trequestTemplate_->addEntry(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,\n> > >>> +\t\t\t\t   &aberrationMode, 1);\n> > >>> +\n> > >>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_CAPTURE_INTENT,\n> > >>> +\t\t\t\t   &captureIntent, 1);\n> > >>>\n> > >>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>> -\t\t\tANDROID_CONTROL_CAPTURE_INTENT,\n> > >>> -\t\t\t&captureIntent, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tif (!requestTemplate_->isValid()) {\n> > >>> +\t\tdelete requestTemplate_;\n> > >>> +\t\trequestTemplate_ = nullptr;\n> > >>\n> > >> You should return nullptr here, otherwise the below requestTemplate_->get();\n> > >> will de-reference a nullptr.\n> > >\n> > > Absolutely, my bad.\n> > >\n> > >>> +\t}\n> > >>>\n> > >>> -\treturn requestTemplate_;\n> > >>> +\treturn requestTemplate_->get();\n> > >>>  }\n> > >>>\n> > >>>  /*\n> > >>> @@ -799,7 +708,7 @@ void CameraDevice::requestComplete(Request *request,\n> > >>>  {\n> > >>>  \tBuffer *libcameraBuffer = buffers.begin()->second;\n> > >>>  \tcamera3_buffer_status status = CAMERA3_BUFFER_STATUS_OK;\n> > >>> -\tcamera_metadata_t *resultMetadata = nullptr;\n> > >>> +\tstd::unique_ptr<CameraMetadata> resultMetadata;\n> > >>>\n> > >>>  \tif (request->status() != Request::RequestComplete) {\n> > >>>  \t\tLOG(HAL, Error) << \"Request not succesfully completed: \"\n> > >>> @@ -837,16 +746,12 @@ void CameraDevice::requestComplete(Request *request,\n> > >>>  \t\tcaptureResult.partial_result = 1;\n> > >>>  \t\tresultMetadata = getResultMetadata(descriptor->frameNumber,\n> > >>>  \t\t\t\t\t\t   libcameraBuffer->timestamp());\n> > >>> -\t\tcaptureResult.result = resultMetadata;\n> > >>> +\t\tcaptureResult.result = resultMetadata->get();\n> > >>>  \t}\n> > >>>\n> > >>>  \tcallbacks_->process_capture_result(callbacks_, &captureResult);\n> > >>>\n> > >>>  \tdelete descriptor;\n> > >>> -\tif (resultMetadata)\n> > >>> -\t\tfree_camera_metadata(resultMetadata);\n> > >>> -\n> > >>> -\treturn;\n> > >>>  }\n> > >>>\n> > >>>  void CameraDevice::notifyShutter(uint32_t frameNumber, uint64_t timestamp)\n> > >>> @@ -875,89 +780,63 @@ void CameraDevice::notifyError(uint32_t frameNumber, camera3_stream_t *stream)\n> > >>>  /*\n> > >>>   * Produce a set of fixed result metadata.\n> > >>>   */\n> > >>> -camera_metadata_t *CameraDevice::getResultMetadata(int frame_number,\n> > >>> -\t\t\t\t\t\t   int64_t timestamp)\n> > >>> +std::unique_ptr<CameraMetadata> CameraDevice::getResultMetadata(int frame_number,\n> > >>\n> > >> Not a fan of smart pointers, you know already. How does this work?\n> > >> Because the compiler applies copy-elision or because of the move\n> > >> semantic applied on the return value?\n> > >\n> > > std::unique_ptr<> has an operator= that takes an rvalue reference to\n> > > another std::unique_ptr<>, and uses move semantic. As explained in\n> > > https://en.cppreference.com/w/cpp/language/value_category, an rvalue is\n> > > either a prvalue or an xvalue, and a prvalue can be \"a function call or\n> > > an overloaded operator expression, whose return type is non-reference\".\n> > > As far as I can tell, that's why we don't need an std::move() in the\n> > > caller.\n> >\n> > I see.. This seems to suggest both RVO and move semantic can play a\n> > role https://stackoverflow.com/a/46571941\n> >\n> > Ah, c++\n> >\n> > >> difficult to follow in my opinion.\n> > >\n> > > I think we should standardise as much as possible on std::unique_ptr<>\n> > > when passing ownership of a returned pointer. That's documented in\n> > > Documentation/coding-style.rst.\n> >\n> > Ack, let's keep it the way it is then.\n> >\n> > >>> +\t\t\t\t\t\t\t\tint64_t timestamp)\n> > >>>  {\n> > >>> -\tint ret;\n> > >>> -\n> > >>>  \t/*\n> > >>>  \t * \\todo Keep this in sync with the actual number of entries.\n> > >>>  \t * Currently: 13 entries, 36 bytes\n> > >>>  \t */\n> > >>> -\tcamera_metadata_t *resultMetadata = allocate_camera_metadata(15, 50);\n> > >>> +\tstd::unique_ptr<CameraMetadata> resultMetadata =\n> > >>> +\t\tutils::make_unique<CameraMetadata>(15, 50);\n> > >>> +\tif (!resultMetadata->isValid()) {\n> > >>> +\t\tLOG(HAL, Error) << \"Failed to allocate static metadata\";\n> > >>> +\t\treturn nullptr;\n> > >>> +\t}\n> > >>>\n> > >>>  \tconst uint8_t ae_state = ANDROID_CONTROL_AE_STATE_CONVERGED;\n> > >>> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AE_STATE,\n> > >>> -\t\t\t\t\t&ae_state, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AE_STATE, &ae_state, 1);\n> > >>>\n> > >>>  \tconst uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;\n> > >>> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AE_LOCK,\n> > >>> -\t\t\t\t\t&ae_lock, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);\n> > >>>\n> > >>>  \tuint8_t af_state = ANDROID_CONTROL_AF_STATE_INACTIVE;\n> > >>> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AF_STATE,\n> > >>> -\t\t\t\t\t&af_state, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AF_STATE, &af_state, 1);\n> > >>>\n> > >>>  \tconst uint8_t awb_state = ANDROID_CONTROL_AWB_STATE_CONVERGED;\n> > >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>> -\t\t\t\t\tANDROID_CONTROL_AWB_STATE,\n> > >>> -\t\t\t\t\t&awb_state, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AWB_STATE, &awb_state, 1);\n> > >>>\n> > >>>  \tconst uint8_t awb_lock = ANDROID_CONTROL_AWB_LOCK_OFF;\n> > >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>> -\t\t\t\t\tANDROID_CONTROL_AWB_LOCK,\n> > >>> -\t\t\t\t\t&awb_lock, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AWB_LOCK, &awb_lock, 1);\n> > >>>\n> > >>>  \tconst uint8_t lens_state = ANDROID_LENS_STATE_STATIONARY;\n> > >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>> -\t\t\t\t\tANDROID_LENS_STATE,\n> > >>> -\t\t\t\t\t&lens_state, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tresultMetadata->addEntry(ANDROID_LENS_STATE, &lens_state, 1);\n> > >>>\n> > >>>  \tint32_t sensorSizes[] = {\n> > >>>  \t\t0, 0, 2560, 1920,\n> > >>>  \t};\n> > >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>> -\t\t\t\t\tANDROID_SCALER_CROP_REGION,\n> > >>> -\t\t\t\t\tsensorSizes, 4);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tresultMetadata->addEntry(ANDROID_SCALER_CROP_REGION, sensorSizes, 4);\n> > >>>\n> > >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>> -\t\t\t\t\tANDROID_SENSOR_TIMESTAMP,\n> > >>> -\t\t\t\t\t&timestamp, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tresultMetadata->addEntry(ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);\n> > >>>\n> > >>>  \t/* 33.3 msec */\n> > >>>  \tconst int64_t rolling_shutter_skew = 33300000;\n> > >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>> -\t\t\t\t\tANDROID_SENSOR_ROLLING_SHUTTER_SKEW,\n> > >>> -\t\t\t\t\t&rolling_shutter_skew, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tresultMetadata->addEntry(ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,\n> > >>> +\t\t\t\t &rolling_shutter_skew, 1);\n> > >>>\n> > >>>  \t/* 16.6 msec */\n> > >>>  \tconst int64_t exposure_time = 16600000;\n> > >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>> -\t\t\t\t\tANDROID_SENSOR_EXPOSURE_TIME,\n> > >>> -\t\t\t\t\t&exposure_time, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tresultMetadata->addEntry(ANDROID_SENSOR_EXPOSURE_TIME,\n> > >>> +\t\t\t\t &exposure_time, 1);\n> > >>>\n> > >>>  \tconst uint8_t lens_shading_map_mode =\n> > >>>  \t\t\t\tANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;\n> > >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>> -\t\t\t\t\tANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> > >>> -\t\t\t\t\t&lens_shading_map_mode, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tresultMetadata->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> > >>> +\t\t\t\t &lens_shading_map_mode, 1);\n> > >>>\n> > >>>  \tconst uint8_t scene_flicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE;\n> > >>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>> -\t\t\t\t\tANDROID_STATISTICS_SCENE_FLICKER,\n> > >>> -\t\t\t\t\t&scene_flicker, 1);\n> > >>> -\tMETADATA_ASSERT(ret);\n> > >>> +\tresultMetadata->addEntry(ANDROID_STATISTICS_SCENE_FLICKER,\n> > >>> +\t\t\t\t &scene_flicker, 1);\n> > >>\n> > >> Shouldn't you check if the metadata pack is valid ?\n> > >\n> > > Good point. Should we check here or in the caller ? As the caller would\n> > > then need a nullptr check I'm tempted to do so in the caller. Actually,\n> > > without a change to the code, the caller will operate correctly I\n> > > believe\n> > >\n> > >                 resultMetadata = getResultMetadata(descriptor->frameNumber,\n> > >                                                    libcameraBuffer->timestamp());\n> > >                 captureResult.result = resultMetadata->get();\n> > >\n> > > which will set captureResult.result to nullptr if resultMetadata is not\n> > > valid.\n> >\n> > Yeah, but in that case we should notify an error back to the stack.\n>\n> That makes sense. It should be a faily uncommon case though, is it would\n> be the result of a bug in our code, but bugs happen. I wonder what the\n> proper error recovery would be in that case.\n>\n> > What about:\n> >\n> >         resultMetadata = getResultMetadata(descriptor->frameNumber,\n> >                                            libcameraBuffer->timestamp());\n> > \tif (status == CAMERA3_BUFFER_STATUS_ERROR || !resultMetadata) {\n> > \t\t/* \\todo Improve error handling. */\n> > \t\tnotifyError(descriptor->frameNumber,\n> > \t\t\t    descriptor->buffers[0].stream);\n> > \t} else {\n> > \t\tnotifyShutter(descriptor->frameNumber,\n> > \t\t\t      libcameraBuffer->timestamp());\n> >\n> > \t\tcaptureResult.partial_result = 1;\n> > \t\tcaptureResult.result = resultMetadata->get();\n> > \t}\n> >\n> > The drawback is that we're generating the result metadata even if\n> > status is set to CAMERA3_BUFFER_STATUS_ERROR.\n>\n> That I don't think we should do, as I expect the result metadata\n> generation will not be possible in case of CAMERA3_BUFFER_STATUS_ERROR\n> when we'll stop generating fake metadata.\n>\n> How about this ?\n>\n> \tif (status == CAMERA3_BUFFER_STATUS_OK) {\n> \t\tnotifyShutter(descriptor->frameNumber,\n> \t\t\t      libcameraBuffer->timestamp());\n>\n> \t\tcaptureResult.partial_result = 1;\n> \t\tresultMetadata = getResultMetadata(descriptor->frameNumber,\n> \t\t\t\t\t\t   libcameraBuffer->timestamp());\n> \t\tcaptureResult.result = resultMetadata->get();\n> \t}\n>\n> \tif (status == CAMERA3_BUFFER_STATUS_ERROR || !captureResult.result) {\n> \t\t/* \\todo Improve error handling. */\n> \t\tnotifyError(descriptor->frameNumber,\n> \t\t\t    descriptor->buffers[0].stream);\n> \t}\n>\n> The last condition could be written if (!captureResult.result) as\n> CAMERA3_BUFFER_STATUS_ERROR implies !captureResult.result, but I'd\n> rather have both to make it explicit.\n>\n\nThe only difference I see here is that we send up a shutter event and\nthe if metadata generation fails we send back an error.\n\nIn the previous version was either an error or the shutter\nnotification, not both.\n\nI can't tell if this makes any difference to the camera stack to be\nhonest.\n\nThanks\n   j\n\n> > >>>\n> > >>>  \treturn resultMetadata;\n> > >>>  }\n> > >>> diff --git a/src/android/camera_device.h b/src/android/camera_device.h\n> > >>> index 7897ba9dc5c7..65ba877a02ea 100644\n> > >>> --- a/src/android/camera_device.h\n> > >>> +++ b/src/android/camera_device.h\n> > >>> @@ -19,13 +19,7 @@\n> > >>>\n> > >>>  #include \"message.h\"\n> > >>>\n> > >>> -#define METADATA_ASSERT(_r)\t\t\\\n> > >>> -\tdo {\t\t\t\t\\\n> > >>> -\t\tif (!(_r)) break;\t\\\n> > >>> -\t\tLOG(HAL, Error) << \"Error: \" << __func__ << \":\" << __LINE__; \\\n> > >>> -\t\treturn nullptr;\t\t\\\n> > >>> -\t} while(0);\n> > >>> -\n> > >>> +class CameraMetadata;\n> > >>>  class ThreadRpc;\n> > >>>\n> > >>>  class CameraDevice : public libcamera::Object\n> > >>> @@ -59,14 +53,15 @@ private:\n> > >>>\n> > >>>  \tvoid notifyShutter(uint32_t frameNumber, uint64_t timestamp);\n> > >>>  \tvoid notifyError(uint32_t frameNumber, camera3_stream_t *stream);\n> > >>> -\tcamera_metadata_t *getResultMetadata(int frame_number, int64_t timestamp);\n> > >>> +\tstd::unique_ptr<CameraMetadata> getResultMetadata(int frame_number,\n> > >>> +\t\t\t\t\t\t\t  int64_t timestamp);\n> > >>>\n> > >>>  \tbool running_;\n> > >>>  \tstd::shared_ptr<libcamera::Camera> camera_;\n> > >>>  \tstd::unique_ptr<libcamera::CameraConfiguration> config_;\n> > >>>\n> > >>> -\tcamera_metadata_t *staticMetadata_;\n> > >>> -\tcamera_metadata_t *requestTemplate_;\n> > >>> +\tCameraMetadata *staticMetadata_;\n> > >>> +\tCameraMetadata *requestTemplate_;\n> > >>>  \tconst camera3_callback_ops_t *callbacks_;\n> > >>>  };\n> > >>>\n>\n> --\n> Regards,\n>\n> Laurent Pinchart","headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net\n\t[217.70.183.196])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 46F2160C18\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 Sep 2019 22:23:31 +0200 (CEST)","from uno.localdomain (2-224-242-101.ip172.fastwebnet.it\n\t[2.224.242.101]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay4-d.mail.gandi.net (Postfix) with ESMTPSA id 9E103E000B;\n\tThu,  5 Sep 2019 20:23:30 +0000 (UTC)"],"X-Originating-IP":"2.224.242.101","Date":"Thu, 5 Sep 2019 22:25:03 +0200","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190905202503.bv3uwn66fdetfvii@uno.localdomain>","References":"<20190905074737.6955-1-jacopo@jmondi.org>\n\t<20190905074737.6955-8-jacopo@jmondi.org>\n\t<20190905081828.y647dyfqg2apejjp@uno.localdomain>\n\t<20190905093657.GA5035@pendragon.ideasonboard.com>\n\t<20190905095205.333n5sof5rjimsaf@uno.localdomain>\n\t<20190905100259.GE5035@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Type":"multipart/signed; micalg=pgp-sha256;\n\tprotocol=\"application/pgp-signature\"; boundary=\"aa22oedf6pgmfg43\"","Content-Disposition":"inline","In-Reply-To":"<20190905100259.GE5035@pendragon.ideasonboard.com>","User-Agent":"NeoMutt/20180716","Subject":"Re: [libcamera-devel] [PATCH v6 7/9] android: camera_device: Use\n\tthe new CameraMetadata helper class","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Thu, 05 Sep 2019 20:23:31 -0000"}},{"id":2622,"web_url":"https://patchwork.libcamera.org/comment/2622/","msgid":"<20190905203917.GP5035@pendragon.ideasonboard.com>","date":"2019-09-05T20:39:17","subject":"Re: [libcamera-devel] [PATCH v6 7/9] android: camera_device: Use\n\tthe new CameraMetadata helper class","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nOn Thu, Sep 05, 2019 at 10:25:03PM +0200, Jacopo Mondi wrote:\n> On Thu, Sep 05, 2019 at 01:02:59PM +0300, Laurent Pinchart wrote:\n> > On Thu, Sep 05, 2019 at 11:52:05AM +0200, Jacopo Mondi wrote:\n> >> On Thu, Sep 05, 2019 at 12:36:57PM +0300, Laurent Pinchart wrote:\n> >>> On Thu, Sep 05, 2019 at 10:18:28AM +0200, Jacopo Mondi wrote:\n> >>>> On Thu, Sep 05, 2019 at 09:47:34AM +0200, Jacopo Mondi wrote:\n> >>>>> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> >>>>>\n> >>>>> Simplify the implementation of metadata handling in the CameraDevice\n> >>>>> class by using the new CameraMetadata helper class.\n> >>>>>\n> >>>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> >>>>> ---\n> >>>>>  src/android/camera_device.cpp | 507 +++++++++++++---------------------\n> >>>>>  src/android/camera_device.h   |  15 +-\n> >>>>>  2 files changed, 198 insertions(+), 324 deletions(-)\n> >>>>>\n> >>>>> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n> >>>>> index 5f8d19b9ef3d..475fa2404421 100644\n> >>>>> --- a/src/android/camera_device.cpp\n> >>>>> +++ b/src/android/camera_device.cpp\n> >>>>> @@ -7,10 +7,10 @@\n> >>>>>\n> >>>>>  #include \"camera_device.h\"\n> >>>>>\n> >>>>> -#include <system/camera_metadata.h>\n> >>>>> -\n> >>>>>  #include \"log.h\"\n> >>>>> +#include \"utils.h\"\n> >>>>>\n> >>>>> +#include \"camera_metadata.h\"\n> >>>>>  #include \"thread_rpc.h\"\n> >>>>>\n> >>>>>  using namespace libcamera;\n> >>>>> @@ -59,12 +59,10 @@ CameraDevice::CameraDevice(unsigned int id, const std::shared_ptr<Camera> &camer\n> >>>>>  CameraDevice::~CameraDevice()\n> >>>>>  {\n> >>>>>  \tif (staticMetadata_)\n> >>>>> -\t\tfree_camera_metadata(staticMetadata_);\n> >>>>> -\tstaticMetadata_ = nullptr;\n> >>>>> +\t\tdelete staticMetadata_;\n> >>>>>\n> >>>>>  \tif (requestTemplate_)\n> >>>>> -\t\tfree_camera_metadata(requestTemplate_);\n> >>>>> -\trequestTemplate_ = nullptr;\n> >>>>> +\t\tdelete requestTemplate_;\n> >>>>>  }\n> >>>>>\n> >>>>>  /*\n> >>>>> @@ -117,10 +115,8 @@ void CameraDevice::setCallbacks(const camera3_callback_ops_t *callbacks)\n> >>>>>   */\n> >>>>>  camera_metadata_t *CameraDevice::getStaticMetadata()\n> >>>>>  {\n> >>>>> -\tint ret;\n> >>>>> -\n> >>>>>  \tif (staticMetadata_)\n> >>>>> -\t\treturn staticMetadata_;\n> >>>>> +\t\treturn staticMetadata_->get();\n> >>>>>\n> >>>>>  \t/*\n> >>>>>  \t * The here reported metadata are enough to implement a basic capture\n> >>>>> @@ -132,16 +128,21 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> >>>>>  \t * \\todo Keep this in sync with the actual number of entries.\n> >>>>>  \t * Currently: 46 entries, 390 bytes\n> >>>>>  \t */\n> >>>>> -\tstaticMetadata_ = allocate_camera_metadata(50, 500);\n> >>>>> +\tstaticMetadata_ = new CameraMetadata(50, 500);\n> >>>>> +\tif (!staticMetadata_->isValid()) {\n> >>>>> +\t\tLOG(HAL, Error) << \"Failed to allocate static metadata\";\n> >>>>> +\t\tdelete staticMetadata_;\n> >>>>> +\t\tstaticMetadata_ = nullptr;\n> >>>>> +\t\treturn nullptr;\n> >>>>\n> >>>> Empty line before return?\n> >>>\n> >>> I don't mind either way, but I haven't added one as the delete,\n> >>> assignment to nullptr and return nullptr are logically grouped in my\n> >>> opinion. Feel free to add a blank line if you prefer.\n> >>\n> >> Ok, if this was intentional let's keep it the way it is.\n> >>\n> >>>>> +\t}\n> >>>>>\n> >>>>>  \t/* Color correction static metadata. */\n> >>>>>  \tstd::vector<uint8_t> aberrationModes = {\n> >>>>>  \t\tANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> >>>>> -\t\t\taberrationModes.data(), aberrationModes.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> >>>>> +\t\t\t\t  aberrationModes.data(),\n> >>>>> +\t\t\t\t  aberrationModes.size());\n> >>>>>\n> >>>>>  \t/* Control static metadata. */\n> >>>>>  \tstd::vector<uint8_t> aeAvailableAntiBandingModes = {\n> >>>>> @@ -150,294 +151,228 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> >>>>>  \t\tANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,\n> >>>>>  \t\tANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,\n> >>>>> -\t\t\taeAvailableAntiBandingModes.data(),\n> >>>>> -\t\t\taeAvailableAntiBandingModes.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,\n> >>>>> +\t\t\t\t  aeAvailableAntiBandingModes.data(),\n> >>>>> +\t\t\t\t  aeAvailableAntiBandingModes.size());\n> >>>>>\n> >>>>>  \tstd::vector<uint8_t> aeAvailableModes = {\n> >>>>>  \t\tANDROID_CONTROL_AE_MODE_ON,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_MODES,\n> >>>>> -\t\t\taeAvailableModes.data(), aeAvailableModes.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,\n> >>>>> +\t\t\t\t  aeAvailableModes.data(),\n> >>>>> +\t\t\t\t  aeAvailableModes.size());\n> >>>>>\n> >>>>>  \tstd::vector<int32_t> availableAeFpsTarget = {\n> >>>>>  \t\t15, 30,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> >>>>> -\t\t\tavailableAeFpsTarget.data(),\n> >>>>> -\t\t\tavailableAeFpsTarget.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> >>>>> +\t\t\t\t  availableAeFpsTarget.data(),\n> >>>>> +\t\t\t\t  availableAeFpsTarget.size());\n> >>>>>\n> >>>>>  \tstd::vector<int32_t> aeCompensationRange = {\n> >>>>>  \t\t0, 0,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_AE_COMPENSATION_RANGE,\n> >>>>> -\t\t\taeCompensationRange.data(),\n> >>>>> -\t\t\taeCompensationRange.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_RANGE,\n> >>>>> +\t\t\t\t  aeCompensationRange.data(),\n> >>>>> +\t\t\t\t  aeCompensationRange.size());\n> >>>>>\n> >>>>>  \tconst camera_metadata_rational_t aeCompensationStep[] = {\n> >>>>>  \t\t{ 0, 1 }\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_AE_COMPENSATION_STEP,\n> >>>>> -\t\t\taeCompensationStep, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_STEP,\n> >>>>> +\t\t\t\t  aeCompensationStep, 1);\n> >>>>>\n> >>>>>  \tstd::vector<uint8_t> availableAfModes = {\n> >>>>>  \t\tANDROID_CONTROL_AF_MODE_OFF,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_AF_AVAILABLE_MODES,\n> >>>>> -\t\t\tavailableAfModes.data(), availableAfModes.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AF_AVAILABLE_MODES,\n> >>>>> +\t\t\t\t  availableAfModes.data(),\n> >>>>> +\t\t\t\t  availableAfModes.size());\n> >>>>>\n> >>>>>  \tstd::vector<uint8_t> availableEffects = {\n> >>>>>  \t\tANDROID_CONTROL_EFFECT_MODE_OFF,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_AVAILABLE_EFFECTS,\n> >>>>> -\t\t\tavailableEffects.data(), availableEffects.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_EFFECTS,\n> >>>>> +\t\t\t\t  availableEffects.data(),\n> >>>>> +\t\t\t\t  availableEffects.size());\n> >>>>>\n> >>>>>  \tstd::vector<uint8_t> availableSceneModes = {\n> >>>>>  \t\tANDROID_CONTROL_SCENE_MODE_DISABLED,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_AVAILABLE_SCENE_MODES,\n> >>>>> -\t\t\tavailableSceneModes.data(), availableSceneModes.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,\n> >>>>> +\t\t\t\t  availableSceneModes.data(),\n> >>>>> +\t\t\t\t  availableSceneModes.size());\n> >>>>>\n> >>>>>  \tstd::vector<uint8_t> availableStabilizationModes = {\n> >>>>>  \t\tANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,\n> >>>>> -\t\t\tavailableStabilizationModes.data(),\n> >>>>> -\t\t\tavailableStabilizationModes.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,\n> >>>>> +\t\t\t\t  availableStabilizationModes.data(),\n> >>>>> +\t\t\t\t  availableStabilizationModes.size());\n> >>>>>\n> >>>>>  \tstd::vector<uint8_t> availableAwbModes = {\n> >>>>>  \t\tANDROID_CONTROL_AWB_MODE_OFF,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> >>>>> -\t\t\tavailableAwbModes.data(), availableAwbModes.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> >>>>> +\t\t\t\t  availableAwbModes.data(),\n> >>>>> +\t\t\t\t  availableAwbModes.size());\n> >>>>>\n> >>>>>  \tstd::vector<int32_t> availableMaxRegions = {\n> >>>>>  \t\t0, 0, 0,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_MAX_REGIONS,\n> >>>>> -\t\t\tavailableMaxRegions.data(), availableMaxRegions.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_MAX_REGIONS,\n> >>>>> +\t\t\t\t  availableMaxRegions.data(),\n> >>>>> +\t\t\t\t  availableMaxRegions.size());\n> >>>>>\n> >>>>>  \tstd::vector<uint8_t> sceneModesOverride = {\n> >>>>>  \t\tANDROID_CONTROL_AE_MODE_ON,\n> >>>>>  \t\tANDROID_CONTROL_AWB_MODE_AUTO,\n> >>>>>  \t\tANDROID_CONTROL_AF_MODE_AUTO,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_SCENE_MODE_OVERRIDES,\n> >>>>> -\t\t\tsceneModesOverride.data(), sceneModesOverride.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,\n> >>>>> +\t\t\t\t  sceneModesOverride.data(),\n> >>>>> +\t\t\t\t  sceneModesOverride.size());\n> >>>>>\n> >>>>>  \tuint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> >>>>> -\t\t\t&aeLockAvailable, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> >>>>> +\t\t\t\t  &aeLockAvailable, 1);\n> >>>>>\n> >>>>>  \tuint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> >>>>> -\t\t\t&awbLockAvailable, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> >>>>> +\t\t\t\t  &awbLockAvailable, 1);\n> >>>>>\n> >>>>>  \tchar availableControlModes = ANDROID_CONTROL_MODE_AUTO;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_CONTROL_AVAILABLE_MODES,\n> >>>>> -\t\t\t&availableControlModes, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,\n> >>>>> +\t\t\t\t  &availableControlModes, 1);\n> >>>>>\n> >>>>>  \t/* JPEG static metadata. */\n> >>>>>  \tstd::vector<int32_t> availableThumbnailSizes = {\n> >>>>>  \t\t0, 0,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,\n> >>>>> -\t\t\tavailableThumbnailSizes.data(),\n> >>>>> -\t\t\tavailableThumbnailSizes.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,\n> >>>>> +\t\t\t\t  availableThumbnailSizes.data(),\n> >>>>> +\t\t\t\t  availableThumbnailSizes.size());\n> >>>>>\n> >>>>>  \t/* Sensor static metadata. */\n> >>>>>  \tint32_t pixelArraySize[] = {\n> >>>>>  \t\t2592, 1944,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,\n> >>>>> -\t\t\t\t&pixelArraySize, 2);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,\n> >>>>> +\t\t\t\t  &pixelArraySize, 2);\n> >>>>>\n> >>>>>  \tint32_t sensorSizes[] = {\n> >>>>>  \t\t0, 0, 2560, 1920,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,\n> >>>>> -\t\t\t\t&sensorSizes, 4);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,\n> >>>>> +\t\t\t\t  &sensorSizes, 4);\n> >>>>>\n> >>>>>  \tint32_t sensitivityRange[] = {\n> >>>>>  \t\t32, 2400,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_SENSOR_INFO_SENSITIVITY_RANGE,\n> >>>>> -\t\t\t\t&sensitivityRange, 2);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,\n> >>>>> +\t\t\t\t  &sensitivityRange, 2);\n> >>>>>\n> >>>>>  \tuint16_t filterArr = ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,\n> >>>>> -\t\t\t\t&filterArr, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,\n> >>>>> +\t\t\t\t  &filterArr, 1);\n> >>>>>\n> >>>>>  \tint64_t exposureTimeRange[] = {\n> >>>>>  \t\t100000, 200000000,\n> >>>>>  \t};\n> >>>>\n> >>>> I've been thinking for a while to stabilize on the use of std::vector in\n> >>>> place of arrays, so e can always use .data() and .size() and have\n> >>>> guaranteed we should only change the declaration and not the\n> >>>> parameters to the addEntry() operation.\n> >>>>\n> >>>> This might be a good time to do so. What do you think?\n> >>>\n> >>> I've thought about it, and constructing a vector is a bit costly\n> >>> compared to arrays. I'd rather used std::array<>, but that requires\n> >>> specifying the size explicitly :-S I've been thinking about overloading\n> >>> the addEntry() method, in order to be able to write\n> >>>\n> >>> \tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> >>> \t\t\t\t  { 100000, 200000000 });\n> >>>\n> >>> I'm not sure if that will be possible as we need to handle different\n> >>> data types, but I think it's worth a try. Other overloaded methods\n> >>> should also be added for the arrays of a single element:\n> >>>\n> >>> \tstaticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION, 0);\n> >>>\n> >>> I would prefer handling the standardisation of vector vs. array in a\n> >>> separate patch, when dealing with overloaded versions of addEntry(), as\n> >>> this patch is big enough already.\n> >>\n> >> Agreed\n> >>\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> >>>>> -\t\t\t\t&exposureTimeRange, 2);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> >>>>> +\t\t\t\t  &exposureTimeRange, 2);\n> >>>>>\n> >>>>>  \tint32_t orientation = 0;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_SENSOR_ORIENTATION,\n> >>>>> -\t\t\t\t&orientation, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION,\n> >>>>> +\t\t\t\t  &orientation, 1);\n> >>>>\n> >>>> Fits in 1 line\n> >>>\n> >>> I've kept it on two lines to use similar constructs through the whole\n> >>> function, but I don't mind much, so please feel free to change it if you\n> >>> prefer.\n> >>\n> >> If it was intentional, let's keep it the way it is\n> >>\n> >>>>>\n> >>>>>  \tstd::vector<int32_t> testPatterModes = {\n> >>>>>  \t\tANDROID_SENSOR_TEST_PATTERN_MODE_OFF,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,\n> >>>>> -\t\t\t\ttestPatterModes.data(), testPatterModes.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,\n> >>>>> +\t\t\t\t  testPatterModes.data(),\n> >>>>> +\t\t\t\t  testPatterModes.size());\n> >>>>>\n> >>>>>  \tstd::vector<float> physicalSize = {\n> >>>>>  \t\t2592, 1944,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_SENSOR_INFO_PHYSICAL_SIZE,\n> >>>>> -\t\t\t\tphysicalSize.data(), physicalSize.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,\n> >>>>> +\t\t\t\t  physicalSize.data(),\n> >>>>> +\t\t\t\t  physicalSize.size());\n> >>>>\n> >>>> Fits in 1 line\n> >>>>\n> >>>>>\n> >>>>>  \tuint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,\n> >>>>> -\t\t\t&timestampSource, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,\n> >>>>> +\t\t\t\t  &timestampSource, 1);\n> >>>>>\n> >>>>>  \t/* Statistics static metadata. */\n> >>>>>  \tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> >>>>> -\t\t\t&faceDetectMode, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> >>>>> +\t\t\t\t  &faceDetectMode, 1);\n> >>>>>\n> >>>>>  \tint32_t maxFaceCount = 0;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> >>>>> -\t\t\t&maxFaceCount, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> >>>>> +\t\t\t\t  &maxFaceCount, 1);\n> >>>>>\n> >>>>>  \t/* Sync static metadata. */\n> >>>>>  \tint32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);\n> >>>>>\n> >>>>>  \t/* Flash static metadata. */\n> >>>>>  \tchar flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_FLASH_INFO_AVAILABLE,\n> >>>>> -\t\t\t&flashAvailable, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_FLASH_INFO_AVAILABLE,\n> >>>>> +\t\t\t\t  &flashAvailable, 1);\n> >>>>>\n> >>>>>  \t/* Lens static metadata. */\n> >>>>>  \tstd::vector<float> lensApertures = {\n> >>>>>  \t\t2.53 / 100,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_APERTURES,\n> >>>>> -\t\t\t\tlensApertures.data(), lensApertures.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_APERTURES,\n> >>>>> +\t\t\t\t  lensApertures.data(),\n> >>>>> +\t\t\t\t  lensApertures.size());\n> >>>>>\n> >>>>>  \tuint8_t lensFacing = ANDROID_LENS_FACING_FRONT;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_LENS_FACING, &lensFacing, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_LENS_FACING, &lensFacing, 1);\n> >>>>>\n> >>>>>  \tstd::vector<float> lensFocalLenghts = {\n> >>>>>  \t\t1,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,\n> >>>>> -\t\t\t\tlensFocalLenghts.data(),\n> >>>>> -\t\t\t\tlensFocalLenghts.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,\n> >>>>> +\t\t\t\t  lensFocalLenghts.data(),\n> >>>>> +\t\t\t\t  lensFocalLenghts.size());\n> >>>>>\n> >>>>>  \tstd::vector<uint8_t> opticalStabilizations = {\n> >>>>>  \t\tANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,\n> >>>>> -\t\t\t\topticalStabilizations.data(),\n> >>>>> -\t\t\t\topticalStabilizations.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,\n> >>>>> +\t\t\t\t  opticalStabilizations.data(),\n> >>>>> +\t\t\t\t  opticalStabilizations.size());\n> >>>>>\n> >>>>>  \tfloat hypeFocalDistance = 0;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,\n> >>>>> -\t\t\t\t&hypeFocalDistance, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,\n> >>>>> +\t\t\t\t  &hypeFocalDistance, 1);\n> >>>>>\n> >>>>>  \tfloat minFocusDistance = 0;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,\n> >>>>> -\t\t\t\t&minFocusDistance, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,\n> >>>>> +\t\t\t\t  &minFocusDistance, 1);\n> >>>>>\n> >>>>>  \t/* Noise reduction modes. */\n> >>>>>  \tuint8_t noiseReductionModes = ANDROID_NOISE_REDUCTION_MODE_OFF;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\t\tANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,\n> >>>>> -\t\t\t\t&noiseReductionModes, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,\n> >>>>> +\t\t\t\t  &noiseReductionModes, 1);\n> >>>>>\n> >>>>>  \t/* Scaler static metadata. */\n> >>>>>  \tfloat maxDigitalZoom = 1;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,\n> >>>>> -\t\t\t&maxDigitalZoom, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,\n> >>>>> +\t\t\t\t  &maxDigitalZoom, 1);\n> >>>>>\n> >>>>>  \tstd::vector<uint32_t> availableStreamFormats = {\n> >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB,\n> >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888,\n> >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_SCALER_AVAILABLE_FORMATS,\n> >>>>> -\t\t\tavailableStreamFormats.data(),\n> >>>>> -\t\t\tavailableStreamFormats.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_FORMATS,\n> >>>>> +\t\t\t\t  availableStreamFormats.data(),\n> >>>>> +\t\t\t\t  availableStreamFormats.size());\n> >>>>>\n> >>>>>  \tstd::vector<uint32_t> availableStreamConfigurations = {\n> >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920,\n> >>>>> @@ -447,65 +382,57 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920,\n> >>>>>  \t\tANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,\n> >>>>> -\t\t\tavailableStreamConfigurations.data(),\n> >>>>> -\t\t\tavailableStreamConfigurations.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,\n> >>>>> +\t\t\t\t  availableStreamConfigurations.data(),\n> >>>>> +\t\t\t\t  availableStreamConfigurations.size());\n> >>>>>\n> >>>>>  \tstd::vector<int64_t> availableStallDurations = {\n> >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_SCALER_AVAILABLE_STALL_DURATIONS,\n> >>>>> -\t\t\tavailableStallDurations.data(),\n> >>>>> -\t\t\tavailableStallDurations.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,\n> >>>>> +\t\t\t\t  availableStallDurations.data(),\n> >>>>> +\t\t\t\t  availableStallDurations.size());\n> >>>>>\n> >>>>>  \tstd::vector<int64_t> minFrameDurations = {\n> >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,\n> >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920, 33333333,\n> >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888, 2560, 1920, 33333333,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> >>>>> -\t\t\tminFrameDurations.data(), minFrameDurations.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> >>>>> +\t\t\t\t  minFrameDurations.data(),\n> >>>>> +\t\t\t\t  minFrameDurations.size());\n> >>>>>\n> >>>>>  \tuint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);\n> >>>>>\n> >>>>>  \t/* Info static metadata. */\n> >>>>>  \tuint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> >>>>> -\t\t\t&supportedHWLevel, 1);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> >>>>> +\t\t\t\t  &supportedHWLevel, 1);\n> >>>>>\n> >>>>>  \t/* Request static metadata. */\n> >>>>>  \tint32_t partialResultCount = 1;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> >>>>> -\t\t\t&partialResultCount, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> >>>>> +\t\t\t\t  &partialResultCount, 1);\n> >>>>>\n> >>>>>  \tuint8_t maxPipelineDepth = 2;\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_REQUEST_PIPELINE_MAX_DEPTH,\n> >>>>> -\t\t\t&maxPipelineDepth, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_PIPELINE_MAX_DEPTH,\n> >>>>> +\t\t\t\t  &maxPipelineDepth, 1);\n> >>>>>\n> >>>>>  \tstd::vector<uint8_t> availableCapabilities = {\n> >>>>>  \t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> >>>>> -\t\t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> >>>>> -\t\t\tavailableCapabilities.data(),\n> >>>>> -\t\t\tavailableCapabilities.size());\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> >>>>> +\t\t\t\t  availableCapabilities.data(),\n> >>>>> +\t\t\t\t  availableCapabilities.size());\n> >>>>> +\n> >>>>> +\tif (!staticMetadata_->isValid()) {\n> >>>>> +\t\tdelete staticMetadata_;\n> >>>>> +\t\tstaticMetadata_ = nullptr;\n> >>>>> +\t\treturn nullptr;\n> >>>>> +\t}\n> >>>>>\n> >>>>> -\treturn staticMetadata_;\n> >>>>> +\treturn staticMetadata_->get();\n> >>>>>  }\n> >>>>>\n> >>>>>  /*\n> >>>>> @@ -513,8 +440,6 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> >>>>>   */\n> >>>>>  const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)\n> >>>>>  {\n> >>>>> -\tint ret;\n> >>>>> -\n> >>>>>  \t/*\n> >>>>>  \t * \\todo Inspect type and pick the right metadata pack.\n> >>>>>  \t * As of now just use a single one for all templates.\n> >>>>> @@ -545,89 +470,73 @@ const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)\n> >>>>>  \t}\n> >>>>>\n> >>>>>  \tif (requestTemplate_)\n> >>>>> -\t\treturn requestTemplate_;\n> >>>>> +\t\treturn requestTemplate_->get();\n> >>>>>\n> >>>>>  \t/*\n> >>>>>  \t * \\todo Keep this in sync with the actual number of entries.\n> >>>>>  \t * Currently: 12 entries, 15 bytes\n> >>>>>  \t */\n> >>>>> -\trequestTemplate_ = allocate_camera_metadata(15, 20);\n> >>>>> +\trequestTemplate_ = new CameraMetadata(15, 20);\n> >>>>>  \tif (!requestTemplate_) {\n> >>>>>  \t\tLOG(HAL, Error) << \"Failed to allocate template metadata\";\n> >>>>> +\t\tdelete requestTemplate_;\n> >>>>> +\t\trequestTemplate_ = nullptr;\n> >>>>\n> >>>> Empty line before return ?\n> >>>>\n> >>>>>  \t\treturn nullptr;\n> >>>>>  \t}\n> >>>>>\n> >>>>>  \tuint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;\n> >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>>>> -\t\t\tANDROID_CONTROL_AE_MODE,\n> >>>>> -\t\t\t&aeMode, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_MODE,\n> >>>>> +\t\t\t\t   &aeMode, 1);\n> >>>>\n> >>>> This and many others entries here and below fit in 1 line.\n> >>>>\n> >>>>>\n> >>>>>  \tint32_t aeExposureCompensation = 0;\n> >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>>>> -\t\t\tANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,\n> >>>>> -\t\t\t&aeExposureCompensation, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,\n> >>>>> +\t\t\t\t   &aeExposureCompensation, 1);\n> >>>>>\n> >>>>>  \tuint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;\n> >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>>>> -\t\t\tANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,\n> >>>>> -\t\t\t&aePrecaptureTrigger, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,\n> >>>>> +\t\t\t\t   &aePrecaptureTrigger, 1);\n> >>>>>\n> >>>>>  \tuint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;\n> >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>>>> -\t\t\tANDROID_CONTROL_AE_LOCK,\n> >>>>> -\t\t\t&aeLock, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_LOCK,\n> >>>>> +\t\t\t\t   &aeLock, 1);\n> >>>>>\n> >>>>>  \tuint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;\n> >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>>>> -\t\t\tANDROID_CONTROL_AF_TRIGGER,\n> >>>>> -\t\t\t&afTrigger, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AF_TRIGGER,\n> >>>>> +\t\t\t\t   &afTrigger, 1);\n> >>>>>\n> >>>>>  \tuint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;\n> >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>>>> -\t\t\tANDROID_CONTROL_AWB_MODE,\n> >>>>> -\t\t\t&awbMode, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AWB_MODE,\n> >>>>> +\t\t\t\t   &awbMode, 1);\n> >>>>>\n> >>>>>  \tuint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;\n> >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>>>> -\t\t\tANDROID_CONTROL_AWB_LOCK,\n> >>>>> -\t\t\t&awbLock, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AWB_LOCK,\n> >>>>> +\t\t\t\t   &awbLock, 1);\n> >>>>>\n> >>>>>  \tuint8_t flashMode = ANDROID_FLASH_MODE_OFF;\n> >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>>>> -\t\t\tANDROID_FLASH_MODE,\n> >>>>> -\t\t\t&flashMode, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\trequestTemplate_->addEntry(ANDROID_FLASH_MODE,\n> >>>>> +\t\t\t\t   &flashMode, 1);\n> >>>>>\n> >>>>>  \tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>>>> -\t\t\tANDROID_STATISTICS_FACE_DETECT_MODE,\n> >>>>> -\t\t\t&faceDetectMode, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\trequestTemplate_->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,\n> >>>>> +\t\t\t\t   &faceDetectMode, 1);\n> >>>>>\n> >>>>>  \tuint8_t noiseReduction = ANDROID_NOISE_REDUCTION_MODE_OFF;\n> >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>>>> -\t\t\tANDROID_NOISE_REDUCTION_MODE, &noiseReduction, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\trequestTemplate_->addEntry(ANDROID_NOISE_REDUCTION_MODE,\n> >>>>> +\t\t\t\t   &noiseReduction, 1);\n> >>>>>\n> >>>>>  \tuint8_t aberrationMode = ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF;\n> >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>>>> -\t\t\tANDROID_COLOR_CORRECTION_ABERRATION_MODE,\n> >>>>> -\t\t\t&aberrationMode, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\trequestTemplate_->addEntry(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,\n> >>>>> +\t\t\t\t   &aberrationMode, 1);\n> >>>>> +\n> >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_CAPTURE_INTENT,\n> >>>>> +\t\t\t\t   &captureIntent, 1);\n> >>>>>\n> >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> >>>>> -\t\t\tANDROID_CONTROL_CAPTURE_INTENT,\n> >>>>> -\t\t\t&captureIntent, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tif (!requestTemplate_->isValid()) {\n> >>>>> +\t\tdelete requestTemplate_;\n> >>>>> +\t\trequestTemplate_ = nullptr;\n> >>>>\n> >>>> You should return nullptr here, otherwise the below requestTemplate_->get();\n> >>>> will de-reference a nullptr.\n> >>>\n> >>> Absolutely, my bad.\n> >>>\n> >>>>> +\t}\n> >>>>>\n> >>>>> -\treturn requestTemplate_;\n> >>>>> +\treturn requestTemplate_->get();\n> >>>>>  }\n> >>>>>\n> >>>>>  /*\n> >>>>> @@ -799,7 +708,7 @@ void CameraDevice::requestComplete(Request *request,\n> >>>>>  {\n> >>>>>  \tBuffer *libcameraBuffer = buffers.begin()->second;\n> >>>>>  \tcamera3_buffer_status status = CAMERA3_BUFFER_STATUS_OK;\n> >>>>> -\tcamera_metadata_t *resultMetadata = nullptr;\n> >>>>> +\tstd::unique_ptr<CameraMetadata> resultMetadata;\n> >>>>>\n> >>>>>  \tif (request->status() != Request::RequestComplete) {\n> >>>>>  \t\tLOG(HAL, Error) << \"Request not succesfully completed: \"\n> >>>>> @@ -837,16 +746,12 @@ void CameraDevice::requestComplete(Request *request,\n> >>>>>  \t\tcaptureResult.partial_result = 1;\n> >>>>>  \t\tresultMetadata = getResultMetadata(descriptor->frameNumber,\n> >>>>>  \t\t\t\t\t\t   libcameraBuffer->timestamp());\n> >>>>> -\t\tcaptureResult.result = resultMetadata;\n> >>>>> +\t\tcaptureResult.result = resultMetadata->get();\n> >>>>>  \t}\n> >>>>>\n> >>>>>  \tcallbacks_->process_capture_result(callbacks_, &captureResult);\n> >>>>>\n> >>>>>  \tdelete descriptor;\n> >>>>> -\tif (resultMetadata)\n> >>>>> -\t\tfree_camera_metadata(resultMetadata);\n> >>>>> -\n> >>>>> -\treturn;\n> >>>>>  }\n> >>>>>\n> >>>>>  void CameraDevice::notifyShutter(uint32_t frameNumber, uint64_t timestamp)\n> >>>>> @@ -875,89 +780,63 @@ void CameraDevice::notifyError(uint32_t frameNumber, camera3_stream_t *stream)\n> >>>>>  /*\n> >>>>>   * Produce a set of fixed result metadata.\n> >>>>>   */\n> >>>>> -camera_metadata_t *CameraDevice::getResultMetadata(int frame_number,\n> >>>>> -\t\t\t\t\t\t   int64_t timestamp)\n> >>>>> +std::unique_ptr<CameraMetadata> CameraDevice::getResultMetadata(int frame_number,\n> >>>>\n> >>>> Not a fan of smart pointers, you know already. How does this work?\n> >>>> Because the compiler applies copy-elision or because of the move\n> >>>> semantic applied on the return value?\n> >>>\n> >>> std::unique_ptr<> has an operator= that takes an rvalue reference to\n> >>> another std::unique_ptr<>, and uses move semantic. As explained in\n> >>> https://en.cppreference.com/w/cpp/language/value_category, an rvalue is\n> >>> either a prvalue or an xvalue, and a prvalue can be \"a function call or\n> >>> an overloaded operator expression, whose return type is non-reference\".\n> >>> As far as I can tell, that's why we don't need an std::move() in the\n> >>> caller.\n> >>\n> >> I see.. This seems to suggest both RVO and move semantic can play a\n> >> role https://stackoverflow.com/a/46571941\n> >>\n> >> Ah, c++\n> >>\n> >>>> difficult to follow in my opinion.\n> >>>\n> >>> I think we should standardise as much as possible on std::unique_ptr<>\n> >>> when passing ownership of a returned pointer. That's documented in\n> >>> Documentation/coding-style.rst.\n> >>\n> >> Ack, let's keep it the way it is then.\n> >>\n> >>>>> +\t\t\t\t\t\t\t\tint64_t timestamp)\n> >>>>>  {\n> >>>>> -\tint ret;\n> >>>>> -\n> >>>>>  \t/*\n> >>>>>  \t * \\todo Keep this in sync with the actual number of entries.\n> >>>>>  \t * Currently: 13 entries, 36 bytes\n> >>>>>  \t */\n> >>>>> -\tcamera_metadata_t *resultMetadata = allocate_camera_metadata(15, 50);\n> >>>>> +\tstd::unique_ptr<CameraMetadata> resultMetadata =\n> >>>>> +\t\tutils::make_unique<CameraMetadata>(15, 50);\n> >>>>> +\tif (!resultMetadata->isValid()) {\n> >>>>> +\t\tLOG(HAL, Error) << \"Failed to allocate static metadata\";\n> >>>>> +\t\treturn nullptr;\n> >>>>> +\t}\n> >>>>>\n> >>>>>  \tconst uint8_t ae_state = ANDROID_CONTROL_AE_STATE_CONVERGED;\n> >>>>> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AE_STATE,\n> >>>>> -\t\t\t\t\t&ae_state, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AE_STATE, &ae_state, 1);\n> >>>>>\n> >>>>>  \tconst uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;\n> >>>>> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AE_LOCK,\n> >>>>> -\t\t\t\t\t&ae_lock, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);\n> >>>>>\n> >>>>>  \tuint8_t af_state = ANDROID_CONTROL_AF_STATE_INACTIVE;\n> >>>>> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AF_STATE,\n> >>>>> -\t\t\t\t\t&af_state, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AF_STATE, &af_state, 1);\n> >>>>>\n> >>>>>  \tconst uint8_t awb_state = ANDROID_CONTROL_AWB_STATE_CONVERGED;\n> >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>>>> -\t\t\t\t\tANDROID_CONTROL_AWB_STATE,\n> >>>>> -\t\t\t\t\t&awb_state, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AWB_STATE, &awb_state, 1);\n> >>>>>\n> >>>>>  \tconst uint8_t awb_lock = ANDROID_CONTROL_AWB_LOCK_OFF;\n> >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>>>> -\t\t\t\t\tANDROID_CONTROL_AWB_LOCK,\n> >>>>> -\t\t\t\t\t&awb_lock, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AWB_LOCK, &awb_lock, 1);\n> >>>>>\n> >>>>>  \tconst uint8_t lens_state = ANDROID_LENS_STATE_STATIONARY;\n> >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>>>> -\t\t\t\t\tANDROID_LENS_STATE,\n> >>>>> -\t\t\t\t\t&lens_state, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tresultMetadata->addEntry(ANDROID_LENS_STATE, &lens_state, 1);\n> >>>>>\n> >>>>>  \tint32_t sensorSizes[] = {\n> >>>>>  \t\t0, 0, 2560, 1920,\n> >>>>>  \t};\n> >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>>>> -\t\t\t\t\tANDROID_SCALER_CROP_REGION,\n> >>>>> -\t\t\t\t\tsensorSizes, 4);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tresultMetadata->addEntry(ANDROID_SCALER_CROP_REGION, sensorSizes, 4);\n> >>>>>\n> >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>>>> -\t\t\t\t\tANDROID_SENSOR_TIMESTAMP,\n> >>>>> -\t\t\t\t\t&timestamp, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tresultMetadata->addEntry(ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);\n> >>>>>\n> >>>>>  \t/* 33.3 msec */\n> >>>>>  \tconst int64_t rolling_shutter_skew = 33300000;\n> >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>>>> -\t\t\t\t\tANDROID_SENSOR_ROLLING_SHUTTER_SKEW,\n> >>>>> -\t\t\t\t\t&rolling_shutter_skew, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tresultMetadata->addEntry(ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,\n> >>>>> +\t\t\t\t &rolling_shutter_skew, 1);\n> >>>>>\n> >>>>>  \t/* 16.6 msec */\n> >>>>>  \tconst int64_t exposure_time = 16600000;\n> >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>>>> -\t\t\t\t\tANDROID_SENSOR_EXPOSURE_TIME,\n> >>>>> -\t\t\t\t\t&exposure_time, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tresultMetadata->addEntry(ANDROID_SENSOR_EXPOSURE_TIME,\n> >>>>> +\t\t\t\t &exposure_time, 1);\n> >>>>>\n> >>>>>  \tconst uint8_t lens_shading_map_mode =\n> >>>>>  \t\t\t\tANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;\n> >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>>>> -\t\t\t\t\tANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> >>>>> -\t\t\t\t\t&lens_shading_map_mode, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tresultMetadata->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> >>>>> +\t\t\t\t &lens_shading_map_mode, 1);\n> >>>>>\n> >>>>>  \tconst uint8_t scene_flicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE;\n> >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> >>>>> -\t\t\t\t\tANDROID_STATISTICS_SCENE_FLICKER,\n> >>>>> -\t\t\t\t\t&scene_flicker, 1);\n> >>>>> -\tMETADATA_ASSERT(ret);\n> >>>>> +\tresultMetadata->addEntry(ANDROID_STATISTICS_SCENE_FLICKER,\n> >>>>> +\t\t\t\t &scene_flicker, 1);\n> >>>>\n> >>>> Shouldn't you check if the metadata pack is valid ?\n> >>>\n> >>> Good point. Should we check here or in the caller ? As the caller would\n> >>> then need a nullptr check I'm tempted to do so in the caller. Actually,\n> >>> without a change to the code, the caller will operate correctly I\n> >>> believe\n> >>>\n> >>>                 resultMetadata = getResultMetadata(descriptor->frameNumber,\n> >>>                                                    libcameraBuffer->timestamp());\n> >>>                 captureResult.result = resultMetadata->get();\n> >>>\n> >>> which will set captureResult.result to nullptr if resultMetadata is not\n> >>> valid.\n> >>\n> >> Yeah, but in that case we should notify an error back to the stack.\n> >\n> > That makes sense. It should be a faily uncommon case though, is it would\n> > be the result of a bug in our code, but bugs happen. I wonder what the\n> > proper error recovery would be in that case.\n> >\n> >> What about:\n> >>\n> >>         resultMetadata = getResultMetadata(descriptor->frameNumber,\n> >>                                            libcameraBuffer->timestamp());\n> >> \tif (status == CAMERA3_BUFFER_STATUS_ERROR || !resultMetadata) {\n> >> \t\t/* \\todo Improve error handling. */\n> >> \t\tnotifyError(descriptor->frameNumber,\n> >> \t\t\t    descriptor->buffers[0].stream);\n> >> \t} else {\n> >> \t\tnotifyShutter(descriptor->frameNumber,\n> >> \t\t\t      libcameraBuffer->timestamp());\n> >>\n> >> \t\tcaptureResult.partial_result = 1;\n> >> \t\tcaptureResult.result = resultMetadata->get();\n> >> \t}\n> >>\n> >> The drawback is that we're generating the result metadata even if\n> >> status is set to CAMERA3_BUFFER_STATUS_ERROR.\n> >\n> > That I don't think we should do, as I expect the result metadata\n> > generation will not be possible in case of CAMERA3_BUFFER_STATUS_ERROR\n> > when we'll stop generating fake metadata.\n> >\n> > How about this ?\n> >\n> > \tif (status == CAMERA3_BUFFER_STATUS_OK) {\n> > \t\tnotifyShutter(descriptor->frameNumber,\n> > \t\t\t      libcameraBuffer->timestamp());\n> >\n> > \t\tcaptureResult.partial_result = 1;\n> > \t\tresultMetadata = getResultMetadata(descriptor->frameNumber,\n> > \t\t\t\t\t\t   libcameraBuffer->timestamp());\n> > \t\tcaptureResult.result = resultMetadata->get();\n> > \t}\n> >\n> > \tif (status == CAMERA3_BUFFER_STATUS_ERROR || !captureResult.result) {\n> > \t\t/* \\todo Improve error handling. */\n> > \t\tnotifyError(descriptor->frameNumber,\n> > \t\t\t    descriptor->buffers[0].stream);\n> > \t}\n> >\n> > The last condition could be written if (!captureResult.result) as\n> > CAMERA3_BUFFER_STATUS_ERROR implies !captureResult.result, but I'd\n> > rather have both to make it explicit.\n> \n> The only difference I see here is that we send up a shutter event and\n> the if metadata generation fails we send back an error.\n> \n> In the previous version was either an error or the shutter\n> notification, not both.\n> \n> I can't tell if this makes any difference to the camera stack to be\n> honest.\n\nNeither can I, and this shouldn't happen in the first place :-) If you\nwant to avoid it,\n\n \tif (status == CAMERA3_BUFFER_STATUS_OK) {\n \t\tcaptureResult.partial_result = 1;\n \t\tresultMetadata = getResultMetadata(descriptor->frameNumber,\n \t\t\t\t\t\t   libcameraBuffer->timestamp());\n \t\tcaptureResult.result = resultMetadata->get();\n \t}\n\n \tif (status == CAMERA3_BUFFER_STATUS_OK && captureResult.result) {\n \t\tnotifyShutter(descriptor->frameNumber,\n \t\t\t      libcameraBuffer->timestamp());\n\t} else {\n \t\t/* \\todo Improve error handling. */\n \t\tnotifyError(descriptor->frameNumber,\n \t\t\t    descriptor->buffers[0].stream);\n \t}\n\n> >>>>>\n> >>>>>  \treturn resultMetadata;\n> >>>>>  }\n> >>>>> diff --git a/src/android/camera_device.h b/src/android/camera_device.h\n> >>>>> index 7897ba9dc5c7..65ba877a02ea 100644\n> >>>>> --- a/src/android/camera_device.h\n> >>>>> +++ b/src/android/camera_device.h\n> >>>>> @@ -19,13 +19,7 @@\n> >>>>>\n> >>>>>  #include \"message.h\"\n> >>>>>\n> >>>>> -#define METADATA_ASSERT(_r)\t\t\\\n> >>>>> -\tdo {\t\t\t\t\\\n> >>>>> -\t\tif (!(_r)) break;\t\\\n> >>>>> -\t\tLOG(HAL, Error) << \"Error: \" << __func__ << \":\" << __LINE__; \\\n> >>>>> -\t\treturn nullptr;\t\t\\\n> >>>>> -\t} while(0);\n> >>>>> -\n> >>>>> +class CameraMetadata;\n> >>>>>  class ThreadRpc;\n> >>>>>\n> >>>>>  class CameraDevice : public libcamera::Object\n> >>>>> @@ -59,14 +53,15 @@ private:\n> >>>>>\n> >>>>>  \tvoid notifyShutter(uint32_t frameNumber, uint64_t timestamp);\n> >>>>>  \tvoid notifyError(uint32_t frameNumber, camera3_stream_t *stream);\n> >>>>> -\tcamera_metadata_t *getResultMetadata(int frame_number, int64_t timestamp);\n> >>>>> +\tstd::unique_ptr<CameraMetadata> getResultMetadata(int frame_number,\n> >>>>> +\t\t\t\t\t\t\t  int64_t timestamp);\n> >>>>>\n> >>>>>  \tbool running_;\n> >>>>>  \tstd::shared_ptr<libcamera::Camera> camera_;\n> >>>>>  \tstd::unique_ptr<libcamera::CameraConfiguration> config_;\n> >>>>>\n> >>>>> -\tcamera_metadata_t *staticMetadata_;\n> >>>>> -\tcamera_metadata_t *requestTemplate_;\n> >>>>> +\tCameraMetadata *staticMetadata_;\n> >>>>> +\tCameraMetadata *requestTemplate_;\n> >>>>>  \tconst camera3_callback_ops_t *callbacks_;\n> >>>>>  };\n> >>>>>","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6F64960C18\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 Sep 2019 22:39:24 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(dfj612yhrgyx302h3jwwy-3.rev.dnainternet.fi\n\t[IPv6:2001:14ba:21f5:5b00:ce28:277f:58d7:3ca4])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id C436DE3C;\n\tThu,  5 Sep 2019 22:39:23 +0200 (CEST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1567715964;\n\tbh=UUmY4Iz75Braa/kzVha5hlUsPV23IgmUCVZDlPT+O+w=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=dFSJgSH70uvpFjlML34NWTINyAomCbDwjd2HQ4XUhNlyYm18HJ3AsHkYGiXviy7fO\n\tJmAnsEkrllThkf/w1RAhKfyrUgjENATEkrYv18hzvdBbg5k6UjpEI7iZ0a0+DaTP6V\n\tX6N68HVcD2JggPLIqBU3R7TPTQlxb+cGuxOacS9s=","Date":"Thu, 5 Sep 2019 23:39:17 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190905203917.GP5035@pendragon.ideasonboard.com>","References":"<20190905074737.6955-1-jacopo@jmondi.org>\n\t<20190905074737.6955-8-jacopo@jmondi.org>\n\t<20190905081828.y647dyfqg2apejjp@uno.localdomain>\n\t<20190905093657.GA5035@pendragon.ideasonboard.com>\n\t<20190905095205.333n5sof5rjimsaf@uno.localdomain>\n\t<20190905100259.GE5035@pendragon.ideasonboard.com>\n\t<20190905202503.bv3uwn66fdetfvii@uno.localdomain>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20190905202503.bv3uwn66fdetfvii@uno.localdomain>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH v6 7/9] android: camera_device: Use\n\tthe new CameraMetadata helper class","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Thu, 05 Sep 2019 20:39:24 -0000"}},{"id":2624,"web_url":"https://patchwork.libcamera.org/comment/2624/","msgid":"<20190905212007.f2hehmb6hfh5fxcq@uno.localdomain>","date":"2019-09-05T21:20:07","subject":"Re: [libcamera-devel] [PATCH v6 7/9] android: camera_device: Use\n\tthe new CameraMetadata helper class","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Laurent,\n\nOn Thu, Sep 05, 2019 at 11:39:17PM +0300, Laurent Pinchart wrote:\n> Hi Jacopo,\n>\n> On Thu, Sep 05, 2019 at 10:25:03PM +0200, Jacopo Mondi wrote:\n> > On Thu, Sep 05, 2019 at 01:02:59PM +0300, Laurent Pinchart wrote:\n> > > On Thu, Sep 05, 2019 at 11:52:05AM +0200, Jacopo Mondi wrote:\n> > >> On Thu, Sep 05, 2019 at 12:36:57PM +0300, Laurent Pinchart wrote:\n> > >>> On Thu, Sep 05, 2019 at 10:18:28AM +0200, Jacopo Mondi wrote:\n> > >>>> On Thu, Sep 05, 2019 at 09:47:34AM +0200, Jacopo Mondi wrote:\n> > >>>>> From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > >>>>>\n> > >>>>> Simplify the implementation of metadata handling in the CameraDevice\n> > >>>>> class by using the new CameraMetadata helper class.\n> > >>>>>\n> > >>>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > >>>>> ---\n> > >>>>>  src/android/camera_device.cpp | 507 +++++++++++++---------------------\n> > >>>>>  src/android/camera_device.h   |  15 +-\n> > >>>>>  2 files changed, 198 insertions(+), 324 deletions(-)\n> > >>>>>\n> > >>>>> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n> > >>>>> index 5f8d19b9ef3d..475fa2404421 100644\n> > >>>>> --- a/src/android/camera_device.cpp\n> > >>>>> +++ b/src/android/camera_device.cpp\n> > >>>>> @@ -7,10 +7,10 @@\n> > >>>>>\n> > >>>>>  #include \"camera_device.h\"\n> > >>>>>\n> > >>>>> -#include <system/camera_metadata.h>\n> > >>>>> -\n> > >>>>>  #include \"log.h\"\n> > >>>>> +#include \"utils.h\"\n> > >>>>>\n> > >>>>> +#include \"camera_metadata.h\"\n> > >>>>>  #include \"thread_rpc.h\"\n> > >>>>>\n> > >>>>>  using namespace libcamera;\n> > >>>>> @@ -59,12 +59,10 @@ CameraDevice::CameraDevice(unsigned int id, const std::shared_ptr<Camera> &camer\n> > >>>>>  CameraDevice::~CameraDevice()\n> > >>>>>  {\n> > >>>>>  \tif (staticMetadata_)\n> > >>>>> -\t\tfree_camera_metadata(staticMetadata_);\n> > >>>>> -\tstaticMetadata_ = nullptr;\n> > >>>>> +\t\tdelete staticMetadata_;\n> > >>>>>\n> > >>>>>  \tif (requestTemplate_)\n> > >>>>> -\t\tfree_camera_metadata(requestTemplate_);\n> > >>>>> -\trequestTemplate_ = nullptr;\n> > >>>>> +\t\tdelete requestTemplate_;\n> > >>>>>  }\n> > >>>>>\n> > >>>>>  /*\n> > >>>>> @@ -117,10 +115,8 @@ void CameraDevice::setCallbacks(const camera3_callback_ops_t *callbacks)\n> > >>>>>   */\n> > >>>>>  camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >>>>>  {\n> > >>>>> -\tint ret;\n> > >>>>> -\n> > >>>>>  \tif (staticMetadata_)\n> > >>>>> -\t\treturn staticMetadata_;\n> > >>>>> +\t\treturn staticMetadata_->get();\n> > >>>>>\n> > >>>>>  \t/*\n> > >>>>>  \t * The here reported metadata are enough to implement a basic capture\n> > >>>>> @@ -132,16 +128,21 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >>>>>  \t * \\todo Keep this in sync with the actual number of entries.\n> > >>>>>  \t * Currently: 46 entries, 390 bytes\n> > >>>>>  \t */\n> > >>>>> -\tstaticMetadata_ = allocate_camera_metadata(50, 500);\n> > >>>>> +\tstaticMetadata_ = new CameraMetadata(50, 500);\n> > >>>>> +\tif (!staticMetadata_->isValid()) {\n> > >>>>> +\t\tLOG(HAL, Error) << \"Failed to allocate static metadata\";\n> > >>>>> +\t\tdelete staticMetadata_;\n> > >>>>> +\t\tstaticMetadata_ = nullptr;\n> > >>>>> +\t\treturn nullptr;\n> > >>>>\n> > >>>> Empty line before return?\n> > >>>\n> > >>> I don't mind either way, but I haven't added one as the delete,\n> > >>> assignment to nullptr and return nullptr are logically grouped in my\n> > >>> opinion. Feel free to add a blank line if you prefer.\n> > >>\n> > >> Ok, if this was intentional let's keep it the way it is.\n> > >>\n> > >>>>> +\t}\n> > >>>>>\n> > >>>>>  \t/* Color correction static metadata. */\n> > >>>>>  \tstd::vector<uint8_t> aberrationModes = {\n> > >>>>>  \t\tANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> > >>>>> -\t\t\taberrationModes.data(), aberrationModes.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,\n> > >>>>> +\t\t\t\t  aberrationModes.data(),\n> > >>>>> +\t\t\t\t  aberrationModes.size());\n> > >>>>>\n> > >>>>>  \t/* Control static metadata. */\n> > >>>>>  \tstd::vector<uint8_t> aeAvailableAntiBandingModes = {\n> > >>>>> @@ -150,294 +151,228 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >>>>>  \t\tANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,\n> > >>>>>  \t\tANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,\n> > >>>>> -\t\t\taeAvailableAntiBandingModes.data(),\n> > >>>>> -\t\t\taeAvailableAntiBandingModes.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,\n> > >>>>> +\t\t\t\t  aeAvailableAntiBandingModes.data(),\n> > >>>>> +\t\t\t\t  aeAvailableAntiBandingModes.size());\n> > >>>>>\n> > >>>>>  \tstd::vector<uint8_t> aeAvailableModes = {\n> > >>>>>  \t\tANDROID_CONTROL_AE_MODE_ON,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_MODES,\n> > >>>>> -\t\t\taeAvailableModes.data(), aeAvailableModes.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_MODES,\n> > >>>>> +\t\t\t\t  aeAvailableModes.data(),\n> > >>>>> +\t\t\t\t  aeAvailableModes.size());\n> > >>>>>\n> > >>>>>  \tstd::vector<int32_t> availableAeFpsTarget = {\n> > >>>>>  \t\t15, 30,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> > >>>>> -\t\t\tavailableAeFpsTarget.data(),\n> > >>>>> -\t\t\tavailableAeFpsTarget.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,\n> > >>>>> +\t\t\t\t  availableAeFpsTarget.data(),\n> > >>>>> +\t\t\t\t  availableAeFpsTarget.size());\n> > >>>>>\n> > >>>>>  \tstd::vector<int32_t> aeCompensationRange = {\n> > >>>>>  \t\t0, 0,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AE_COMPENSATION_RANGE,\n> > >>>>> -\t\t\taeCompensationRange.data(),\n> > >>>>> -\t\t\taeCompensationRange.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_RANGE,\n> > >>>>> +\t\t\t\t  aeCompensationRange.data(),\n> > >>>>> +\t\t\t\t  aeCompensationRange.size());\n> > >>>>>\n> > >>>>>  \tconst camera_metadata_rational_t aeCompensationStep[] = {\n> > >>>>>  \t\t{ 0, 1 }\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AE_COMPENSATION_STEP,\n> > >>>>> -\t\t\taeCompensationStep, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_COMPENSATION_STEP,\n> > >>>>> +\t\t\t\t  aeCompensationStep, 1);\n> > >>>>>\n> > >>>>>  \tstd::vector<uint8_t> availableAfModes = {\n> > >>>>>  \t\tANDROID_CONTROL_AF_MODE_OFF,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AF_AVAILABLE_MODES,\n> > >>>>> -\t\t\tavailableAfModes.data(), availableAfModes.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AF_AVAILABLE_MODES,\n> > >>>>> +\t\t\t\t  availableAfModes.data(),\n> > >>>>> +\t\t\t\t  availableAfModes.size());\n> > >>>>>\n> > >>>>>  \tstd::vector<uint8_t> availableEffects = {\n> > >>>>>  \t\tANDROID_CONTROL_EFFECT_MODE_OFF,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AVAILABLE_EFFECTS,\n> > >>>>> -\t\t\tavailableEffects.data(), availableEffects.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_EFFECTS,\n> > >>>>> +\t\t\t\t  availableEffects.data(),\n> > >>>>> +\t\t\t\t  availableEffects.size());\n> > >>>>>\n> > >>>>>  \tstd::vector<uint8_t> availableSceneModes = {\n> > >>>>>  \t\tANDROID_CONTROL_SCENE_MODE_DISABLED,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AVAILABLE_SCENE_MODES,\n> > >>>>> -\t\t\tavailableSceneModes.data(), availableSceneModes.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,\n> > >>>>> +\t\t\t\t  availableSceneModes.data(),\n> > >>>>> +\t\t\t\t  availableSceneModes.size());\n> > >>>>>\n> > >>>>>  \tstd::vector<uint8_t> availableStabilizationModes = {\n> > >>>>>  \t\tANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,\n> > >>>>> -\t\t\tavailableStabilizationModes.data(),\n> > >>>>> -\t\t\tavailableStabilizationModes.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,\n> > >>>>> +\t\t\t\t  availableStabilizationModes.data(),\n> > >>>>> +\t\t\t\t  availableStabilizationModes.size());\n> > >>>>>\n> > >>>>>  \tstd::vector<uint8_t> availableAwbModes = {\n> > >>>>>  \t\tANDROID_CONTROL_AWB_MODE_OFF,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> > >>>>> -\t\t\tavailableAwbModes.data(), availableAwbModes.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AWB_AVAILABLE_MODES,\n> > >>>>> +\t\t\t\t  availableAwbModes.data(),\n> > >>>>> +\t\t\t\t  availableAwbModes.size());\n> > >>>>>\n> > >>>>>  \tstd::vector<int32_t> availableMaxRegions = {\n> > >>>>>  \t\t0, 0, 0,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_MAX_REGIONS,\n> > >>>>> -\t\t\tavailableMaxRegions.data(), availableMaxRegions.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_MAX_REGIONS,\n> > >>>>> +\t\t\t\t  availableMaxRegions.data(),\n> > >>>>> +\t\t\t\t  availableMaxRegions.size());\n> > >>>>>\n> > >>>>>  \tstd::vector<uint8_t> sceneModesOverride = {\n> > >>>>>  \t\tANDROID_CONTROL_AE_MODE_ON,\n> > >>>>>  \t\tANDROID_CONTROL_AWB_MODE_AUTO,\n> > >>>>>  \t\tANDROID_CONTROL_AF_MODE_AUTO,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_SCENE_MODE_OVERRIDES,\n> > >>>>> -\t\t\tsceneModesOverride.data(), sceneModesOverride.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_SCENE_MODE_OVERRIDES,\n> > >>>>> +\t\t\t\t  sceneModesOverride.data(),\n> > >>>>> +\t\t\t\t  sceneModesOverride.size());\n> > >>>>>\n> > >>>>>  \tuint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> > >>>>> -\t\t\t&aeLockAvailable, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AE_LOCK_AVAILABLE,\n> > >>>>> +\t\t\t\t  &aeLockAvailable, 1);\n> > >>>>>\n> > >>>>>  \tuint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> > >>>>> -\t\t\t&awbLockAvailable, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,\n> > >>>>> +\t\t\t\t  &awbLockAvailable, 1);\n> > >>>>>\n> > >>>>>  \tchar availableControlModes = ANDROID_CONTROL_MODE_AUTO;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AVAILABLE_MODES,\n> > >>>>> -\t\t\t&availableControlModes, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_CONTROL_AVAILABLE_MODES,\n> > >>>>> +\t\t\t\t  &availableControlModes, 1);\n> > >>>>>\n> > >>>>>  \t/* JPEG static metadata. */\n> > >>>>>  \tstd::vector<int32_t> availableThumbnailSizes = {\n> > >>>>>  \t\t0, 0,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,\n> > >>>>> -\t\t\tavailableThumbnailSizes.data(),\n> > >>>>> -\t\t\tavailableThumbnailSizes.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,\n> > >>>>> +\t\t\t\t  availableThumbnailSizes.data(),\n> > >>>>> +\t\t\t\t  availableThumbnailSizes.size());\n> > >>>>>\n> > >>>>>  \t/* Sensor static metadata. */\n> > >>>>>  \tint32_t pixelArraySize[] = {\n> > >>>>>  \t\t2592, 1944,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,\n> > >>>>> -\t\t\t\t&pixelArraySize, 2);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,\n> > >>>>> +\t\t\t\t  &pixelArraySize, 2);\n> > >>>>>\n> > >>>>>  \tint32_t sensorSizes[] = {\n> > >>>>>  \t\t0, 0, 2560, 1920,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,\n> > >>>>> -\t\t\t\t&sensorSizes, 4);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,\n> > >>>>> +\t\t\t\t  &sensorSizes, 4);\n> > >>>>>\n> > >>>>>  \tint32_t sensitivityRange[] = {\n> > >>>>>  \t\t32, 2400,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_SENSOR_INFO_SENSITIVITY_RANGE,\n> > >>>>> -\t\t\t\t&sensitivityRange, 2);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,\n> > >>>>> +\t\t\t\t  &sensitivityRange, 2);\n> > >>>>>\n> > >>>>>  \tuint16_t filterArr = ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,\n> > >>>>> -\t\t\t\t&filterArr, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,\n> > >>>>> +\t\t\t\t  &filterArr, 1);\n> > >>>>>\n> > >>>>>  \tint64_t exposureTimeRange[] = {\n> > >>>>>  \t\t100000, 200000000,\n> > >>>>>  \t};\n> > >>>>\n> > >>>> I've been thinking for a while to stabilize on the use of std::vector in\n> > >>>> place of arrays, so e can always use .data() and .size() and have\n> > >>>> guaranteed we should only change the declaration and not the\n> > >>>> parameters to the addEntry() operation.\n> > >>>>\n> > >>>> This might be a good time to do so. What do you think?\n> > >>>\n> > >>> I've thought about it, and constructing a vector is a bit costly\n> > >>> compared to arrays. I'd rather used std::array<>, but that requires\n> > >>> specifying the size explicitly :-S I've been thinking about overloading\n> > >>> the addEntry() method, in order to be able to write\n> > >>>\n> > >>> \tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> > >>> \t\t\t\t  { 100000, 200000000 });\n> > >>>\n> > >>> I'm not sure if that will be possible as we need to handle different\n> > >>> data types, but I think it's worth a try. Other overloaded methods\n> > >>> should also be added for the arrays of a single element:\n> > >>>\n> > >>> \tstaticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION, 0);\n> > >>>\n> > >>> I would prefer handling the standardisation of vector vs. array in a\n> > >>> separate patch, when dealing with overloaded versions of addEntry(), as\n> > >>> this patch is big enough already.\n> > >>\n> > >> Agreed\n> > >>\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> > >>>>> -\t\t\t\t&exposureTimeRange, 2);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,\n> > >>>>> +\t\t\t\t  &exposureTimeRange, 2);\n> > >>>>>\n> > >>>>>  \tint32_t orientation = 0;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_SENSOR_ORIENTATION,\n> > >>>>> -\t\t\t\t&orientation, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_ORIENTATION,\n> > >>>>> +\t\t\t\t  &orientation, 1);\n> > >>>>\n> > >>>> Fits in 1 line\n> > >>>\n> > >>> I've kept it on two lines to use similar constructs through the whole\n> > >>> function, but I don't mind much, so please feel free to change it if you\n> > >>> prefer.\n> > >>\n> > >> If it was intentional, let's keep it the way it is\n> > >>\n> > >>>>>\n> > >>>>>  \tstd::vector<int32_t> testPatterModes = {\n> > >>>>>  \t\tANDROID_SENSOR_TEST_PATTERN_MODE_OFF,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,\n> > >>>>> -\t\t\t\ttestPatterModes.data(), testPatterModes.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,\n> > >>>>> +\t\t\t\t  testPatterModes.data(),\n> > >>>>> +\t\t\t\t  testPatterModes.size());\n> > >>>>>\n> > >>>>>  \tstd::vector<float> physicalSize = {\n> > >>>>>  \t\t2592, 1944,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_SENSOR_INFO_PHYSICAL_SIZE,\n> > >>>>> -\t\t\t\tphysicalSize.data(), physicalSize.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,\n> > >>>>> +\t\t\t\t  physicalSize.data(),\n> > >>>>> +\t\t\t\t  physicalSize.size());\n> > >>>>\n> > >>>> Fits in 1 line\n> > >>>>\n> > >>>>>\n> > >>>>>  \tuint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,\n> > >>>>> -\t\t\t&timestampSource, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,\n> > >>>>> +\t\t\t\t  &timestampSource, 1);\n> > >>>>>\n> > >>>>>  \t/* Statistics static metadata. */\n> > >>>>>  \tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> > >>>>> -\t\t\t&faceDetectMode, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,\n> > >>>>> +\t\t\t\t  &faceDetectMode, 1);\n> > >>>>>\n> > >>>>>  \tint32_t maxFaceCount = 0;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> > >>>>> -\t\t\t&maxFaceCount, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,\n> > >>>>> +\t\t\t\t  &maxFaceCount, 1);\n> > >>>>>\n> > >>>>>  \t/* Sync static metadata. */\n> > >>>>>  \tint32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);\n> > >>>>>\n> > >>>>>  \t/* Flash static metadata. */\n> > >>>>>  \tchar flashAvailable = ANDROID_FLASH_INFO_AVAILABLE_FALSE;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_FLASH_INFO_AVAILABLE,\n> > >>>>> -\t\t\t&flashAvailable, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_FLASH_INFO_AVAILABLE,\n> > >>>>> +\t\t\t\t  &flashAvailable, 1);\n> > >>>>>\n> > >>>>>  \t/* Lens static metadata. */\n> > >>>>>  \tstd::vector<float> lensApertures = {\n> > >>>>>  \t\t2.53 / 100,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_APERTURES,\n> > >>>>> -\t\t\t\tlensApertures.data(), lensApertures.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_APERTURES,\n> > >>>>> +\t\t\t\t  lensApertures.data(),\n> > >>>>> +\t\t\t\t  lensApertures.size());\n> > >>>>>\n> > >>>>>  \tuint8_t lensFacing = ANDROID_LENS_FACING_FRONT;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_LENS_FACING, &lensFacing, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_LENS_FACING, &lensFacing, 1);\n> > >>>>>\n> > >>>>>  \tstd::vector<float> lensFocalLenghts = {\n> > >>>>>  \t\t1,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,\n> > >>>>> -\t\t\t\tlensFocalLenghts.data(),\n> > >>>>> -\t\t\t\tlensFocalLenghts.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,\n> > >>>>> +\t\t\t\t  lensFocalLenghts.data(),\n> > >>>>> +\t\t\t\t  lensFocalLenghts.size());\n> > >>>>>\n> > >>>>>  \tstd::vector<uint8_t> opticalStabilizations = {\n> > >>>>>  \t\tANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,\n> > >>>>> -\t\t\t\topticalStabilizations.data(),\n> > >>>>> -\t\t\t\topticalStabilizations.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,\n> > >>>>> +\t\t\t\t  opticalStabilizations.data(),\n> > >>>>> +\t\t\t\t  opticalStabilizations.size());\n> > >>>>>\n> > >>>>>  \tfloat hypeFocalDistance = 0;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,\n> > >>>>> -\t\t\t\t&hypeFocalDistance, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,\n> > >>>>> +\t\t\t\t  &hypeFocalDistance, 1);\n> > >>>>>\n> > >>>>>  \tfloat minFocusDistance = 0;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,\n> > >>>>> -\t\t\t\t&minFocusDistance, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,\n> > >>>>> +\t\t\t\t  &minFocusDistance, 1);\n> > >>>>>\n> > >>>>>  \t/* Noise reduction modes. */\n> > >>>>>  \tuint8_t noiseReductionModes = ANDROID_NOISE_REDUCTION_MODE_OFF;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\t\tANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,\n> > >>>>> -\t\t\t\t&noiseReductionModes, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,\n> > >>>>> +\t\t\t\t  &noiseReductionModes, 1);\n> > >>>>>\n> > >>>>>  \t/* Scaler static metadata. */\n> > >>>>>  \tfloat maxDigitalZoom = 1;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,\n> > >>>>> -\t\t\t&maxDigitalZoom, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,\n> > >>>>> +\t\t\t\t  &maxDigitalZoom, 1);\n> > >>>>>\n> > >>>>>  \tstd::vector<uint32_t> availableStreamFormats = {\n> > >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB,\n> > >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888,\n> > >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_SCALER_AVAILABLE_FORMATS,\n> > >>>>> -\t\t\tavailableStreamFormats.data(),\n> > >>>>> -\t\t\tavailableStreamFormats.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_FORMATS,\n> > >>>>> +\t\t\t\t  availableStreamFormats.data(),\n> > >>>>> +\t\t\t\t  availableStreamFormats.size());\n> > >>>>>\n> > >>>>>  \tstd::vector<uint32_t> availableStreamConfigurations = {\n> > >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920,\n> > >>>>> @@ -447,65 +382,57 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920,\n> > >>>>>  \t\tANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,\n> > >>>>> -\t\t\tavailableStreamConfigurations.data(),\n> > >>>>> -\t\t\tavailableStreamConfigurations.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,\n> > >>>>> +\t\t\t\t  availableStreamConfigurations.data(),\n> > >>>>> +\t\t\t\t  availableStreamConfigurations.size());\n> > >>>>>\n> > >>>>>  \tstd::vector<int64_t> availableStallDurations = {\n> > >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_SCALER_AVAILABLE_STALL_DURATIONS,\n> > >>>>> -\t\t\tavailableStallDurations.data(),\n> > >>>>> -\t\t\tavailableStallDurations.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,\n> > >>>>> +\t\t\t\t  availableStallDurations.data(),\n> > >>>>> +\t\t\t\t  availableStallDurations.size());\n> > >>>>>\n> > >>>>>  \tstd::vector<int64_t> minFrameDurations = {\n> > >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB, 2560, 1920, 33333333,\n> > >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED, 2560, 1920, 33333333,\n> > >>>>>  \t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888, 2560, 1920, 33333333,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> > >>>>> -\t\t\tminFrameDurations.data(), minFrameDurations.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,\n> > >>>>> +\t\t\t\t  minFrameDurations.data(),\n> > >>>>> +\t\t\t\t  minFrameDurations.size());\n> > >>>>>\n> > >>>>>  \tuint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);\n> > >>>>>\n> > >>>>>  \t/* Info static metadata. */\n> > >>>>>  \tuint8_t supportedHWLevel = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> > >>>>> -\t\t\t&supportedHWLevel, 1);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,\n> > >>>>> +\t\t\t\t  &supportedHWLevel, 1);\n> > >>>>>\n> > >>>>>  \t/* Request static metadata. */\n> > >>>>>  \tint32_t partialResultCount = 1;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> > >>>>> -\t\t\t&partialResultCount, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_PARTIAL_RESULT_COUNT,\n> > >>>>> +\t\t\t\t  &partialResultCount, 1);\n> > >>>>>\n> > >>>>>  \tuint8_t maxPipelineDepth = 2;\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_REQUEST_PIPELINE_MAX_DEPTH,\n> > >>>>> -\t\t\t&maxPipelineDepth, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_PIPELINE_MAX_DEPTH,\n> > >>>>> +\t\t\t\t  &maxPipelineDepth, 1);\n> > >>>>>\n> > >>>>>  \tstd::vector<uint8_t> availableCapabilities = {\n> > >>>>>  \t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(staticMetadata_,\n> > >>>>> -\t\t\tANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> > >>>>> -\t\t\tavailableCapabilities.data(),\n> > >>>>> -\t\t\tavailableCapabilities.size());\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tstaticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,\n> > >>>>> +\t\t\t\t  availableCapabilities.data(),\n> > >>>>> +\t\t\t\t  availableCapabilities.size());\n> > >>>>> +\n> > >>>>> +\tif (!staticMetadata_->isValid()) {\n> > >>>>> +\t\tdelete staticMetadata_;\n> > >>>>> +\t\tstaticMetadata_ = nullptr;\n> > >>>>> +\t\treturn nullptr;\n> > >>>>> +\t}\n> > >>>>>\n> > >>>>> -\treturn staticMetadata_;\n> > >>>>> +\treturn staticMetadata_->get();\n> > >>>>>  }\n> > >>>>>\n> > >>>>>  /*\n> > >>>>> @@ -513,8 +440,6 @@ camera_metadata_t *CameraDevice::getStaticMetadata()\n> > >>>>>   */\n> > >>>>>  const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)\n> > >>>>>  {\n> > >>>>> -\tint ret;\n> > >>>>> -\n> > >>>>>  \t/*\n> > >>>>>  \t * \\todo Inspect type and pick the right metadata pack.\n> > >>>>>  \t * As of now just use a single one for all templates.\n> > >>>>> @@ -545,89 +470,73 @@ const camera_metadata_t *CameraDevice::constructDefaultRequestSettings(int type)\n> > >>>>>  \t}\n> > >>>>>\n> > >>>>>  \tif (requestTemplate_)\n> > >>>>> -\t\treturn requestTemplate_;\n> > >>>>> +\t\treturn requestTemplate_->get();\n> > >>>>>\n> > >>>>>  \t/*\n> > >>>>>  \t * \\todo Keep this in sync with the actual number of entries.\n> > >>>>>  \t * Currently: 12 entries, 15 bytes\n> > >>>>>  \t */\n> > >>>>> -\trequestTemplate_ = allocate_camera_metadata(15, 20);\n> > >>>>> +\trequestTemplate_ = new CameraMetadata(15, 20);\n> > >>>>>  \tif (!requestTemplate_) {\n> > >>>>>  \t\tLOG(HAL, Error) << \"Failed to allocate template metadata\";\n> > >>>>> +\t\tdelete requestTemplate_;\n> > >>>>> +\t\trequestTemplate_ = nullptr;\n> > >>>>\n> > >>>> Empty line before return ?\n> > >>>>\n> > >>>>>  \t\treturn nullptr;\n> > >>>>>  \t}\n> > >>>>>\n> > >>>>>  \tuint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;\n> > >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AE_MODE,\n> > >>>>> -\t\t\t&aeMode, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_MODE,\n> > >>>>> +\t\t\t\t   &aeMode, 1);\n> > >>>>\n> > >>>> This and many others entries here and below fit in 1 line.\n> > >>>>\n> > >>>>>\n> > >>>>>  \tint32_t aeExposureCompensation = 0;\n> > >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,\n> > >>>>> -\t\t\t&aeExposureCompensation, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,\n> > >>>>> +\t\t\t\t   &aeExposureCompensation, 1);\n> > >>>>>\n> > >>>>>  \tuint8_t aePrecaptureTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;\n> > >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,\n> > >>>>> -\t\t\t&aePrecaptureTrigger, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,\n> > >>>>> +\t\t\t\t   &aePrecaptureTrigger, 1);\n> > >>>>>\n> > >>>>>  \tuint8_t aeLock = ANDROID_CONTROL_AE_LOCK_OFF;\n> > >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AE_LOCK,\n> > >>>>> -\t\t\t&aeLock, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AE_LOCK,\n> > >>>>> +\t\t\t\t   &aeLock, 1);\n> > >>>>>\n> > >>>>>  \tuint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE;\n> > >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AF_TRIGGER,\n> > >>>>> -\t\t\t&afTrigger, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AF_TRIGGER,\n> > >>>>> +\t\t\t\t   &afTrigger, 1);\n> > >>>>>\n> > >>>>>  \tuint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO;\n> > >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AWB_MODE,\n> > >>>>> -\t\t\t&awbMode, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AWB_MODE,\n> > >>>>> +\t\t\t\t   &awbMode, 1);\n> > >>>>>\n> > >>>>>  \tuint8_t awbLock = ANDROID_CONTROL_AWB_LOCK_OFF;\n> > >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>>>> -\t\t\tANDROID_CONTROL_AWB_LOCK,\n> > >>>>> -\t\t\t&awbLock, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_AWB_LOCK,\n> > >>>>> +\t\t\t\t   &awbLock, 1);\n> > >>>>>\n> > >>>>>  \tuint8_t flashMode = ANDROID_FLASH_MODE_OFF;\n> > >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>>>> -\t\t\tANDROID_FLASH_MODE,\n> > >>>>> -\t\t\t&flashMode, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\trequestTemplate_->addEntry(ANDROID_FLASH_MODE,\n> > >>>>> +\t\t\t\t   &flashMode, 1);\n> > >>>>>\n> > >>>>>  \tuint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;\n> > >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>>>> -\t\t\tANDROID_STATISTICS_FACE_DETECT_MODE,\n> > >>>>> -\t\t\t&faceDetectMode, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\trequestTemplate_->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE,\n> > >>>>> +\t\t\t\t   &faceDetectMode, 1);\n> > >>>>>\n> > >>>>>  \tuint8_t noiseReduction = ANDROID_NOISE_REDUCTION_MODE_OFF;\n> > >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>>>> -\t\t\tANDROID_NOISE_REDUCTION_MODE, &noiseReduction, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\trequestTemplate_->addEntry(ANDROID_NOISE_REDUCTION_MODE,\n> > >>>>> +\t\t\t\t   &noiseReduction, 1);\n> > >>>>>\n> > >>>>>  \tuint8_t aberrationMode = ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF;\n> > >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>>>> -\t\t\tANDROID_COLOR_CORRECTION_ABERRATION_MODE,\n> > >>>>> -\t\t\t&aberrationMode, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\trequestTemplate_->addEntry(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,\n> > >>>>> +\t\t\t\t   &aberrationMode, 1);\n> > >>>>> +\n> > >>>>> +\trequestTemplate_->addEntry(ANDROID_CONTROL_CAPTURE_INTENT,\n> > >>>>> +\t\t\t\t   &captureIntent, 1);\n> > >>>>>\n> > >>>>> -\tret = add_camera_metadata_entry(requestTemplate_,\n> > >>>>> -\t\t\tANDROID_CONTROL_CAPTURE_INTENT,\n> > >>>>> -\t\t\t&captureIntent, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tif (!requestTemplate_->isValid()) {\n> > >>>>> +\t\tdelete requestTemplate_;\n> > >>>>> +\t\trequestTemplate_ = nullptr;\n> > >>>>\n> > >>>> You should return nullptr here, otherwise the below requestTemplate_->get();\n> > >>>> will de-reference a nullptr.\n> > >>>\n> > >>> Absolutely, my bad.\n> > >>>\n> > >>>>> +\t}\n> > >>>>>\n> > >>>>> -\treturn requestTemplate_;\n> > >>>>> +\treturn requestTemplate_->get();\n> > >>>>>  }\n> > >>>>>\n> > >>>>>  /*\n> > >>>>> @@ -799,7 +708,7 @@ void CameraDevice::requestComplete(Request *request,\n> > >>>>>  {\n> > >>>>>  \tBuffer *libcameraBuffer = buffers.begin()->second;\n> > >>>>>  \tcamera3_buffer_status status = CAMERA3_BUFFER_STATUS_OK;\n> > >>>>> -\tcamera_metadata_t *resultMetadata = nullptr;\n> > >>>>> +\tstd::unique_ptr<CameraMetadata> resultMetadata;\n> > >>>>>\n> > >>>>>  \tif (request->status() != Request::RequestComplete) {\n> > >>>>>  \t\tLOG(HAL, Error) << \"Request not succesfully completed: \"\n> > >>>>> @@ -837,16 +746,12 @@ void CameraDevice::requestComplete(Request *request,\n> > >>>>>  \t\tcaptureResult.partial_result = 1;\n> > >>>>>  \t\tresultMetadata = getResultMetadata(descriptor->frameNumber,\n> > >>>>>  \t\t\t\t\t\t   libcameraBuffer->timestamp());\n> > >>>>> -\t\tcaptureResult.result = resultMetadata;\n> > >>>>> +\t\tcaptureResult.result = resultMetadata->get();\n> > >>>>>  \t}\n> > >>>>>\n> > >>>>>  \tcallbacks_->process_capture_result(callbacks_, &captureResult);\n> > >>>>>\n> > >>>>>  \tdelete descriptor;\n> > >>>>> -\tif (resultMetadata)\n> > >>>>> -\t\tfree_camera_metadata(resultMetadata);\n> > >>>>> -\n> > >>>>> -\treturn;\n> > >>>>>  }\n> > >>>>>\n> > >>>>>  void CameraDevice::notifyShutter(uint32_t frameNumber, uint64_t timestamp)\n> > >>>>> @@ -875,89 +780,63 @@ void CameraDevice::notifyError(uint32_t frameNumber, camera3_stream_t *stream)\n> > >>>>>  /*\n> > >>>>>   * Produce a set of fixed result metadata.\n> > >>>>>   */\n> > >>>>> -camera_metadata_t *CameraDevice::getResultMetadata(int frame_number,\n> > >>>>> -\t\t\t\t\t\t   int64_t timestamp)\n> > >>>>> +std::unique_ptr<CameraMetadata> CameraDevice::getResultMetadata(int frame_number,\n> > >>>>\n> > >>>> Not a fan of smart pointers, you know already. How does this work?\n> > >>>> Because the compiler applies copy-elision or because of the move\n> > >>>> semantic applied on the return value?\n> > >>>\n> > >>> std::unique_ptr<> has an operator= that takes an rvalue reference to\n> > >>> another std::unique_ptr<>, and uses move semantic. As explained in\n> > >>> https://en.cppreference.com/w/cpp/language/value_category, an rvalue is\n> > >>> either a prvalue or an xvalue, and a prvalue can be \"a function call or\n> > >>> an overloaded operator expression, whose return type is non-reference\".\n> > >>> As far as I can tell, that's why we don't need an std::move() in the\n> > >>> caller.\n> > >>\n> > >> I see.. This seems to suggest both RVO and move semantic can play a\n> > >> role https://stackoverflow.com/a/46571941\n> > >>\n> > >> Ah, c++\n> > >>\n> > >>>> difficult to follow in my opinion.\n> > >>>\n> > >>> I think we should standardise as much as possible on std::unique_ptr<>\n> > >>> when passing ownership of a returned pointer. That's documented in\n> > >>> Documentation/coding-style.rst.\n> > >>\n> > >> Ack, let's keep it the way it is then.\n> > >>\n> > >>>>> +\t\t\t\t\t\t\t\tint64_t timestamp)\n> > >>>>>  {\n> > >>>>> -\tint ret;\n> > >>>>> -\n> > >>>>>  \t/*\n> > >>>>>  \t * \\todo Keep this in sync with the actual number of entries.\n> > >>>>>  \t * Currently: 13 entries, 36 bytes\n> > >>>>>  \t */\n> > >>>>> -\tcamera_metadata_t *resultMetadata = allocate_camera_metadata(15, 50);\n> > >>>>> +\tstd::unique_ptr<CameraMetadata> resultMetadata =\n> > >>>>> +\t\tutils::make_unique<CameraMetadata>(15, 50);\n> > >>>>> +\tif (!resultMetadata->isValid()) {\n> > >>>>> +\t\tLOG(HAL, Error) << \"Failed to allocate static metadata\";\n> > >>>>> +\t\treturn nullptr;\n> > >>>>> +\t}\n> > >>>>>\n> > >>>>>  \tconst uint8_t ae_state = ANDROID_CONTROL_AE_STATE_CONVERGED;\n> > >>>>> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AE_STATE,\n> > >>>>> -\t\t\t\t\t&ae_state, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AE_STATE, &ae_state, 1);\n> > >>>>>\n> > >>>>>  \tconst uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;\n> > >>>>> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AE_LOCK,\n> > >>>>> -\t\t\t\t\t&ae_lock, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);\n> > >>>>>\n> > >>>>>  \tuint8_t af_state = ANDROID_CONTROL_AF_STATE_INACTIVE;\n> > >>>>> -\tret = add_camera_metadata_entry(resultMetadata, ANDROID_CONTROL_AF_STATE,\n> > >>>>> -\t\t\t\t\t&af_state, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AF_STATE, &af_state, 1);\n> > >>>>>\n> > >>>>>  \tconst uint8_t awb_state = ANDROID_CONTROL_AWB_STATE_CONVERGED;\n> > >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>>>> -\t\t\t\t\tANDROID_CONTROL_AWB_STATE,\n> > >>>>> -\t\t\t\t\t&awb_state, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AWB_STATE, &awb_state, 1);\n> > >>>>>\n> > >>>>>  \tconst uint8_t awb_lock = ANDROID_CONTROL_AWB_LOCK_OFF;\n> > >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>>>> -\t\t\t\t\tANDROID_CONTROL_AWB_LOCK,\n> > >>>>> -\t\t\t\t\t&awb_lock, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tresultMetadata->addEntry(ANDROID_CONTROL_AWB_LOCK, &awb_lock, 1);\n> > >>>>>\n> > >>>>>  \tconst uint8_t lens_state = ANDROID_LENS_STATE_STATIONARY;\n> > >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>>>> -\t\t\t\t\tANDROID_LENS_STATE,\n> > >>>>> -\t\t\t\t\t&lens_state, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tresultMetadata->addEntry(ANDROID_LENS_STATE, &lens_state, 1);\n> > >>>>>\n> > >>>>>  \tint32_t sensorSizes[] = {\n> > >>>>>  \t\t0, 0, 2560, 1920,\n> > >>>>>  \t};\n> > >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>>>> -\t\t\t\t\tANDROID_SCALER_CROP_REGION,\n> > >>>>> -\t\t\t\t\tsensorSizes, 4);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tresultMetadata->addEntry(ANDROID_SCALER_CROP_REGION, sensorSizes, 4);\n> > >>>>>\n> > >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>>>> -\t\t\t\t\tANDROID_SENSOR_TIMESTAMP,\n> > >>>>> -\t\t\t\t\t&timestamp, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tresultMetadata->addEntry(ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);\n> > >>>>>\n> > >>>>>  \t/* 33.3 msec */\n> > >>>>>  \tconst int64_t rolling_shutter_skew = 33300000;\n> > >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>>>> -\t\t\t\t\tANDROID_SENSOR_ROLLING_SHUTTER_SKEW,\n> > >>>>> -\t\t\t\t\t&rolling_shutter_skew, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tresultMetadata->addEntry(ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,\n> > >>>>> +\t\t\t\t &rolling_shutter_skew, 1);\n> > >>>>>\n> > >>>>>  \t/* 16.6 msec */\n> > >>>>>  \tconst int64_t exposure_time = 16600000;\n> > >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>>>> -\t\t\t\t\tANDROID_SENSOR_EXPOSURE_TIME,\n> > >>>>> -\t\t\t\t\t&exposure_time, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tresultMetadata->addEntry(ANDROID_SENSOR_EXPOSURE_TIME,\n> > >>>>> +\t\t\t\t &exposure_time, 1);\n> > >>>>>\n> > >>>>>  \tconst uint8_t lens_shading_map_mode =\n> > >>>>>  \t\t\t\tANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;\n> > >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>>>> -\t\t\t\t\tANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> > >>>>> -\t\t\t\t\t&lens_shading_map_mode, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tresultMetadata->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,\n> > >>>>> +\t\t\t\t &lens_shading_map_mode, 1);\n> > >>>>>\n> > >>>>>  \tconst uint8_t scene_flicker = ANDROID_STATISTICS_SCENE_FLICKER_NONE;\n> > >>>>> -\tret = add_camera_metadata_entry(resultMetadata,\n> > >>>>> -\t\t\t\t\tANDROID_STATISTICS_SCENE_FLICKER,\n> > >>>>> -\t\t\t\t\t&scene_flicker, 1);\n> > >>>>> -\tMETADATA_ASSERT(ret);\n> > >>>>> +\tresultMetadata->addEntry(ANDROID_STATISTICS_SCENE_FLICKER,\n> > >>>>> +\t\t\t\t &scene_flicker, 1);\n> > >>>>\n> > >>>> Shouldn't you check if the metadata pack is valid ?\n> > >>>\n> > >>> Good point. Should we check here or in the caller ? As the caller would\n> > >>> then need a nullptr check I'm tempted to do so in the caller. Actually,\n> > >>> without a change to the code, the caller will operate correctly I\n> > >>> believe\n> > >>>\n> > >>>                 resultMetadata = getResultMetadata(descriptor->frameNumber,\n> > >>>                                                    libcameraBuffer->timestamp());\n> > >>>                 captureResult.result = resultMetadata->get();\n> > >>>\n> > >>> which will set captureResult.result to nullptr if resultMetadata is not\n> > >>> valid.\n> > >>\n> > >> Yeah, but in that case we should notify an error back to the stack.\n> > >\n> > > That makes sense. It should be a faily uncommon case though, is it would\n> > > be the result of a bug in our code, but bugs happen. I wonder what the\n> > > proper error recovery would be in that case.\n> > >\n> > >> What about:\n> > >>\n> > >>         resultMetadata = getResultMetadata(descriptor->frameNumber,\n> > >>                                            libcameraBuffer->timestamp());\n> > >> \tif (status == CAMERA3_BUFFER_STATUS_ERROR || !resultMetadata) {\n> > >> \t\t/* \\todo Improve error handling. */\n> > >> \t\tnotifyError(descriptor->frameNumber,\n> > >> \t\t\t    descriptor->buffers[0].stream);\n> > >> \t} else {\n> > >> \t\tnotifyShutter(descriptor->frameNumber,\n> > >> \t\t\t      libcameraBuffer->timestamp());\n> > >>\n> > >> \t\tcaptureResult.partial_result = 1;\n> > >> \t\tcaptureResult.result = resultMetadata->get();\n> > >> \t}\n> > >>\n> > >> The drawback is that we're generating the result metadata even if\n> > >> status is set to CAMERA3_BUFFER_STATUS_ERROR.\n> > >\n> > > That I don't think we should do, as I expect the result metadata\n> > > generation will not be possible in case of CAMERA3_BUFFER_STATUS_ERROR\n> > > when we'll stop generating fake metadata.\n> > >\n> > > How about this ?\n> > >\n> > > \tif (status == CAMERA3_BUFFER_STATUS_OK) {\n> > > \t\tnotifyShutter(descriptor->frameNumber,\n> > > \t\t\t      libcameraBuffer->timestamp());\n> > >\n> > > \t\tcaptureResult.partial_result = 1;\n> > > \t\tresultMetadata = getResultMetadata(descriptor->frameNumber,\n> > > \t\t\t\t\t\t   libcameraBuffer->timestamp());\n> > > \t\tcaptureResult.result = resultMetadata->get();\n> > > \t}\n> > >\n> > > \tif (status == CAMERA3_BUFFER_STATUS_ERROR || !captureResult.result) {\n> > > \t\t/* \\todo Improve error handling. */\n> > > \t\tnotifyError(descriptor->frameNumber,\n> > > \t\t\t    descriptor->buffers[0].stream);\n> > > \t}\n> > >\n> > > The last condition could be written if (!captureResult.result) as\n> > > CAMERA3_BUFFER_STATUS_ERROR implies !captureResult.result, but I'd\n> > > rather have both to make it explicit.\n> >\n> > The only difference I see here is that we send up a shutter event and\n> > the if metadata generation fails we send back an error.\n> >\n> > In the previous version was either an error or the shutter\n> > notification, not both.\n> >\n> > I can't tell if this makes any difference to the camera stack to be\n> > honest.\n>\n> Neither can I, and this shouldn't happen in the first place :-) If you\n> want to avoid it,\n>\n\nI have expanded the todo comment in v7 which I posted before this.\nIf no other comments on v7 I can take this in when applying, or keep\nthe version in v7 which doesn't seem so dangerous after all.\n\n\n\n>  \tif (status == CAMERA3_BUFFER_STATUS_OK) {\n>  \t\tcaptureResult.partial_result = 1;\n>  \t\tresultMetadata = getResultMetadata(descriptor->frameNumber,\n>  \t\t\t\t\t\t   libcameraBuffer->timestamp());\n>  \t\tcaptureResult.result = resultMetadata->get();\n>  \t}\n>\n>  \tif (status == CAMERA3_BUFFER_STATUS_OK && captureResult.result) {\n>  \t\tnotifyShutter(descriptor->frameNumber,\n>  \t\t\t      libcameraBuffer->timestamp());\n> \t} else {\n>  \t\t/* \\todo Improve error handling. */\n>  \t\tnotifyError(descriptor->frameNumber,\n>  \t\t\t    descriptor->buffers[0].stream);\n>  \t}\n>\n> > >>>>>\n> > >>>>>  \treturn resultMetadata;\n> > >>>>>  }\n> > >>>>> diff --git a/src/android/camera_device.h b/src/android/camera_device.h\n> > >>>>> index 7897ba9dc5c7..65ba877a02ea 100644\n> > >>>>> --- a/src/android/camera_device.h\n> > >>>>> +++ b/src/android/camera_device.h\n> > >>>>> @@ -19,13 +19,7 @@\n> > >>>>>\n> > >>>>>  #include \"message.h\"\n> > >>>>>\n> > >>>>> -#define METADATA_ASSERT(_r)\t\t\\\n> > >>>>> -\tdo {\t\t\t\t\\\n> > >>>>> -\t\tif (!(_r)) break;\t\\\n> > >>>>> -\t\tLOG(HAL, Error) << \"Error: \" << __func__ << \":\" << __LINE__; \\\n> > >>>>> -\t\treturn nullptr;\t\t\\\n> > >>>>> -\t} while(0);\n> > >>>>> -\n> > >>>>> +class CameraMetadata;\n> > >>>>>  class ThreadRpc;\n> > >>>>>\n> > >>>>>  class CameraDevice : public libcamera::Object\n> > >>>>> @@ -59,14 +53,15 @@ private:\n> > >>>>>\n> > >>>>>  \tvoid notifyShutter(uint32_t frameNumber, uint64_t timestamp);\n> > >>>>>  \tvoid notifyError(uint32_t frameNumber, camera3_stream_t *stream);\n> > >>>>> -\tcamera_metadata_t *getResultMetadata(int frame_number, int64_t timestamp);\n> > >>>>> +\tstd::unique_ptr<CameraMetadata> getResultMetadata(int frame_number,\n> > >>>>> +\t\t\t\t\t\t\t  int64_t timestamp);\n> > >>>>>\n> > >>>>>  \tbool running_;\n> > >>>>>  \tstd::shared_ptr<libcamera::Camera> camera_;\n> > >>>>>  \tstd::unique_ptr<libcamera::CameraConfiguration> config_;\n> > >>>>>\n> > >>>>> -\tcamera_metadata_t *staticMetadata_;\n> > >>>>> -\tcamera_metadata_t *requestTemplate_;\n> > >>>>> +\tCameraMetadata *staticMetadata_;\n> > >>>>> +\tCameraMetadata *requestTemplate_;\n> > >>>>>  \tconst camera3_callback_ops_t *callbacks_;\n> > >>>>>  };\n> > >>>>>\n>\n> --\n> Regards,\n>\n> Laurent Pinchart","headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay2-d.mail.gandi.net (relay2-d.mail.gandi.net\n\t[217.70.183.194])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C0FB060C18\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 Sep 2019 23:18:35 +0200 (CEST)","from uno.localdomain (2-224-242-101.ip172.fastwebnet.it\n\t[2.224.242.101]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay2-d.mail.gandi.net (Postfix) with ESMTPSA id 30B594000A;\n\tThu,  5 Sep 2019 21:18:34 +0000 (UTC)"],"X-Originating-IP":"2.224.242.101","Date":"Thu, 5 Sep 2019 23:20:07 +0200","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190905212007.f2hehmb6hfh5fxcq@uno.localdomain>","References":"<20190905074737.6955-1-jacopo@jmondi.org>\n\t<20190905074737.6955-8-jacopo@jmondi.org>\n\t<20190905081828.y647dyfqg2apejjp@uno.localdomain>\n\t<20190905093657.GA5035@pendragon.ideasonboard.com>\n\t<20190905095205.333n5sof5rjimsaf@uno.localdomain>\n\t<20190905100259.GE5035@pendragon.ideasonboard.com>\n\t<20190905202503.bv3uwn66fdetfvii@uno.localdomain>\n\t<20190905203917.GP5035@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Type":"multipart/signed; micalg=pgp-sha256;\n\tprotocol=\"application/pgp-signature\"; boundary=\"afpwujell66sn5es\"","Content-Disposition":"inline","In-Reply-To":"<20190905203917.GP5035@pendragon.ideasonboard.com>","User-Agent":"NeoMutt/20180716","Subject":"Re: [libcamera-devel] [PATCH v6 7/9] android: camera_device: Use\n\tthe new CameraMetadata helper class","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Thu, 05 Sep 2019 21:18:35 -0000"}}]