Patch Detail
Show a patch.
GET /api/1.1/patches/3945/?format=api
{ "id": 3945, "url": "https://patchwork.libcamera.org/api/1.1/patches/3945/?format=api", "web_url": "https://patchwork.libcamera.org/patch/3945/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20200605141002.49119-2-jacopo@jmondi.org>", "date": "2020-06-05T14:09:55", "name": "[libcamera-devel,v3,1/8] android: camera_device: Initialize stream configuration", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "40e67270558b208306307dfb382d9bbcac0ce0f8", "submitter": { "id": 3, "url": "https://patchwork.libcamera.org/api/1.1/people/3/?format=api", "name": "Jacopo Mondi", "email": "jacopo@jmondi.org" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/3945/mbox/", "series": [ { "id": 958, "url": "https://patchwork.libcamera.org/api/1.1/series/958/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=958", "date": "2020-06-05T14:09:54", "name": "android: Build stream configuration map", "version": 3, "mbox": "https://patchwork.libcamera.org/series/958/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/3945/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/3945/checks/", "tags": {}, "headers": { "Return-Path": "<jacopo@jmondi.org>", "Received": [ "from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net\n\t[217.70.183.200])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 142C360410\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 5 Jun 2020 16:07:07 +0200 (CEST)", "from localhost.localdomain (93-34-118-233.ip49.fastwebnet.it\n\t[93.34.118.233]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay7-d.mail.gandi.net (Postfix) with ESMTPSA id 7ABD62000D;\n\tFri, 5 Jun 2020 14:07:06 +0000 (UTC)" ], "X-Originating-IP": "93.34.118.233", "From": "Jacopo Mondi <jacopo@jmondi.org>", "To": "libcamera-devel@lists.libcamera.org", "Date": "Fri, 5 Jun 2020 16:09:55 +0200", "Message-Id": "<20200605141002.49119-2-jacopo@jmondi.org>", "X-Mailer": "git-send-email 2.27.0", "In-Reply-To": "<20200605141002.49119-1-jacopo@jmondi.org>", "References": "<20200605141002.49119-1-jacopo@jmondi.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[libcamera-devel] [PATCH v3 1/8] android: camera_device: Initialize\n\tstream configuration", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "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": "Fri, 05 Jun 2020 14:07:07 -0000" }, "content": "Initialize the stream configuration map by applying the Android Camera3\nrequested resolutions and formats to the libcamera Camera device.\n\nFor each required format test a list of required and optional\nresolutions, construct a map to translate from Android format to the\nlibcamera formats and store the available stream configuration to\nbe provided to the Android framework through static metadata.\n\nSigned-off-by: Jacopo Mondi <jacopo@jmondi.org>\n---\n src/android/camera_device.cpp | 224 ++++++++++++++++++++++++++++++++++\n src/android/camera_device.h | 12 ++\n 2 files changed, 236 insertions(+)", "diff": "diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\nindex b30263451b76..cb9e4a6bc15b 100644\n--- a/src/android/camera_device.cpp\n+++ b/src/android/camera_device.cpp\n@@ -8,6 +8,8 @@\n #include \"camera_device.h\"\n #include \"camera_ops.h\"\n \n+#include <vector>\n+\n #include <libcamera/controls.h>\n #include <libcamera/property_ids.h>\n \n@@ -15,9 +17,75 @@\n #include \"libcamera/internal/utils.h\"\n \n #include \"camera_metadata.h\"\n+#include \"system/graphics.h\"\n \n using namespace libcamera;\n \n+namespace {\n+\n+/*\n+ * \\var camera3Resolutions\n+ * \\brief The list of image resolutions defined as mandatory to be supported by\n+ * the Android Camera3 specification\n+ */\n+const std::vector<Size> camera3Resolutions = {\n+\t{ 320, 240 },\n+\t{ 640, 480 },\n+\t{ 1280, 720 },\n+\t{ 1920, 1080 }\n+};\n+\n+/*\n+ * \\struct Camera3Format\n+ * \\brief Data associated with an Android format identifier\n+ * \\var libcameraFormats List of libcamera pixel formats compatible with the\n+ * Android format\n+ * \\var scalerFormat The format identifier to be reported to the android\n+ * framework through the static format configuration map\n+ * \\var formatName The human-readable representation of the Android format code\n+ */\n+struct Camera3Format {\n+\tstd::vector<PixelFormat> libcameraFormats;\n+\tcamera_metadata_enum_android_scaler_available_formats_t scalerFormat;\n+\tconst char *formatName;\n+};\n+\n+/*\n+ * \\var camera3FormatsMap\n+ * \\brief Associate Android format code with ancillary data\n+ */\n+const std::map<int, const Camera3Format> camera3FormatsMap = {\n+\t{\n+\t\tHAL_PIXEL_FORMAT_BLOB, {\n+\t\t\t{ PixelFormat(DRM_FORMAT_MJPEG) },\n+\t\t\tANDROID_SCALER_AVAILABLE_FORMATS_BLOB,\n+\t\t\t\"HAL_PIXEL_FORMAT_BLOB\"\n+\t\t}\n+\t},\n+\n+\t{\n+\t\tHAL_PIXEL_FORMAT_YCbCr_420_888, {\n+\t\t\t{ PixelFormat(DRM_FORMAT_NV12), PixelFormat(DRM_FORMAT_NV21) },\n+\t\t\tANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888,\n+\t\t\t\"HAL_PIXEL_FORMAT_YCbCr_420_888\"\n+\t\t}\n+\t},\n+\n+\t/*\n+\t * \\todo Translate IMPLEMENTATION_DEFINED inspecting the\n+\t * gralloc usage flag. For now, copy the YCbCr_420 configuration.\n+\t */\n+\t{\n+\t\tHAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, {\n+\t\t\t{ PixelFormat(DRM_FORMAT_NV12), PixelFormat(DRM_FORMAT_NV21) },\n+\t\t\tANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED,\n+\t\t\t\"HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED\"\n+\t\t}\n+\t},\n+};\n+\n+} /* namespace */\n+\n LOG_DECLARE_CATEGORY(HAL);\n \n /*\n@@ -100,6 +168,162 @@ int CameraDevice::initialize()\n \tif (properties.contains(properties::Rotation))\n \t\torientation_ = properties.get(properties::Rotation);\n \n+\tint ret = camera_->acquire();\n+\tif (ret) {\n+\t\tLOG(HAL, Error) << \"Failed to temporarily acquire the camera\";\n+\t\treturn ret;\n+\t}\n+\n+\tret = initializeStreamConfigurations();\n+\tcamera_->release();\n+\treturn ret;\n+}\n+\n+/*\n+ * Initialize the format conversion map to translate from Android format\n+ * identifier to libcamera pixel formats and fill in the list of supported\n+ * stream configurations to be reported to the Android camera framework through\n+ * the static stream configuration metadata.\n+ */\n+int CameraDevice::initializeStreamConfigurations()\n+{\n+\t/*\n+\t * Get the maximum output resolutions\n+\t * \\todo Get this from the camera properties once defined\n+\t */\n+\tstd::unique_ptr<CameraConfiguration> cameraConfig =\n+\t\tcamera_->generateConfiguration({ StillCapture });\n+\tif (!cameraConfig) {\n+\t\tLOG(HAL, Error) << \"Failed to get maximum resolution\";\n+\t\treturn -EINVAL;\n+\t}\n+\tStreamConfiguration &cfg = cameraConfig->at(0);\n+\n+\t/*\n+\t * \\todo JPEG - Adjust the maximum available resolution by taking the\n+\t * JPEG encoder requirements into account (alignment and aspect ratio).\n+\t */\n+\tconst Size maxRes = cfg.size;\n+\tLOG(HAL, Debug) << \"Maximum supported resolution: \" << maxRes.toString();\n+\n+\t/*\n+\t * Build the list of supported image resolutions.\n+\t *\n+\t * The resolutions listed in camera3Resolution are mandatory to be\n+\t * supported, up to the camera maximum resolution.\n+\t *\n+\t * Augment the list by adding resolutions calculated from the camera\n+\t * maximum one.\n+\t */\n+\tstd::vector<Size> cameraResolutions;\n+\tstd::copy_if(camera3Resolutions.begin(), camera3Resolutions.end(),\n+\t\t std::back_inserter(cameraResolutions),\n+\t\t [&](const Size &res) { return res < maxRes; });\n+\n+\t/* Camera3 specification suggests to add 1/2 and 1/4 max resolution. */\n+\tfor (unsigned int divider = 2;; divider <<= 1) {\n+\t\tSize derivedSize{\n+\t\t\tmaxRes.width / divider,\n+\t\t\tmaxRes.height / divider,\n+\t\t};\n+\n+\t\tif (derivedSize.width < 320 ||\n+\t\t derivedSize.height < 240)\n+\t\t\tbreak;\n+\n+\t\tcameraResolutions.push_back(derivedSize);\n+\t}\n+\tcameraResolutions.push_back(maxRes);\n+\n+\t/* Remove duplicated entries from the list of supported resolutions. */\n+\tstd::sort(cameraResolutions.begin(), cameraResolutions.end());\n+\tauto last = std::unique(cameraResolutions.begin(), cameraResolutions.end());\n+\tcameraResolutions.erase(last, cameraResolutions.end());\n+\n+\t/*\n+\t * Build the list of supported camera formats.\n+\t *\n+\t * To each Android format a list of compatible libcamera formats is\n+\t * associated. The first libcamera format that tests successful is added\n+\t * to the format translation map used when configuring the streams.\n+\t * It is then tested against the list of supported camera resolutions to\n+\t * build the stream configuration map reported through the camera static\n+\t * metadata.\n+\t */\n+\tfor (const auto &format : camera3FormatsMap) {\n+\t\tint androidFormat = format.first;\n+\t\tconst Camera3Format &camera3Format = format.second;\n+\t\tconst std::vector<PixelFormat> &libcameraFormats =\n+\t\t\tcamera3Format.libcameraFormats;\n+\n+\t\t/*\n+\t\t * Test the libcamera formats that can produce images\n+\t\t * compatible with the Android defined format.\n+\t\t */\n+\t\tPixelFormat mappedFormat{};\n+\t\tfor (const PixelFormat &pixelFormat : libcameraFormats) {\n+\t\t\t/* \\todo Fixed mapping for JPEG. */\n+\t\t\tif (androidFormat == HAL_PIXEL_FORMAT_BLOB) {\n+\t\t\t\tmappedFormat = PixelFormat(DRM_FORMAT_MJPEG);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\n+\t\t\t/*\n+\t\t\t * The stream configuration size can be adjusted,\n+\t\t\t * not the pixel format.\n+\t\t\t *\n+\t\t\t * \\todo This could be simplified once all pipeline\n+\t\t\t * handlers will report the StreamFormats list of\n+\t\t\t * supported formats.\n+\t\t\t */\n+\t\t\tcfg.pixelFormat = pixelFormat;\n+\n+\t\t\tCameraConfiguration::Status status = cameraConfig->validate();\n+\t\t\tif (status != CameraConfiguration::Invalid &&\n+\t\t\t cfg.pixelFormat == pixelFormat) {\n+\t\t\t\tmappedFormat = pixelFormat;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tif (!mappedFormat.isValid()) {\n+\t\t\tLOG(HAL, Error) << \"Failed to map Android format \"\n+\t\t\t\t\t<< camera3Format.formatName << \" (\"\n+\t\t\t\t\t<< utils::hex(androidFormat) << \")\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\t/*\n+\t\t * Record the mapping and then proceed to generate the\n+\t\t * stream configurations map, by testing the image resolutions.\n+\t\t */\n+\t\tformatsMap_[androidFormat] = mappedFormat;\n+\n+\t\tfor (const Size &res : cameraResolutions) {\n+\t\t\tcfg.pixelFormat = mappedFormat;\n+\t\t\tcfg.size = res;\n+\n+\t\t\tCameraConfiguration::Status status = cameraConfig->validate();\n+\t\t\t/*\n+\t\t\t * Unconditionally report we can produce JPEG.\n+\t\t\t *\n+\t\t\t * \\todo The JPEG stream will be implemented as an\n+\t\t\t * HAL-only stream, but some cameras can produce it\n+\t\t\t * directly. As of now, claim support for JPEG without\n+\t\t\t * inspecting where the JPEG stream is produced.\n+\t\t\t */\n+\t\t\tif (androidFormat != HAL_PIXEL_FORMAT_BLOB &&\n+\t\t\t status != CameraConfiguration::Valid)\n+\t\t\t\tcontinue;\n+\n+\t\t\tstreamConfigurations_.push_back({ res, camera3Format.scalerFormat });\n+\t\t}\n+\t}\n+\n+\tLOG(HAL, Debug) << \"Collected stream configuration map: \";\n+\tfor (const auto &entry : streamConfigurations_)\n+\t\tLOG(HAL, Debug) << \"{ \" << entry.resolution.toString() << \" - \"\n+\t\t\t\t<< utils::hex(entry.androidScalerCode) << \" }\";\n+\n \treturn 0;\n }\n \ndiff --git a/src/android/camera_device.h b/src/android/camera_device.h\nindex a87f7623c790..4e8911da5770 100644\n--- a/src/android/camera_device.h\n+++ b/src/android/camera_device.h\n@@ -7,12 +7,15 @@\n #ifndef __ANDROID_CAMERA_DEVICE_H__\n #define __ANDROID_CAMERA_DEVICE_H__\n \n+#include <map>\n #include <memory>\n+#include <vector>\n \n #include <hardware/camera3.h>\n \n #include <libcamera/buffer.h>\n #include <libcamera/camera.h>\n+#include <libcamera/geometry.h>\n #include <libcamera/request.h>\n #include <libcamera/stream.h>\n \n@@ -59,6 +62,12 @@ private:\n \t\tcamera3_stream_buffer_t *buffers;\n \t};\n \n+\tstruct Camera3StreamConfiguration {\n+\t\tlibcamera::Size resolution;\n+\t\tint androidScalerCode;\n+\t};\n+\n+\tint initializeStreamConfigurations();\n \tvoid notifyShutter(uint32_t frameNumber, uint64_t timestamp);\n \tvoid notifyError(uint32_t frameNumber, camera3_stream_t *stream);\n \tstd::unique_ptr<CameraMetadata> getResultMetadata(int frame_number,\n@@ -75,6 +84,9 @@ private:\n \tstd::map<unsigned int, CameraMetadata *> requestTemplates_;\n \tconst camera3_callback_ops_t *callbacks_;\n \n+\tstd::vector<Camera3StreamConfiguration> streamConfigurations_;\n+\tstd::map<int, libcamera::PixelFormat> formatsMap_;\n+\n \tint facing_;\n \tint orientation_;\n };\n", "prefixes": [ "libcamera-devel", "v3", "1/8" ] }