Patch Detail
Show a patch.
GET /api/1.1/patches/3915/?format=api
{ "id": 3915, "url": "https://patchwork.libcamera.org/api/1.1/patches/3915/?format=api", "web_url": "https://patchwork.libcamera.org/patch/3915/", "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": "<20200604133503.14689-2-jacopo@jmondi.org>", "date": "2020-06-04T13:35:00", "name": "[libcamera-devel,v2,1/4] android: camera_device: Build stream configuration", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": true, "hash": "2581238f2b8d986cd0257d08f5903d1cf552211a", "submitter": { "id": 3, "url": "https://patchwork.libcamera.org/api/1.1/people/3/?format=api", "name": "Jacopo Mondi", "email": "jacopo@jmondi.org" }, "delegate": { "id": 15, "url": "https://patchwork.libcamera.org/api/1.1/users/15/?format=api", "username": "jmondi", "first_name": "Jacopo", "last_name": "Mondi", "email": "jacopo@jmondi.org" }, "mbox": "https://patchwork.libcamera.org/patch/3915/mbox/", "series": [ { "id": 951, "url": "https://patchwork.libcamera.org/api/1.1/series/951/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=951", "date": "2020-06-04T13:34:59", "name": "android: Implement format translation", "version": 2, "mbox": "https://patchwork.libcamera.org/series/951/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/3915/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/3915/checks/", "tags": {}, "headers": { "Return-Path": "<jacopo@jmondi.org>", "Received": [ "from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net\n\t[217.70.183.197])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D6C5C610A5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 4 Jun 2020 15:31:46 +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 relay5-d.mail.gandi.net (Postfix) with ESMTPSA id 59CFD1C000E;\n\tThu, 4 Jun 2020 13:31:46 +0000 (UTC)" ], "X-Originating-IP": "2.224.242.101", "From": "Jacopo Mondi <jacopo@jmondi.org>", "To": "libcamera-devel@lists.libcamera.org", "Date": "Thu, 4 Jun 2020 15:35:00 +0200", "Message-Id": "<20200604133503.14689-2-jacopo@jmondi.org>", "X-Mailer": "git-send-email 2.26.2", "In-Reply-To": "<20200604133503.14689-1-jacopo@jmondi.org>", "References": "<20200604133503.14689-1-jacopo@jmondi.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[libcamera-devel] [PATCH v2 1/4] android: camera_device: Build\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": "Thu, 04 Jun 2020 13:31:47 -0000" }, "content": "Build 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 | 218 ++++++++++++++++++++++++++++++++++\n src/android/camera_device.h | 12 ++\n 2 files changed, 230 insertions(+)", "diff": "diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\nindex b30263451b76..0c462f53c9cc 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,70 @@\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 Camera3Format::libcameraFormats: List of libcamera pixel formats\n+ * compatible with the Android format\n+ * \\var Camera3Format::scalerFormat: The format identifier to be reported to the\n+ * android framework through the static format configuration map\n+ */\n+struct Camera3Format {\n+\tstd::vector<PixelFormat> libcameraFormats;\n+\tcamera_metadata_enum_android_scaler_available_formats_t scalerFormat;\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}\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}\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_YCbCr_420_888\n+\t\t}\n+\t},\n+};\n+\n+} /* namespace */\n+\n LOG_DECLARE_CATEGORY(HAL);\n \n /*\n@@ -100,6 +163,161 @@ 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 = initializeFormats();\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::initializeFormats()\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 &format : 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 = format;\n+\n+\t\t\tCameraConfiguration::Status status = cameraConfig->validate();\n+\t\t\tif (status != CameraConfiguration::Invalid &&\n+\t\t\t cfg.pixelFormat == format) {\n+\t\t\t\tmappedFormat = format;\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<< 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..d31b7233e795 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 initializeFormats();\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", "v2", "1/4" ] }