Add V4L2 Format Metadata Factory.
This factory queries the device for the properties detailing
what formats it supports. Since this may fail, Metadata/V4L2Metadata
was moved from the weird inheritance/constructor stuff it was doing
to Metadata having a better constructor and V4L2Metadata being a
factory.
BUG: 30140438
TEST: unit tests pass
Change-Id: Id4bcb27fbd8b517e3a9a8e9fb8a984af139254b3
diff --git a/modules/camera/3_4/Android.mk b/modules/camera/3_4/Android.mk
index ae28598..140e73b 100644
--- a/modules/camera/3_4/Android.mk
+++ b/modules/camera/3_4/Android.mk
@@ -39,6 +39,7 @@
v4l2_src_files := \
camera.cpp \
+ format_metadata_factory.cpp \
metadata/enum_converter.cpp \
metadata/metadata.cpp \
stream.cpp \
@@ -46,10 +47,11 @@
v4l2_camera.cpp \
v4l2_camera_hal.cpp \
v4l2_gralloc.cpp \
- v4l2_metadata.cpp \
+ v4l2_metadata_factory.cpp \
v4l2_wrapper.cpp \
v4l2_test_files := \
+ format_metadata_factory_test.cpp \
metadata/control_factory_test.cpp \
metadata/control_test.cpp \
metadata/enum_converter_test.cpp \
diff --git a/modules/camera/3_4/format_metadata_factory.cpp b/modules/camera/3_4/format_metadata_factory.cpp
new file mode 100644
index 0000000..83cf5cc
--- /dev/null
+++ b/modules/camera/3_4/format_metadata_factory.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "format_metadata_factory.h"
+
+#include "metadata/array_vector.h"
+
+namespace v4l2_camera_hal {
+
+static int GetHalFormats(const std::shared_ptr<V4L2Wrapper>& device,
+ std::set<int32_t>* result_formats) {
+ if (!result_formats) {
+ HAL_LOGE("Null result formats pointer passed");
+ return -EINVAL;
+ }
+
+ std::set<uint32_t> v4l2_formats;
+ int res = device->GetFormats(&v4l2_formats);
+ if (res) {
+ HAL_LOGE("Failed to get device formats.");
+ return res;
+ }
+ for (auto v4l2_format : v4l2_formats) {
+ int32_t hal_format = StreamFormat::V4L2ToHalPixelFormat(v4l2_format);
+ if (hal_format < 0) {
+ // Unrecognized/unused format. Skip it.
+ continue;
+ }
+ result_formats->insert(hal_format);
+ }
+
+ // In addition to well-defined formats, there may be an
+ // "Implementation Defined" format chosen by the HAL (in this
+ // case what that means is managed by the StreamFormat class).
+
+ // Get the V4L2 format for IMPLEMENTATION_DEFINED.
+ int v4l2_format = StreamFormat::HalToV4L2PixelFormat(
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
+ // If it's available, add IMPLEMENTATION_DEFINED to the result set.
+ if (v4l2_format && v4l2_formats.count(v4l2_format) > 0) {
+ result_formats->insert(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
+ }
+
+ return 0;
+}
+
+int AddFormatComponents(
+ std::shared_ptr<V4L2Wrapper> device,
+ std::insert_iterator<PartialMetadataSet> insertion_point) {
+ HAL_LOG_ENTER();
+
+ // Get all supported formats.
+ std::set<int32_t> hal_formats;
+ int res = GetHalFormats(device, &hal_formats);
+ if (res) {
+ return res;
+ }
+
+ // Requirements check: need to support YCbCr_420_888, JPEG,
+ // and "Implementation Defined".
+ if (hal_formats.find(HAL_PIXEL_FORMAT_YCbCr_420_888) == hal_formats.end()) {
+ HAL_LOGE("YCbCr_420_888 not supported by device.");
+ return -ENODEV;
+ } else if (hal_formats.find(HAL_PIXEL_FORMAT_BLOB) == hal_formats.end()) {
+ HAL_LOGE("JPEG not supported by device.");
+ return -ENODEV;
+ } else if (hal_formats.find(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) ==
+ hal_formats.end()) {
+ HAL_LOGE("HAL implementation defined format not supported by device.");
+ return -ENODEV;
+ }
+
+ // Find sizes and frame/stall durations for all formats.
+ // We also want to find the smallest max frame duration amongst all formats,
+ // And the largest min frame duration amongst YUV (i.e. largest max frame rate
+ // supported by all YUV sizes).
+ // Stream configs are {format, width, height, direction} (input or output).
+ ArrayVector<int32_t, 4> stream_configs;
+ // Frame durations are {format, width, height, duration} (duration in ns).
+ ArrayVector<int64_t, 4> min_frame_durations;
+ // Stall durations are {format, width, height, duration} (duration in ns).
+ ArrayVector<int64_t, 4> stall_durations;
+ int64_t min_max_frame_duration = std::numeric_limits<int64_t>::max();
+ int64_t max_min_frame_duration_yuv = std::numeric_limits<int64_t>::min();
+ for (auto hal_format : hal_formats) {
+ // Get the corresponding V4L2 format.
+ uint32_t v4l2_format = StreamFormat::HalToV4L2PixelFormat(hal_format);
+ if (v4l2_format == 0) {
+ // Unrecognized/unused format. Should never happen since hal_formats
+ // came from translating a bunch of V4L2 formats above.
+ HAL_LOGE("Couldn't find V4L2 format for HAL format %d", hal_format);
+ return -ENODEV;
+ }
+
+ // Get the available sizes for this format.
+ std::set<std::array<int32_t, 2>> frame_sizes;
+ res = device->GetFormatFrameSizes(v4l2_format, &frame_sizes);
+ if (res) {
+ HAL_LOGE("Failed to get all frame sizes for format %d", v4l2_format);
+ return res;
+ }
+
+ for (const auto& frame_size : frame_sizes) {
+ // Note the format and size combination in stream configs.
+ stream_configs.push_back(
+ {{hal_format,
+ frame_size[0],
+ frame_size[1],
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT}});
+
+ // Find the duration range for this format and size.
+ std::array<int64_t, 2> duration_range;
+ res = device->GetFormatFrameDurationRange(
+ v4l2_format, frame_size, &duration_range);
+ if (res) {
+ HAL_LOGE(
+ "Failed to get frame duration range for format %d, "
+ "size %u x %u",
+ v4l2_format,
+ frame_size[0],
+ frame_size[1]);
+ return res;
+ }
+ int64_t size_min_frame_duration = duration_range[0];
+ int64_t size_max_frame_duration = duration_range[1];
+ min_frame_durations.push_back({{hal_format,
+ frame_size[0],
+ frame_size[1],
+ size_min_frame_duration}});
+
+ // Note the stall duration for this format and size.
+ // Usually 0 for non-jpeg, non-zero for JPEG.
+ // Randomly choosing absurd 1 sec for JPEG. Unsure what this breaks.
+ int64_t stall_duration = 0;
+ if (hal_format == HAL_PIXEL_FORMAT_BLOB) {
+ stall_duration = 1000000000;
+ }
+ stall_durations.push_back(
+ {{hal_format, frame_size[0], frame_size[1], stall_duration}});
+
+ // Update our search for general min & max frame durations.
+ // In theory max frame duration (min frame rate) should be consistent
+ // between all formats, but we check and only advertise the smallest
+ // available max duration just in case.
+ if (size_max_frame_duration < min_max_frame_duration) {
+ min_max_frame_duration = size_max_frame_duration;
+ }
+ // We only care about the largest min frame duration
+ // (smallest max frame rate) for YUV sizes.
+ if (hal_format == HAL_PIXEL_FORMAT_YCbCr_420_888 &&
+ size_min_frame_duration > max_min_frame_duration_yuv) {
+ max_min_frame_duration_yuv = size_min_frame_duration;
+ }
+ }
+ }
+
+ // Convert from frame durations measured in ns.
+ // Min fps supported by all formats.
+ int32_t min_fps = 1000000000 / min_max_frame_duration;
+ if (min_fps > 15) {
+ HAL_LOGE("Minimum FPS %d is larger than HAL max allowable value of 15",
+ min_fps);
+ return -ENODEV;
+ }
+ // Max fps supported by all YUV formats.
+ int32_t max_yuv_fps = 1000000000 / max_min_frame_duration_yuv;
+ // ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES should be at minimum
+ // {mi, ma}, {ma, ma} where mi and ma are min and max frame rates for
+ // YUV_420_888. Min should be at most 15.
+ std::vector<std::array<int32_t, 2>> fps_ranges;
+ fps_ranges.push_back({{min_fps, max_yuv_fps}});
+ fps_ranges.push_back({{max_yuv_fps, max_yuv_fps}});
+
+ // Construct the metadata components.
+ insertion_point = std::make_unique<Property<ArrayVector<int32_t, 4>>>(
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+ std::move(stream_configs));
+ insertion_point = std::make_unique<Property<ArrayVector<int64_t, 4>>>(
+ ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
+ std::move(min_frame_durations));
+ insertion_point = std::make_unique<Property<ArrayVector<int64_t, 4>>>(
+ ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, std::move(stall_durations));
+ insertion_point = std::make_unique<Property<int64_t>>(
+ ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, min_max_frame_duration);
+ // TODO(b/31019725): This should probably not be a NoEffect control.
+ insertion_point = NoEffectMenuControl<std::array<int32_t, 2>>(
+ ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+ ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+ fps_ranges);
+
+ return 0;
+}
+
+} // namespace v4l2_camera_hal
diff --git a/modules/camera/3_4/v4l2_metadata.h b/modules/camera/3_4/format_metadata_factory.h
similarity index 60%
copy from modules/camera/3_4/v4l2_metadata.h
copy to modules/camera/3_4/format_metadata_factory.h
index 29e69b9..f9eb8b2 100644
--- a/modules/camera/3_4/v4l2_metadata.h
+++ b/modules/camera/3_4/format_metadata_factory.h
@@ -14,32 +14,25 @@
* limitations under the License.
*/
-#ifndef V4L2_CAMERA_HAL_V4L2_METADATA_H_
-#define V4L2_CAMERA_HAL_V4L2_METADATA_H_
+#ifndef V4L2_CAMERA_HAL_FORMAT_METADATA_FACTORY_H_
+#define V4L2_CAMERA_HAL_FORMAT_METADATA_FACTORY_H_
-#include <map>
+#include <iterator>
#include <memory>
-
-#include <hardware/camera3.h>
+#include <set>
#include "common.h"
-#include "metadata/control.h"
-#include "metadata/metadata.h"
+#include "metadata/control_factory.h"
+#include "metadata/metadata_common.h"
+#include "metadata/property.h"
#include "v4l2_wrapper.h"
namespace v4l2_camera_hal {
-class V4L2Metadata : public Metadata {
- public:
- V4L2Metadata(std::shared_ptr<V4L2Wrapper> device);
- virtual ~V4L2Metadata();
- private:
- // Access to the device.
- std::shared_ptr<V4L2Wrapper> device_;
-
- DISALLOW_COPY_AND_ASSIGN(V4L2Metadata);
-};
+int AddFormatComponents(
+ std::shared_ptr<V4L2Wrapper> device,
+ std::insert_iterator<PartialMetadataSet> insertion_point);
} // namespace v4l2_camera_hal
-#endif // V4L2_CAMERA_HAL_V4L2_METADATA_H_
+#endif // V4L2_CAMERA_HAL_FORMAT_METADATA_FACTORY_H_
diff --git a/modules/camera/3_4/format_metadata_factory_test.cpp b/modules/camera/3_4/format_metadata_factory_test.cpp
new file mode 100644
index 0000000..f033e37
--- /dev/null
+++ b/modules/camera/3_4/format_metadata_factory_test.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <camera/CameraMetadata.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "format_metadata_factory.h"
+#include "metadata/test_common.h"
+#include "v4l2_wrapper_mock.h"
+
+using testing::AtLeast;
+using testing::Expectation;
+using testing::Return;
+using testing::SetArgPointee;
+using testing::Test;
+using testing::_;
+
+namespace v4l2_camera_hal {
+
+class FormatMetadataFactoryTest : public Test {
+ protected:
+ virtual void SetUp() { mock_device_.reset(new V4L2WrapperMock()); }
+
+ virtual void ExpectMetadataTagCount(const android::CameraMetadata& metadata,
+ uint32_t tag,
+ size_t count) {
+ camera_metadata_ro_entry_t entry = metadata.find(tag);
+ EXPECT_EQ(entry.count, count);
+ }
+
+ std::shared_ptr<V4L2WrapperMock> mock_device_;
+};
+
+TEST_F(FormatMetadataFactoryTest, GetFormatMetadata) {
+ std::set<uint32_t> formats{V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_YUV420};
+ std::map<uint32_t, std::set<std::array<int32_t, 2>>> sizes{
+ {V4L2_PIX_FMT_JPEG, {{{10, 20}}, {{30, 60}}, {{120, 240}}}},
+ {V4L2_PIX_FMT_YUV420, {{{1, 2}}, {{3, 6}}, {{12, 24}}}}};
+ // These need to be on the correct order of magnitude,
+ // as there is a check for min fps > 15.
+ std::map<uint32_t, std::map<std::array<int32_t, 2>, std::array<int64_t, 2>>>
+ durations{{V4L2_PIX_FMT_JPEG,
+ {{{{10, 20}}, {{100000000, 200000000}}},
+ {{{30, 60}}, {{1000000000, 2000000000}}},
+ {{{120, 240}}, {{700000000, 1200000000}}}}},
+ {V4L2_PIX_FMT_YUV420,
+ {{{{1, 2}}, {{10000000000, 20000000000}}},
+ {{{3, 6}}, {{11000000000, 21000000000}}},
+ {{{12, 24}}, {{10500000000, 19000000000}}}}}};
+
+ EXPECT_CALL(*mock_device_, GetFormats(_))
+ .WillOnce(DoAll(SetArgPointee<0>(formats), Return(0)));
+
+ for (auto format : formats) {
+ std::set<std::array<int32_t, 2>> format_sizes = sizes[format];
+ EXPECT_CALL(*mock_device_, GetFormatFrameSizes(format, _))
+ .Times(AtLeast(1))
+ .WillRepeatedly(DoAll(SetArgPointee<1>(format_sizes), Return(0)));
+ for (auto size : format_sizes) {
+ EXPECT_CALL(*mock_device_, GetFormatFrameDurationRange(format, size, _))
+ .Times(AtLeast(1))
+ .WillRepeatedly(
+ DoAll(SetArgPointee<2>(durations[format][size]), Return(0)));
+ }
+ }
+
+ PartialMetadataSet components;
+ ASSERT_EQ(AddFormatComponents(mock_device_,
+ std::inserter(components, components.end())),
+ 0);
+
+ for (auto& component : components) {
+ android::CameraMetadata metadata;
+ component->PopulateStaticFields(&metadata);
+ ASSERT_EQ(metadata.entryCount(), 1);
+ int32_t tag = component->StaticTags()[0];
+ switch (tag) {
+ case ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS: // Fall through.
+ case ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS: // Fall through.
+ case ANDROID_SCALER_AVAILABLE_STALL_DURATIONS: // Fall through.
+ // 3 sizes per format, 4 elements per config.
+ // # formats + 1 for IMPLEMENTATION_DEFINED.
+ ExpectMetadataTagCount(metadata, tag, (formats.size() + 1) * 3 * 4);
+ break;
+ case ANDROID_SENSOR_INFO_MAX_FRAME_DURATION:
+ // The lowest max duration from above.
+ ExpectMetadataEq(metadata, tag, 200000000);
+ break;
+ case ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES:
+ // 2 ranges ({min, max} and {max, max}), each with a min and max.
+ ExpectMetadataTagCount(metadata, tag, 4);
+ break;
+ default:
+ FAIL() << "Unexpected component created.";
+ break;
+ }
+ }
+}
+} // namespace v4l2_camera_hal
diff --git a/modules/camera/3_4/metadata/metadata.cpp b/modules/camera/3_4/metadata/metadata.cpp
index e18a454..976a77d 100644
--- a/modules/camera/3_4/metadata/metadata.cpp
+++ b/modules/camera/3_4/metadata/metadata.cpp
@@ -23,7 +23,8 @@
namespace v4l2_camera_hal {
-Metadata::Metadata() {
+Metadata::Metadata(PartialMetadataSet components)
+ : components_(std::move(components)) {
HAL_LOG_ENTER();
}
@@ -31,13 +32,6 @@
HAL_LOG_ENTER();
}
-void Metadata::AddComponent(
- std::unique_ptr<PartialMetadataInterface> component) {
- HAL_LOG_ENTER();
-
- components_.push_back(std::move(component));
-}
-
int Metadata::FillStaticMetadata(android::CameraMetadata* metadata) {
HAL_LOG_ENTER();
diff --git a/modules/camera/3_4/metadata/metadata.h b/modules/camera/3_4/metadata/metadata.h
index 36e238b..0683df2 100644
--- a/modules/camera/3_4/metadata/metadata.h
+++ b/modules/camera/3_4/metadata/metadata.h
@@ -17,16 +17,18 @@
#ifndef V4L2_CAMERA_HAL_METADATA_H_
#define V4L2_CAMERA_HAL_METADATA_H_
+#include <set>
+
#include <camera/CameraMetadata.h>
#include <hardware/camera3.h>
#include "../common.h"
-#include "partial_metadata_interface.h"
+#include "metadata_common.h"
namespace v4l2_camera_hal {
class Metadata {
public:
- Metadata();
+ Metadata(PartialMetadataSet components);
virtual ~Metadata();
int FillStaticMetadata(android::CameraMetadata* metadata);
@@ -34,16 +36,10 @@
int SetRequestSettings(const android::CameraMetadata& metadata);
int FillResultMetadata(android::CameraMetadata* metadata);
- protected:
- // Helper for the child constructors to fill in metadata components.
- void AddComponent(std::unique_ptr<PartialMetadataInterface> component);
-
private:
// The overall metadata is broken down into several distinct pieces.
// Note: it is undefined behavior if multiple components share tags.
- std::vector<std::unique_ptr<PartialMetadataInterface>> components_;
-
- friend class MetadataTest;
+ PartialMetadataSet components_;
DISALLOW_COPY_AND_ASSIGN(Metadata);
};
diff --git a/modules/camera/3_4/metadata/metadata_common.h b/modules/camera/3_4/metadata/metadata_common.h
index efea152..15f8084 100644
--- a/modules/camera/3_4/metadata/metadata_common.h
+++ b/modules/camera/3_4/metadata/metadata_common.h
@@ -18,14 +18,19 @@
#define V4L2_CAMERA_HAL_METADATA_METADATA_COMMON_H_
#include <array>
+#include <memory>
+#include <set>
#include <vector>
#include <camera/CameraMetadata.h>
#include "array_vector.h"
+#include "partial_metadata_interface.h"
namespace v4l2_camera_hal {
+typedef std::set<std::unique_ptr<PartialMetadataInterface>> PartialMetadataSet;
+
// Templated helper functions effectively extending android::CameraMetadata.
// Will cause a compile-time errors if CameraMetadata doesn't support
// using the templated type. Templates are provided to extend this support
diff --git a/modules/camera/3_4/metadata/metadata_test.cpp b/modules/camera/3_4/metadata/metadata_test.cpp
index 3ea94ba..e6fb70f 100644
--- a/modules/camera/3_4/metadata/metadata_test.cpp
+++ b/modules/camera/3_4/metadata/metadata_test.cpp
@@ -24,7 +24,8 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include "metadata/partial_metadata_interface_mock.h"
+#include "metadata_common.h"
+#include "partial_metadata_interface_mock.h"
using testing::AtMost;
using testing::Return;
@@ -36,7 +37,8 @@
class MetadataTest : public Test {
protected:
virtual void SetUp() {
- dut_.reset(new Metadata());
+ // Clear the DUT. AddComponents must be called before using it.
+ dut_.reset();
component1_.reset(new PartialMetadataInterfaceMock());
component2_.reset(new PartialMetadataInterfaceMock());
@@ -51,8 +53,10 @@
virtual void AddComponents() {
// Don't mind moving; Gmock/Gtest fails on leaked mocks unless disabled by
// runtime flags.
- dut_->AddComponent(std::move(component1_));
- dut_->AddComponent(std::move(component2_));
+ PartialMetadataSet components;
+ components.insert(std::move(component1_));
+ components.insert(std::move(component2_));
+ dut_.reset(new Metadata(std::move(components)));
}
virtual void CompareTags(const std::set<int32_t>& expected,
diff --git a/modules/camera/3_4/metadata/property.h b/modules/camera/3_4/metadata/property.h
index 1ddd20f..3ded4c4 100644
--- a/modules/camera/3_4/metadata/property.h
+++ b/modules/camera/3_4/metadata/property.h
@@ -27,7 +27,7 @@
template <typename T>
class Property : public PartialMetadataInterface {
public:
- Property(int32_t tag, T value) : tag_(tag), value_(value){};
+ Property(int32_t tag, T value) : tag_(tag), value_(std::move(value)){};
virtual std::vector<int32_t> StaticTags() const override { return {tag_}; };
diff --git a/modules/camera/3_4/v4l2_metadata.cpp b/modules/camera/3_4/v4l2_metadata_factory.cpp
similarity index 77%
rename from modules/camera/3_4/v4l2_metadata.cpp
rename to modules/camera/3_4/v4l2_metadata_factory.cpp
index 06bd8d9..86c9a4d 100644
--- a/modules/camera/3_4/v4l2_metadata.cpp
+++ b/modules/camera/3_4/v4l2_metadata_factory.cpp
@@ -14,20 +14,22 @@
* limitations under the License.
*/
-#include "v4l2_metadata.h"
+#include "v4l2_metadata_factory.h"
#include <camera/CameraMetadata.h>
#include "common.h"
+#include "format_metadata_factory.h"
#include "metadata/control.h"
#include "metadata/control_factory.h"
#include "metadata/enum_converter.h"
+#include "metadata/metadata_common.h"
#include "metadata/property.h"
namespace v4l2_camera_hal {
-V4L2Metadata::V4L2Metadata(std::shared_ptr<V4L2Wrapper> device)
- : device_(std::move(device)) {
+int GetV4L2Metadata(std::shared_ptr<V4L2Wrapper> device,
+ std::unique_ptr<Metadata>* result) {
HAL_LOG_ENTER();
// TODO: Temporarily connect to the device so that V4L2-specific components
@@ -38,7 +40,9 @@
// V4L2 enum controls. Will add the other properties as more PartialMetadata
// subclasses get implemented.
- AddComponent(NoEffectMenuControl<uint8_t>(
+ PartialMetadataSet components;
+
+ components.insert(NoEffectMenuControl<uint8_t>(
ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
{ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST,
@@ -47,24 +51,24 @@
// TODO(b/30510395): subcomponents of 3A.
// In general, default to ON/AUTO since they imply pretty much nothing,
// while OFF implies guarantees about not hindering performance.
- AddComponent(std::unique_ptr<PartialMetadataInterface>(
+ components.insert(std::unique_ptr<PartialMetadataInterface>(
new Property<std::array<int32_t, 3>>(ANDROID_CONTROL_MAX_REGIONS,
{{/*AE*/ 0, /*AWB*/ 0, /*AF*/ 0}})));
- AddComponent(V4L2ControlOrDefault<uint8_t>(
+ components.insert(V4L2ControlOrDefault<uint8_t>(
ControlType::kMenu,
ANDROID_CONTROL_AE_MODE,
ANDROID_CONTROL_AE_AVAILABLE_MODES,
- device_,
+ device,
V4L2_CID_EXPOSURE_AUTO,
std::shared_ptr<ConverterInterface<uint8_t, int32_t>>(new EnumConverter(
{{V4L2_EXPOSURE_AUTO, ANDROID_CONTROL_AE_MODE_ON},
{V4L2_EXPOSURE_MANUAL, ANDROID_CONTROL_AE_MODE_OFF}})),
ANDROID_CONTROL_AE_MODE_ON));
- AddComponent(V4L2ControlOrDefault<uint8_t>(
+ components.insert(V4L2ControlOrDefault<uint8_t>(
ControlType::kMenu,
ANDROID_CONTROL_AE_ANTIBANDING_MODE,
ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
- device_,
+ device,
V4L2_CID_POWER_LINE_FREQUENCY,
std::shared_ptr<ConverterInterface<uint8_t, int32_t>>(
new EnumConverter({{V4L2_CID_POWER_LINE_FREQUENCY_DISABLED,
@@ -82,12 +86,11 @@
// Modes from each API that don't match up:
// Android: WARM_FLUORESCENT, TWILIGHT.
// V4L2: FLUORESCENT_H, HORIZON, FLASH.
- std::unique_ptr<PartialMetadataInterface> awb(V4L2Control<
- uint8_t>(
+ std::unique_ptr<PartialMetadataInterface> awb(V4L2Control<uint8_t>(
ControlType::kMenu,
ANDROID_CONTROL_AWB_MODE,
ANDROID_CONTROL_AWB_AVAILABLE_MODES,
- device_,
+ device,
V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
std::shared_ptr<ConverterInterface<uint8_t, int32_t>>(new EnumConverter(
{{V4L2_WHITE_BALANCE_MANUAL, ANDROID_CONTROL_AWB_MODE_OFF},
@@ -101,14 +104,14 @@
ANDROID_CONTROL_AWB_MODE_CLOUDY_DAYLIGHT},
{V4L2_WHITE_BALANCE_SHADE, ANDROID_CONTROL_AWB_MODE_SHADE}}))));
if (awb) {
- AddComponent(std::move(awb));
+ components.insert(std::move(awb));
} else {
// Fall back to simpler AWB or even just an ignored control.
- AddComponent(V4L2ControlOrDefault<uint8_t>(
+ components.insert(V4L2ControlOrDefault<uint8_t>(
ControlType::kMenu,
ANDROID_CONTROL_AWB_MODE,
ANDROID_CONTROL_AWB_AVAILABLE_MODES,
- device_,
+ device,
V4L2_CID_AUTO_WHITE_BALANCE,
std::shared_ptr<ConverterInterface<uint8_t, int32_t>>(
new EnumConverter({{0, ANDROID_CONTROL_AWB_MODE_OFF},
@@ -121,11 +124,11 @@
// Android: FACE_PRIORITY, ACTION, NIGHT_PORTRAIT, THEATRE, STEADYPHOTO,
// BARCODE, HIGH_SPEED_VIDEO.
// V4L2: BACKLIGHT, DAWN_DUSK, FALL_COLORS, TEXT.
- AddComponent(V4L2ControlOrDefault<uint8_t>(
+ components.insert(V4L2ControlOrDefault<uint8_t>(
ControlType::kMenu,
ANDROID_CONTROL_SCENE_MODE,
ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
- device_,
+ device,
V4L2_CID_SCENE_MODE,
std::shared_ptr<ConverterInterface<uint8_t, int32_t>>(new EnumConverter(
{{V4L2_SCENE_MODE_NONE, ANDROID_CONTROL_SCENE_MODE_DISABLED},
@@ -144,11 +147,11 @@
// Android: POSTERIZE, WHITEBOARD, BLACKBOARD.
// V4L2: ANTIQUE, ART_FREEZE, EMBOSS, GRASS_GREEN, SKETCH, SKIN_WHITEN,
// SKY_BLUE, SILHOUETTE, VIVID, SET_CBCR.
- AddComponent(V4L2ControlOrDefault<uint8_t>(
+ components.insert(V4L2ControlOrDefault<uint8_t>(
ControlType::kMenu,
ANDROID_CONTROL_EFFECT_MODE,
ANDROID_CONTROL_AVAILABLE_EFFECTS,
- device_,
+ device,
V4L2_CID_COLORFX,
std::shared_ptr<ConverterInterface<uint8_t, int32_t>>(new EnumConverter(
{{V4L2_COLORFX_NONE, ANDROID_CONTROL_EFFECT_MODE_OFF},
@@ -162,20 +165,20 @@
// Not sure if V4L2 does or doesn't do this, but HAL documentation says
// all devices must support FAST, and FAST can be equivalent to OFF, so
// either way it's fine to list.
- AddComponent(NoEffectMenuControl<uint8_t>(
- ANDROID_EDGE_MODE,
- ANDROID_EDGE_AVAILABLE_EDGE_MODES,
- {ANDROID_EDGE_MODE_FAST}));
+ components.insert(
+ NoEffectMenuControl<uint8_t>(ANDROID_EDGE_MODE,
+ ANDROID_EDGE_AVAILABLE_EDGE_MODES,
+ {ANDROID_EDGE_MODE_FAST}));
// TODO(30510395): subcomponents of hotpixel.
// No known V4L2 hot pixel correction. But it might be happening,
// so we report FAST/HIGH_QUALITY.
- AddComponent(NoEffectMenuControl<uint8_t>(
+ components.insert(NoEffectMenuControl<uint8_t>(
ANDROID_HOT_PIXEL_MODE,
ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES,
{ANDROID_HOT_PIXEL_MODE_FAST, ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY}));
// ON only needs to be supported for RAW capable devices.
- AddComponent(NoEffectMenuControl<uint8_t>(
+ components.insert(NoEffectMenuControl<uint8_t>(
ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
{ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF}));
@@ -183,56 +186,57 @@
// TODO(30510395): subcomponents focus/lens.
// No way to actually get the aperture and focal length
// in V4L2, but they're required keys, so fake them.
- AddComponent(NoEffectMenuControl<float>(
- ANDROID_LENS_APERTURE,
- ANDROID_LENS_INFO_AVAILABLE_APERTURES,
- {2.0})); // RPi camera v2 is f/2.0.
- AddComponent(NoEffectMenuControl<float>(
- ANDROID_LENS_FOCAL_LENGTH,
- ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
- {3.04})); // RPi camera v2 is 3.04mm.
+ components.insert(
+ NoEffectMenuControl<float>(ANDROID_LENS_APERTURE,
+ ANDROID_LENS_INFO_AVAILABLE_APERTURES,
+ {2.0})); // RPi camera v2 is f/2.0.
+ components.insert(
+ NoEffectMenuControl<float>(ANDROID_LENS_FOCAL_LENGTH,
+ ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
+ {3.04})); // RPi camera v2 is 3.04mm.
// No known way to get filter densities from V4L2,
// report 0 to indicate this control is not supported.
- AddComponent(NoEffectMenuControl<float>(
- ANDROID_LENS_FILTER_DENSITY,
- ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
- {0.0}));
+ components.insert(
+ NoEffectMenuControl<float>(ANDROID_LENS_FILTER_DENSITY,
+ ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
+ {0.0}));
// V4L2 focal units do not correspond to a particular physical unit.
- AddComponent(std::unique_ptr<PartialMetadataInterface>(new Property<uint8_t>(
- ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
- ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED)));
+ components.insert(
+ std::unique_ptr<PartialMetadataInterface>(new Property<uint8_t>(
+ ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
+ ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED)));
// info.hyperfocalDistance not required for UNCALIBRATED.
// No known V4L2 lens shading. But it might be happening,
// so report FAST/HIGH_QUALITY.
- AddComponent(NoEffectMenuControl<uint8_t>(
+ components.insert(NoEffectMenuControl<uint8_t>(
ANDROID_SHADING_MODE,
ANDROID_SHADING_AVAILABLE_MODES,
{ANDROID_SHADING_MODE_FAST, ANDROID_SHADING_MODE_HIGH_QUALITY}));
// ON only needs to be supported for RAW capable devices.
- AddComponent(NoEffectMenuControl<uint8_t>(
+ components.insert(NoEffectMenuControl<uint8_t>(
ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
{ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF}));
// V4L2 doesn't differentiate between OPTICAL and VIDEO stabilization,
// so only report one (and report the other as OFF).
- AddComponent(V4L2ControlOrDefault<uint8_t>(
+ components.insert(V4L2ControlOrDefault<uint8_t>(
ControlType::kMenu,
ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
- device_,
+ device,
V4L2_CID_IMAGE_STABILIZATION,
std::shared_ptr<ConverterInterface<uint8_t, int32_t>>(new EnumConverter(
{{0, ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF},
{1, ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_ON}})),
ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF));
- AddComponent(NoEffectMenuControl<uint8_t>(
+ components.insert(NoEffectMenuControl<uint8_t>(
ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
{ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF}));
// Unable to control noise reduction in V4L2 devices,
// but FAST is allowed to be the same as OFF.
- AddComponent(NoEffectMenuControl<uint8_t>(
+ components.insert(NoEffectMenuControl<uint8_t>(
ANDROID_NOISE_REDUCTION_MODE,
ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
{ANDROID_NOISE_REDUCTION_MODE_FAST}));
@@ -241,76 +245,84 @@
// For now, no thumbnails available (only [0,0], the "no thumbnail" size).
// TODO(b/29580107): Could end up with a mismatch between request & result,
// since V4L2 doesn't actually allow for thumbnail size control.
- AddComponent(NoEffectMenuControl<std::array<int32_t, 2>>(
+ components.insert(NoEffectMenuControl<std::array<int32_t, 2>>(
ANDROID_JPEG_THUMBNAIL_SIZE,
ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
{{{0, 0}}}));
// TODO(b/29939583): V4L2 can only support 1 stream at a time.
// For now, just reporting minimum allowable for LIMITED devices.
- AddComponent(std::unique_ptr<PartialMetadataInterface>(
+ components.insert(std::unique_ptr<PartialMetadataInterface>(
new Property<std::array<int32_t, 3>>(
ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
{{/* Raw */ 0, /* Non-stalling */ 2, /* Stalling */ 1}})));
// Reprocessing not supported.
- AddComponent(std::unique_ptr<PartialMetadataInterface>(
+ components.insert(std::unique_ptr<PartialMetadataInterface>(
new Property<int32_t>(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, 0)));
// No way to know pipeline depth for V4L2, so fake with max allowable latency.
// Doesn't mean much without per-frame controls anyways.
- AddComponent(std::unique_ptr<PartialMetadataInterface>(
+ components.insert(std::unique_ptr<PartialMetadataInterface>(
new Property<uint8_t>(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, 4)));
// "LIMITED devices are strongly encouraged to use a non-negative value.
// If UNKNOWN is used here then app developers do not have a way to know
// when sensor settings have been applied." - Unfortunately, V4L2 doesn't
// really help here either. Could even be that adjusting settings mid-stream
// blocks in V4L2, and should be avoided.
- AddComponent(std::unique_ptr<PartialMetadataInterface>(new Property<int32_t>(
- ANDROID_SYNC_MAX_LATENCY, ANDROID_SYNC_MAX_LATENCY_UNKNOWN)));
+ components.insert(
+ std::unique_ptr<PartialMetadataInterface>(new Property<int32_t>(
+ ANDROID_SYNC_MAX_LATENCY, ANDROID_SYNC_MAX_LATENCY_UNKNOWN)));
// TODO(30510395): subcomponents of cropping/sensors.
// V4L2 VIDIOC_CROPCAP doesn't give a way to query this;
// it's driver dependent. For now, assume freeform, and
// some cameras may just behave badly.
// TODO(b/29579652): Figure out a way to determine this.
- AddComponent(std::unique_ptr<PartialMetadataInterface>(new Property<uint8_t>(
- ANDROID_SCALER_CROPPING_TYPE, ANDROID_SCALER_CROPPING_TYPE_FREEFORM)));
+ components.insert(std::unique_ptr<PartialMetadataInterface>(
+ new Property<uint8_t>(ANDROID_SCALER_CROPPING_TYPE,
+ ANDROID_SCALER_CROPPING_TYPE_FREEFORM)));
// No way to get in V4L2, so faked. RPi camera v2 is 3.674 x 2.760 mm.
// Physical size is used in framework calculations (field of view,
// pixel pitch, etc.), so faking it may have unexpected results.
- AddComponent(std::unique_ptr<PartialMetadataInterface>(
+ components.insert(std::unique_ptr<PartialMetadataInterface>(
new Property<std::array<float, 2>>(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
{{3.674, 2.760}})));
// HAL uses BOOTTIME timestamps.
// TODO(b/29457051): make sure timestamps are consistent throughout the HAL.
- AddComponent(std::unique_ptr<PartialMetadataInterface>(
+ components.insert(std::unique_ptr<PartialMetadataInterface>(
new Property<uint8_t>(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN)));
// Noo way to actually get orientation from V4L2.
- AddComponent(std::unique_ptr<PartialMetadataInterface>(
+ components.insert(std::unique_ptr<PartialMetadataInterface>(
new Property<int32_t>(ANDROID_SENSOR_ORIENTATION, 0)));
// TODO(30510395): subcomponents of face detection.
// Face detection not supported.
- AddComponent(NoEffectMenuControl<uint8_t>(
+ components.insert(NoEffectMenuControl<uint8_t>(
ANDROID_STATISTICS_FACE_DETECT_MODE,
ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
{ANDROID_STATISTICS_FACE_DETECT_MODE_OFF}));
- AddComponent(std::unique_ptr<PartialMetadataInterface>(
+ components.insert(std::unique_ptr<PartialMetadataInterface>(
new Property<int32_t>(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, 0)));
/* Capabilities. */
// The V4L2Metadata pretends to at least meet the
// "LIMITED" and "BACKWARD_COMPATIBLE" functionality requirements.
- AddComponent(std::unique_ptr<PartialMetadataInterface>(
+ components.insert(std::unique_ptr<PartialMetadataInterface>(
new Property<uint8_t>(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)));
- AddComponent(std::unique_ptr<PartialMetadataInterface>(
+ components.insert(std::unique_ptr<PartialMetadataInterface>(
new Property<std::vector<uint8_t>>(
ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
{ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE})));
-}
-V4L2Metadata::~V4L2Metadata() {
- HAL_LOG_ENTER();
+ int res =
+ AddFormatComponents(device, std::inserter(components, components.end()));
+ if (res) {
+ HAL_LOGE("Failed to initialize format components.");
+ return res;
+ }
+
+ *result = std::make_unique<Metadata>(std::move(components));
+ return 0;
}
} // namespace v4l2_camera_hal
diff --git a/modules/camera/3_4/v4l2_metadata.h b/modules/camera/3_4/v4l2_metadata_factory.h
similarity index 61%
rename from modules/camera/3_4/v4l2_metadata.h
rename to modules/camera/3_4/v4l2_metadata_factory.h
index 29e69b9..f25a370 100644
--- a/modules/camera/3_4/v4l2_metadata.h
+++ b/modules/camera/3_4/v4l2_metadata_factory.h
@@ -14,32 +14,21 @@
* limitations under the License.
*/
-#ifndef V4L2_CAMERA_HAL_V4L2_METADATA_H_
-#define V4L2_CAMERA_HAL_V4L2_METADATA_H_
+#ifndef V4L2_CAMERA_HAL_V4L2_METADATA_FACTORY_H_
+#define V4L2_CAMERA_HAL_V4L2_METADATA_FACTORY_H_
-#include <map>
#include <memory>
-#include <hardware/camera3.h>
-
-#include "common.h"
-#include "metadata/control.h"
#include "metadata/metadata.h"
#include "v4l2_wrapper.h"
namespace v4l2_camera_hal {
-class V4L2Metadata : public Metadata {
- public:
- V4L2Metadata(std::shared_ptr<V4L2Wrapper> device);
- virtual ~V4L2Metadata();
- private:
- // Access to the device.
- std::shared_ptr<V4L2Wrapper> device_;
-
- DISALLOW_COPY_AND_ASSIGN(V4L2Metadata);
-};
+// A static function to get a Metadata object populated with V4L2 or other
+// controls as appropriate.
+int GetV4L2Metadata(std::shared_ptr<V4L2Wrapper> device,
+ std::unique_ptr<Metadata>* result);
} // namespace v4l2_camera_hal
-#endif // V4L2_CAMERA_HAL_V4L2_METADATA_H_
+#endif // V4L2_CAMERA_HAL_V4L2_METADATA_FACTORY_H_