Add format querying.
Query formats, sizes, and frame rates.
BUG: https://b/29394024, https://b/30605346
TEST: Test java program shows a bunch of formats & rates,
can take pictures in different sizes now.
Change-Id: I203fd8f200dda79cf6946c58f130548b05269fbd
diff --git a/modules/camera/3_4/v4l2_camera.cpp b/modules/camera/3_4/v4l2_camera.cpp
index f8c1c61..87a7a31 100644
--- a/modules/camera/3_4/v4l2_camera.cpp
+++ b/modules/camera/3_4/v4l2_camera.cpp
@@ -51,7 +51,7 @@
V4L2Camera* V4L2Camera::NewV4L2Camera(int id, const std::string path) {
HAL_LOG_ENTER();
- std::unique_ptr<V4L2Wrapper> v4l2_wrapper(V4L2Wrapper::NewV4L2Wrapper(path));
+ std::shared_ptr<V4L2Wrapper> v4l2_wrapper(V4L2Wrapper::NewV4L2Wrapper(path));
if (!v4l2_wrapper) {
HAL_LOGE("Failed to initialize V4L2 wrapper.");
return nullptr;
@@ -60,7 +60,7 @@
return new V4L2Camera(id, std::move(v4l2_wrapper));
}
-V4L2Camera::V4L2Camera(int id, std::unique_ptr<V4L2Wrapper> v4l2_wrapper)
+V4L2Camera::V4L2Camera(int id, std::shared_ptr<V4L2Wrapper> v4l2_wrapper)
: default_camera_hal::Camera(id),
mV4L2Device(std::move(v4l2_wrapper)),
mTemplatesInitialized(false),
@@ -75,10 +75,15 @@
int V4L2Camera::connect() {
HAL_LOG_ENTER();
- int res = mV4L2Device->Connect();
- if (res) {
+ if (mConnection) {
+ HAL_LOGE("Already connected. Please disconnect and try again.");
+ return -EIO;
+ }
+
+ mConnection.reset(new V4L2Wrapper::Connection(mV4L2Device));
+ if (mConnection->status()) {
HAL_LOGE("Failed to connect to device.");
- return res;
+ return mConnection->status();
}
// TODO(b/29185945): confirm this is a supported device.
@@ -96,7 +101,7 @@
void V4L2Camera::disconnect() {
HAL_LOG_ENTER();
- mV4L2Device->Disconnect();
+ mConnection.reset();
// TODO(b/29158098): Inform service of any flashes that are available again
// because this camera is no longer in use.
@@ -1460,35 +1465,77 @@
mVideoStabilizationModes.push_back(
ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF);
- // Need to support YUV_420_888 and JPEG.
- // TODO(b/29394024): query VIDIOC_ENUM_FMT.
- std::vector<uint32_t> formats = {{V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_YUV420}};
- // We want to find the smallest maximum frame duration amongst formats.
- mMaxFrameDuration = std::numeric_limits<int64_t>::max();
- int64_t min_yuv_frame_duration = std::numeric_limits<int64_t>::max();
- for (auto format : formats) {
- int32_t hal_format = StreamFormat::V4L2ToHalPixelFormat(format);
+ // Need to be connected to query the device.
+ V4L2Wrapper::Connection temp_connection(mV4L2Device);
+ if (temp_connection.status()) {
+ HAL_LOGE("Failed to connect to device.");
+ return temp_connection.status();
+ }
+
+ // Get all supported formats.
+ std::set<uint32_t> v4l2_formats;
+ int res = mV4L2Device->GetFormats(&v4l2_formats);
+ if (res) {
+ HAL_LOGE("Failed to get device formats.");
+ return res;
+ }
+ std::set<int32_t> hal_formats;
+ for (auto v4l2_format : v4l2_formats) {
+ int32_t hal_format = StreamFormat::V4L2ToHalPixelFormat(v4l2_format);
if (hal_format < 0) {
// Unrecognized/unused format. Skip it.
continue;
}
- // TODO(b/29394024): query VIDIOC_ENUM_FRAMESIZES.
- // For now, just 640x480.
- ArrayVector<int32_t, 2> frame_sizes;
- frame_sizes.push_back({{640, 480}});
- size_t num_frame_sizes = frame_sizes.num_arrays();
- for (size_t i = 0; i < num_frame_sizes; ++i) {
- const int32_t* frame_size = frame_sizes[i];
+ hal_formats.insert(hal_format);
+ }
+ // In addition to well-defined formats, must support "Implementation Defined"
+ // (in this case what that means is managed by the StreamFormat class).
+ hal_formats.insert(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
+
+ // Requirements check: need to support YCbCr_420_888 and JPEG.
+ 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;
+ }
+
+ // Find sizes and frame durations for all formats.
+ // We also want to find the smallest max frame duration amongst all formats.
+ mMaxFrameDuration = std::numeric_limits<int64_t>::max();
+ int64_t min_yuv_frame_duration = std::numeric_limits<int64_t>::max();
+ for (auto hal_format : hal_formats) {
+ 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;
+ }
+
+ std::set<std::array<int32_t, 2>> frame_sizes;
+ res = mV4L2Device->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) {
mStreamConfigs.push_back({{hal_format, frame_size[0], frame_size[1],
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT}});
- // TODO(b/29394024): query VIDIOC_ENUM_FRAMEINTERVALS.
- // For now, using the emulator max value of .3 sec.
- int64_t max_frame_duration = 300000000;
- // For now, min value of 30 fps = 1/30 spf ~= 33333333 ns.
- // For whatever reason the goldfish/qcom cameras report this as
- // 33331760, so copying that.
- int64_t min_frame_duration = 33331760;
+ std::array<int64_t, 2> duration_range;
+ res = mV4L2Device->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 min_frame_duration = duration_range[0];
+ int64_t max_frame_duration = duration_range[1];
mMinFrameDurations.push_back(
{{hal_format, frame_size[0], frame_size[1], min_frame_duration}});