Show a patch.

GET /api/1.1/patches/9277/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 9277,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/9277/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/9277/",
    "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": "<20200810130110.429191-1-kieran.bingham@ideasonboard.com>",
    "date": "2020-08-10T13:01:10",
    "name": "[libcamera-devel] Documentation: Vivid Pipeline",
    "commit_ref": null,
    "pull_url": null,
    "state": "rejected",
    "archived": false,
    "hash": "f69ac56c1cd0fe765f4b233509260ce2ec290faf",
    "submitter": {
        "id": 4,
        "url": "https://patchwork.libcamera.org/api/1.1/people/4/?format=api",
        "name": "Kieran Bingham",
        "email": "kieran.bingham@ideasonboard.com"
    },
    "delegate": {
        "id": 11,
        "url": "https://patchwork.libcamera.org/api/1.1/users/11/?format=api",
        "username": "kbingham",
        "first_name": "Kieran",
        "last_name": "Bingham",
        "email": "kieran.bingham@ideasonboard.com"
    },
    "mbox": "https://patchwork.libcamera.org/patch/9277/mbox/",
    "series": [
        {
            "id": 1211,
            "url": "https://patchwork.libcamera.org/api/1.1/series/1211/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=1211",
            "date": "2020-08-10T13:01:10",
            "name": "[libcamera-devel] Documentation: Vivid Pipeline",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/1211/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/9277/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/9277/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>",
        "X-Original-To": "parsemail@patchwork.libcamera.org",
        "Delivered-To": "parsemail@patchwork.libcamera.org",
        "Received": [
            "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 17F5ABD87C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 10 Aug 2020 13:01:21 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 94A3360F72;\n\tMon, 10 Aug 2020 15:01:20 +0200 (CEST)",
            "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 779076038C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 10 Aug 2020 15:01:19 +0200 (CEST)",
            "from Q.local (cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net\n\t[86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 1B921F9;\n\tMon, 10 Aug 2020 15:01:14 +0200 (CEST)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"P0/XFj4S\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1597064474;\n\tbh=wYWeTIid+4V8JqSnee2isbIqvoQhayeEDa8xdVj1CpQ=;\n\th=From:To:Cc:Subject:Date:From;\n\tb=P0/XFj4SJncM3vtXGf/P+LW46XSPTaryqQyhqAO07HCatz+npIWuzdygFUGjM8stB\n\tVHZMgPq/Y+bhhILIOPwb7b+gYgTzk3jAVds0Q2Vmmdq93TduaZ2/03vwp8IFWIu9pV\n\t+zeDNyznwPd/s3zrLhLuNk+AlrrNLs9byRFo3gLU=",
        "From": "Kieran Bingham <kieran.bingham@ideasonboard.com>",
        "To": "libcamera devel <libcamera-devel@lists.libcamera.org>",
        "Date": "Mon, 10 Aug 2020 14:01:10 +0100",
        "Message-Id": "<20200810130110.429191-1-kieran.bingham@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "MIME-Version": "1.0",
        "Subject": "[libcamera-devel] [PATCH] Documentation: Vivid Pipeline",
        "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>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "Provide the patches for the Vivid pipeline within the Documentation tree.\nThese patches are not destined for direct integration, but serve as a reference\nfor implementing a new pipeline handler.\n\nKeep the patches within the tree to allow tracking updates, and making them\naccessible to developers.\n\nSigned-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n---\n .../0000-cover-letter.patch                   |  56 ++++++\n ...ne-Introduce-skeleton-Vivid-Pipeline.patch | 139 +++++++++++++++\n ...ibcamera-pipeline-vivid-Match-device.patch |  54 ++++++\n ...amera-pipeline-vivid-Create-a-Camera.patch | 110 ++++++++++++\n ...ne-vivid-Generate-and-validate-Strea.patch | 160 ++++++++++++++++++\n ...-pipeline-vivid-Configure-the-device.patch |  71 ++++++++\n ...ne-vivid-Buffer-handling-and-stream-.patch | 102 +++++++++++\n ...camera-pipeline-vivid-Queue-requests.patch |  45 +++++\n ...peline-vivid-Initialise-key-controls.patch |  70 ++++++++\n ...amera-pipeline-vivid-Handle-controls.patch | 133 +++++++++++++++\n 10 files changed, 940 insertions(+)\n create mode 100644 Documentation/vivid-pipeline-handler/0000-cover-letter.patch\n create mode 100644 Documentation/vivid-pipeline-handler/0001-libcamera-pipeline-Introduce-skeleton-Vivid-Pipeline.patch\n create mode 100644 Documentation/vivid-pipeline-handler/0002-libcamera-pipeline-vivid-Match-device.patch\n create mode 100644 Documentation/vivid-pipeline-handler/0003-libcamera-pipeline-vivid-Create-a-Camera.patch\n create mode 100644 Documentation/vivid-pipeline-handler/0004-libcamera-pipeline-vivid-Generate-and-validate-Strea.patch\n create mode 100644 Documentation/vivid-pipeline-handler/0005-libcamera-pipeline-vivid-Configure-the-device.patch\n create mode 100644 Documentation/vivid-pipeline-handler/0006-libcamera-pipeline-vivid-Buffer-handling-and-stream-.patch\n create mode 100644 Documentation/vivid-pipeline-handler/0007-libcamera-pipeline-vivid-Queue-requests.patch\n create mode 100644 Documentation/vivid-pipeline-handler/0008-libcamera-pipeline-vivid-Initialise-key-controls.patch\n create mode 100644 Documentation/vivid-pipeline-handler/0009-libcamera-pipeline-vivid-Handle-controls.patch",
    "diff": "diff --git a/Documentation/vivid-pipeline-handler/0000-cover-letter.patch b/Documentation/vivid-pipeline-handler/0000-cover-letter.patch\nnew file mode 100644\nindex 000000000000..25e61d4313ff\n--- /dev/null\n+++ b/Documentation/vivid-pipeline-handler/0000-cover-letter.patch\n@@ -0,0 +1,56 @@\n+From 03bbac3265554b73e6ddcdebaf95090062e3669f Mon Sep 17 00:00:00 2001\n+From: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+Date: Mon, 10 Aug 2020 13:28:23 +0100\n+Subject: [PATCH 0/9] libcamera: pipeline: Add a VIVID Pipeline Handler\n+\n+Introduce a new pipeline handler to support the virtual video test\n+driver provided by V4L2.\n+\n+These patches are intended to serve as a code-guide for writing a new\n+pipeline handler, and can be referenced along side the Pipeline Handler\n+Writers Guide documentation.\n+\n+To test these patches, apply locally to your libcamera sources by\n+executing the following:\n+\n+  git am Documentation/vivid-pipeline-handler/*\n+\n+Then test by ensuring you have the vivid module loaded:\n+\n+  sudo modprobe vivid\n+\n+To enable the new pipeline handler the build must be re-configured. A\n+limitation in the meson build system means that this requires a full\n+reconfiguration. The easiest solution of which is to remove any existing\n+build and commence with a fresh build tree.\n+\n+Configure, build and test:\n+\n+  rm -r build\n+  meson build\n+  cd build\n+  ninja\n+ \n+ \n+\n+Kieran Bingham (9):\n+  libcamera: pipeline: Introduce skeleton Vivid Pipeline\n+  libcamera: pipeline: vivid: Match device\n+  libcamera: pipeline: vivid: Create a Camera\n+  libcamera: pipeline: vivid: Generate and validate StreamConfigurations\n+  libcamera: pipeline: vivid: Configure the device\n+  libcamera: pipeline: vivid: Buffer handling and stream control\n+  libcamera: pipeline: vivid: Queue requests\n+  libcamera: pipeline: vivid: Initialise key controls\n+  libcamera: pipeline: vivid: Handle controls\n+\n+ meson_options.txt                        |   2 +-\n+ src/libcamera/pipeline/vivid/meson.build |   5 +\n+ src/libcamera/pipeline/vivid/vivid.cpp   | 382 +++++++++++++++++++++++\n+ 3 files changed, 388 insertions(+), 1 deletion(-)\n+ create mode 100644 src/libcamera/pipeline/vivid/meson.build\n+ create mode 100644 src/libcamera/pipeline/vivid/vivid.cpp\n+\n+-- \n+2.25.1\n+\ndiff --git a/Documentation/vivid-pipeline-handler/0001-libcamera-pipeline-Introduce-skeleton-Vivid-Pipeline.patch b/Documentation/vivid-pipeline-handler/0001-libcamera-pipeline-Introduce-skeleton-Vivid-Pipeline.patch\nnew file mode 100644\nindex 000000000000..ca1dc48e4fb9\n--- /dev/null\n+++ b/Documentation/vivid-pipeline-handler/0001-libcamera-pipeline-Introduce-skeleton-Vivid-Pipeline.patch\n@@ -0,0 +1,139 @@\n+From 2480348e61bfcbc8a113a03e6090308f9b904acb Mon Sep 17 00:00:00 2001\n+From: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+Date: Fri, 10 Jul 2020 15:13:05 +0100\n+Subject: [PATCH 1/9] libcamera: pipeline: Introduce skeleton Vivid Pipeline\n+\n+Provide all of the skeleton stubs to succesfully compile\n+and register a new Pipeline Handler for the Vivid test device.\n+\n+Meson must be reconfigured to ensure that this pipeline handler is\n+included in the selected pipelines configuration, and after building, we\n+can test that the PipelineHandler is successfully registered by listing\n+the cameras on the system with LIBCAMERA_LOG_LEVELS enabled:\n+\n+\"\"\"\n+LIBCAMERA_LOG_LEVELS=Pipeline:0 ./build-vivid/src/cam/cam -l\n+[230:30:03.624102821] [2867886] DEBUG Pipeline pipeline_handler.cpp:680 Registered pipeline handler \"PipelineHandlerVivid\"\n+Available cameras:\n+\"\"\"\n+\n+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+---\n+ meson_options.txt                        |  2 +-\n+ src/libcamera/pipeline/vivid/meson.build |  5 ++\n+ src/libcamera/pipeline/vivid/vivid.cpp   | 78 ++++++++++++++++++++++++\n+ 3 files changed, 84 insertions(+), 1 deletion(-)\n+ create mode 100644 src/libcamera/pipeline/vivid/meson.build\n+ create mode 100644 src/libcamera/pipeline/vivid/vivid.cpp\n+\n+diff --git a/meson_options.txt b/meson_options.txt\n+index e9e815fde366..ea38f1553240 100644\n+--- a/meson_options.txt\n++++ b/meson_options.txt\n+@@ -16,7 +16,7 @@ option('gstreamer',\n+ \n+ option('pipelines',\n+         type : 'array',\n+-        choices : ['ipu3', 'raspberrypi', 'rkisp1', 'simple', 'uvcvideo', 'vimc'],\n++        choices : ['ipu3', 'raspberrypi', 'rkisp1', 'simple', 'uvcvideo', 'vimc', 'vivid'],\n+         description : 'Select which pipeline handlers to include')\n+ \n+ option('qcam',\n+diff --git a/src/libcamera/pipeline/vivid/meson.build b/src/libcamera/pipeline/vivid/meson.build\n+new file mode 100644\n+index 000000000000..086bb825387c\n+--- /dev/null\n++++ b/src/libcamera/pipeline/vivid/meson.build\n+@@ -0,0 +1,5 @@\n++# SPDX-License-Identifier: CC0-1.0\n++\n++libcamera_sources += files([\n++    'vivid.cpp',\n++])\n+diff --git a/src/libcamera/pipeline/vivid/vivid.cpp b/src/libcamera/pipeline/vivid/vivid.cpp\n+new file mode 100644\n+index 000000000000..4418f616fe84\n+--- /dev/null\n++++ b/src/libcamera/pipeline/vivid/vivid.cpp\n+@@ -0,0 +1,78 @@\n++/* SPDX-License-Identifier: LGPL-2.1-or-later */\n++/*\n++ * Copyright (C) 2020, Google Inc.\n++ *\n++ * vivid.cpp - Pipeline handler for the vivid capture device\n++ */\n++\n++#include \"libcamera/internal/log.h\"\n++#include \"libcamera/internal/pipeline_handler.h\"\n++\n++namespace libcamera {\n++\n++LOG_DEFINE_CATEGORY(VIVID)\n++\n++class PipelineHandlerVivid : public PipelineHandler\n++{\n++public:\n++\tPipelineHandlerVivid(CameraManager *manager);\n++\n++\tCameraConfiguration *generateConfiguration(Camera *camera,\n++\t\t\t\t\t\t   const StreamRoles &roles) override;\n++\tint configure(Camera *camera, CameraConfiguration *config) override;\n++\n++\tint exportFrameBuffers(Camera *camera, Stream *stream,\n++\t\t\t       std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;\n++\n++\tint start(Camera *camera) override;\n++\tvoid stop(Camera *camera) override;\n++\n++\tint queueRequestDevice(Camera *camera, Request *request) override;\n++\n++\tbool match(DeviceEnumerator *enumerator) override;\n++};\n++\n++PipelineHandlerVivid::PipelineHandlerVivid(CameraManager *manager)\n++\t: PipelineHandler(manager)\n++{\n++}\n++\n++CameraConfiguration *PipelineHandlerVivid::generateConfiguration(Camera *camera,\n++\t\t\t\t\t\t\t\t const StreamRoles &roles)\n++{\n++\treturn nullptr;\n++}\n++\n++int PipelineHandlerVivid::configure(Camera *camera, CameraConfiguration *config)\n++{\n++\treturn -1;\n++}\n++\n++int PipelineHandlerVivid::exportFrameBuffers(Camera *camera, Stream *stream,\n++\t\t\t\t\t     std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n++{\n++\treturn -1;\n++}\n++\n++int PipelineHandlerVivid::start(Camera *camera)\n++{\n++\treturn -1;\n++}\n++\n++void PipelineHandlerVivid::stop(Camera *camera)\n++{\n++}\n++\n++int PipelineHandlerVivid::queueRequestDevice(Camera *camera, Request *request)\n++{\n++\treturn -1;\n++}\n++\n++bool PipelineHandlerVivid::match(DeviceEnumerator *enumerator)\n++{\n++\treturn false;\n++}\n++\n++REGISTER_PIPELINE_HANDLER(PipelineHandlerVivid);\n++\n++} /* namespace libcamera */\n+-- \n+2.25.1\n+\ndiff --git a/Documentation/vivid-pipeline-handler/0002-libcamera-pipeline-vivid-Match-device.patch b/Documentation/vivid-pipeline-handler/0002-libcamera-pipeline-vivid-Match-device.patch\nnew file mode 100644\nindex 000000000000..a48eeeac1fe9\n--- /dev/null\n+++ b/Documentation/vivid-pipeline-handler/0002-libcamera-pipeline-vivid-Match-device.patch\n@@ -0,0 +1,54 @@\n+From d676cff10779a5a8f286cf0553f52c5f747436f0 Mon Sep 17 00:00:00 2001\n+From: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+Date: Fri, 10 Jul 2020 15:37:55 +0100\n+Subject: [PATCH 2/9] libcamera: pipeline: vivid: Match device\n+\n+Verify that we can match on our expected device(s).\n+\n+Use a temporary debug print to check that the pipeline finds\n+our device:\n+\n+\"\"\"\n+LIBCAMERA_LOG_LEVELS=Pipeline,VIVID:0 ./src/cam/cam -l\n+<snipped>\n+[230:51:10.670503423] [2872877] DEBUG VIVID vivid.cpp:81 Obtained Vivid Device\n+\"\"\"\n+\n+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+---\n+ src/libcamera/pipeline/vivid/vivid.cpp | 12 +++++++++++-\n+ 1 file changed, 11 insertions(+), 1 deletion(-)\n+\n+diff --git a/src/libcamera/pipeline/vivid/vivid.cpp b/src/libcamera/pipeline/vivid/vivid.cpp\n+index 4418f616fe84..9811f6ef5095 100644\n+--- a/src/libcamera/pipeline/vivid/vivid.cpp\n++++ b/src/libcamera/pipeline/vivid/vivid.cpp\n+@@ -5,6 +5,7 @@\n+  * vivid.cpp - Pipeline handler for the vivid capture device\n+  */\n+ \n++#include \"libcamera/internal/device_enumerator.h\"\n+ #include \"libcamera/internal/log.h\"\n+ #include \"libcamera/internal/pipeline_handler.h\"\n+ \n+@@ -70,7 +71,16 @@ int PipelineHandlerVivid::queueRequestDevice(Camera *camera, Request *request)\n+ \n+ bool PipelineHandlerVivid::match(DeviceEnumerator *enumerator)\n+ {\n+-\treturn false;\n++\tDeviceMatch dm(\"vivid\");\n++\tdm.add(\"vivid-000-vid-cap\");\n++\n++\tMediaDevice *media = acquireMediaDevice(enumerator, dm);\n++\tif (!media)\n++\t\treturn false;\n++\n++\tLOG(VIVID, Debug) << \"Obtained Vivid Device\";\n++\n++\treturn false; // Prevent infinite loops for now\n+ }\n+ \n+ REGISTER_PIPELINE_HANDLER(PipelineHandlerVivid);\n+-- \n+2.25.1\n+\ndiff --git a/Documentation/vivid-pipeline-handler/0003-libcamera-pipeline-vivid-Create-a-Camera.patch b/Documentation/vivid-pipeline-handler/0003-libcamera-pipeline-vivid-Create-a-Camera.patch\nnew file mode 100644\nindex 000000000000..1d8552752047\n--- /dev/null\n+++ b/Documentation/vivid-pipeline-handler/0003-libcamera-pipeline-vivid-Create-a-Camera.patch\n@@ -0,0 +1,110 @@\n+From f80f723a010501c6d159ae9601c2787d5d02906f Mon Sep 17 00:00:00 2001\n+From: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+Date: Fri, 10 Jul 2020 16:28:36 +0100\n+Subject: [PATCH 3/9] libcamera: pipeline: vivid: Create a Camera\n+\n+Create a VividCameraData inheriting from the CameraData to handle camera\n+specific data, and use it to create and register the camera with the\n+CameraManager.\n+\n+This can now be tested to see that the camera becomes available to\n+applications:\n+\n+\"\"\"\n+LIBCAMERA_LOG_LEVELS=Pipeline,VIVID:0 ./src/cam/cam -l\n+[231:44:49.325333712] [2880028]  INFO IPAManager ipa_manager.cpp:136 libcamera is not installed. Adding '/home/libcamera/build-vivid/src/ipa' to the IPA search path\n+[231:44:49.325428449] [2880028]  WARN IPAManager ipa_manager.cpp:147 No IPA found in '/usr/local/lib/x86_64-linux-gnu/libcamera'\n+[231:44:49.325446253] [2880028]  INFO Camera camera_manager.cpp:283 libcamera v0.0.11+713-d175334d-dirty\n+Available cameras:\n+1: vivid\n+\"\"\"\n+\n+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+---\n+ src/libcamera/pipeline/vivid/vivid.cpp | 54 +++++++++++++++++++++++++-\n+ 1 file changed, 52 insertions(+), 2 deletions(-)\n+\n+diff --git a/src/libcamera/pipeline/vivid/vivid.cpp b/src/libcamera/pipeline/vivid/vivid.cpp\n+index 9811f6ef5095..a8922ce70ed4 100644\n+--- a/src/libcamera/pipeline/vivid/vivid.cpp\n++++ b/src/libcamera/pipeline/vivid/vivid.cpp\n+@@ -5,14 +5,46 @@\n+  * vivid.cpp - Pipeline handler for the vivid capture device\n+  */\n+ \n++#include <libcamera/camera.h>\n++\n+ #include \"libcamera/internal/device_enumerator.h\"\n+ #include \"libcamera/internal/log.h\"\n++#include \"libcamera/internal/media_device.h\"\n+ #include \"libcamera/internal/pipeline_handler.h\"\n++#include \"libcamera/internal/v4l2_videodevice.h\"\n+ \n+ namespace libcamera {\n+ \n+ LOG_DEFINE_CATEGORY(VIVID)\n+ \n++class VividCameraData : public CameraData\n++{\n++public:\n++\tVividCameraData(PipelineHandler *pipe, MediaDevice *media)\n++\t\t: CameraData(pipe), media_(media), video_(nullptr)\n++\t{\n++\t}\n++\n++\t~VividCameraData()\n++\t{\n++\t\tdelete video_;\n++\t}\n++\n++\tint init();\n++\n++\tMediaDevice *media_;\n++\tV4L2VideoDevice *video_;\n++\tStream stream_;\n++};\n++\n++class VividCameraConfiguration : public CameraConfiguration\n++{\n++public:\n++\tVividCameraConfiguration();\n++\n++\tStatus validate() override;\n++};\n++\n+ class PipelineHandlerVivid : public PipelineHandler\n+ {\n+ public:\n+@@ -78,9 +110,27 @@ bool PipelineHandlerVivid::match(DeviceEnumerator *enumerator)\n+ \tif (!media)\n+ \t\treturn false;\n+ \n+-\tLOG(VIVID, Debug) << \"Obtained Vivid Device\";\n++\tstd::unique_ptr<VividCameraData> data = std::make_unique<VividCameraData>(this, media);\n++\n++\t/* Locate and open the capture video node. */\n++\tif (data->init())\n++\t\treturn false;\n++\n++\t/* Create and register the camera. */\n++\tstd::set<Stream *> streams{ &data->stream_ };\n++\tstd::shared_ptr<Camera> camera = Camera::create(this, data->video_->deviceName(), streams);\n++\tregisterCamera(std::move(camera), std::move(data));\n++\n++\treturn true;\n++}\n++\n++int VividCameraData::init()\n++{\n++\tvideo_ = new V4L2VideoDevice(media_->getEntityByName(\"vivid-000-vid-cap\"));\n++\tif (video_->open())\n++\t\treturn -ENODEV;\n+ \n+-\treturn false; // Prevent infinite loops for now\n++\treturn 0;\n+ }\n+ \n+ REGISTER_PIPELINE_HANDLER(PipelineHandlerVivid);\n+-- \n+2.25.1\n+\ndiff --git a/Documentation/vivid-pipeline-handler/0004-libcamera-pipeline-vivid-Generate-and-validate-Strea.patch b/Documentation/vivid-pipeline-handler/0004-libcamera-pipeline-vivid-Generate-and-validate-Strea.patch\nnew file mode 100644\nindex 000000000000..43a203cffa7b\n--- /dev/null\n+++ b/Documentation/vivid-pipeline-handler/0004-libcamera-pipeline-vivid-Generate-and-validate-Strea.patch\n@@ -0,0 +1,160 @@\n+From 928ab8ae5728677c21bd31309b782d0856441aa2 Mon Sep 17 00:00:00 2001\n+From: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+Date: Fri, 10 Jul 2020 16:44:01 +0100\n+Subject: [PATCH 4/9] libcamera: pipeline: vivid: Generate and validate\n+ StreamConfigurations\n+\n+Implement the support for Generating and Validating the streams the\n+Camera can provide.\n+\n+Vivid is a simple case with only a single stream.\n+\n+Test the configurations can be generated and reported with cam -I:\n+\n+\"\"\"\n+LIBCAMERA_LOG_LEVELS=Pipeline,VIVID:0 ./src/cam/cam -c 1 -I\n+[232:02:09.633067174] [2882911]  INFO IPAManager ipa_manager.cpp:136 libcamera is not installed. Adding '/home//libcamera/build-vivid/src/ipa' to the IPA search path\n+[232:02:09.633332451] [2882911]  WARN IPAManager ipa_manager.cpp:147 No IPA found in '/usr/local/lib/x86_64-linux-gnu/libcamera'\n+[232:02:09.633373414] [2882911]  INFO Camera camera_manager.cpp:283 libcamera v0.0.11+714-d1ebd889-dirty\n+Using camera vivid\n+0: 1280x720-BGR888\n+ * Pixelformat: NV21 (320x180)-(3840x2160)/(+0,+0)\n+  - 320x180\n+  - 640x360\n+  - 640x480\n+  - 1280x720\n+  - 1920x1080\n+  - 3840x2160\n+ * Pixelformat: NV12 (320x180)-(3840x2160)/(+0,+0)\n+  - 320x180\n+  - 640x360\n+  - 640x480\n+  - 1280x720\n+  - 1920x1080\n+  - 3840x2160\n+ * Pixelformat: BGRA8888 (320x180)-(3840x2160)/(+0,+0)\n+  - 320x180\n+  - 640x360\n+  - 640x480\n+  - 1280x720\n+  - 1920x1080\n+  - 3840x2160\n+ * Pixelformat: RGBA8888 (320x180)-(3840x2160)/(+0,+0)\n+  - 320x180\n+  - 640x360\n+  - 640x480\n+  - 1280x720\n+  - 1920x1080\n+  - 3840x2160\n+\n+\"\"\"\n+\n+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+---\n+ src/libcamera/pipeline/vivid/vivid.cpp | 74 +++++++++++++++++++++++++-\n+ 1 file changed, 73 insertions(+), 1 deletion(-)\n+\n+diff --git a/src/libcamera/pipeline/vivid/vivid.cpp b/src/libcamera/pipeline/vivid/vivid.cpp\n+index a8922ce70ed4..9e95bae8bc30 100644\n+--- a/src/libcamera/pipeline/vivid/vivid.cpp\n++++ b/src/libcamera/pipeline/vivid/vivid.cpp\n+@@ -6,6 +6,7 @@\n+  */\n+ \n+ #include <libcamera/camera.h>\n++#include <libcamera/formats.h>\n+ \n+ #include \"libcamera/internal/device_enumerator.h\"\n+ #include \"libcamera/internal/log.h\"\n+@@ -63,8 +64,50 @@ public:\n+ \tint queueRequestDevice(Camera *camera, Request *request) override;\n+ \n+ \tbool match(DeviceEnumerator *enumerator) override;\n++\n++private:\n++\tint processControls(VividCameraData *data, Request *request);\n++\n++\tVividCameraData *cameraData(const Camera *camera)\n++\t{\n++\t\treturn static_cast<VividCameraData *>(\n++\t\t\tPipelineHandler::cameraData(camera));\n++\t}\n+ };\n+ \n++VividCameraConfiguration::VividCameraConfiguration()\n++\t: CameraConfiguration()\n++{\n++}\n++\n++CameraConfiguration::Status VividCameraConfiguration::validate()\n++{\n++\tStatus status = Valid;\n++\n++\tif (config_.empty())\n++\t\treturn Invalid;\n++\n++\t/* Cap the number of entries to the available streams. */\n++\tif (config_.size() > 1) {\n++\t\tconfig_.resize(1);\n++\t\tstatus = Adjusted;\n++\t}\n++\n++\tStreamConfiguration &cfg = config_[0];\n++\n++\t/* Adjust the pixel format. */\n++\tconst std::vector<libcamera::PixelFormat> formats = cfg.formats().pixelformats();\n++\tif (std::find(formats.begin(), formats.end(), cfg.pixelFormat) == formats.end()) {\n++\t\tcfg.pixelFormat = cfg.formats().pixelformats()[0];\n++\t\tLOG(VIVID, Debug) << \"Adjusting format to \" << cfg.pixelFormat.toString();\n++\t\tstatus = Adjusted;\n++\t}\n++\n++\tcfg.bufferCount = 4;\n++\n++\treturn status;\n++}\n++\n+ PipelineHandlerVivid::PipelineHandlerVivid(CameraManager *manager)\n+ \t: PipelineHandler(manager)\n+ {\n+@@ -73,7 +116,36 @@ PipelineHandlerVivid::PipelineHandlerVivid(CameraManager *manager)\n+ CameraConfiguration *PipelineHandlerVivid::generateConfiguration(Camera *camera,\n+ \t\t\t\t\t\t\t\t const StreamRoles &roles)\n+ {\n+-\treturn nullptr;\n++\tCameraConfiguration *config = new VividCameraConfiguration();\n++\tVividCameraData *data = cameraData(camera);\n++\n++\tif (roles.empty())\n++\t\treturn config;\n++\n++\tstd::map<V4L2PixelFormat, std::vector<SizeRange>> v4l2Formats =\n++\t\tdata->video_->formats();\n++\tstd::map<PixelFormat, std::vector<SizeRange>> deviceFormats;\n++\tstd::transform(v4l2Formats.begin(), v4l2Formats.end(),\n++\t\t       std::inserter(deviceFormats, deviceFormats.begin()),\n++\t\t       [&](const decltype(v4l2Formats)::value_type &format) {\n++\t\t\t       return decltype(deviceFormats)::value_type{\n++\t\t\t\t       format.first.toPixelFormat(),\n++\t\t\t\t       format.second\n++\t\t\t       };\n++\t\t       });\n++\n++\tStreamFormats formats(deviceFormats);\n++\tStreamConfiguration cfg(formats);\n++\n++\tcfg.pixelFormat = formats::BGR888;\n++\tcfg.size = { 1280, 720 };\n++\tcfg.bufferCount = 4;\n++\n++\tconfig->addConfiguration(cfg);\n++\n++\tconfig->validate();\n++\n++\treturn config;\n+ }\n+ \n+ int PipelineHandlerVivid::configure(Camera *camera, CameraConfiguration *config)\n+-- \n+2.25.1\n+\ndiff --git a/Documentation/vivid-pipeline-handler/0005-libcamera-pipeline-vivid-Configure-the-device.patch b/Documentation/vivid-pipeline-handler/0005-libcamera-pipeline-vivid-Configure-the-device.patch\nnew file mode 100644\nindex 000000000000..c750ce4e80d4\n--- /dev/null\n+++ b/Documentation/vivid-pipeline-handler/0005-libcamera-pipeline-vivid-Configure-the-device.patch\n@@ -0,0 +1,71 @@\n+From 08df6b40552e67c3607aa1d6802f47beec76e151 Mon Sep 17 00:00:00 2001\n+From: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+Date: Mon, 13 Jul 2020 09:51:51 +0100\n+Subject: [PATCH 5/9] libcamera: pipeline: vivid: Configure the device\n+\n+When the configurations have been generated and validated, they can be\n+applied to a device.\n+\n+Vivid supports only a single stream, so it directly obtains the first\n+StreamConfiguration from the CameraConfiguration.\n+\n+The VIVID catpure device is a V4L2Video device, so we generate a\n+V4L2DeviceFormat to apply directly to the capture device node.\n+\n+Note that we explicitly convert the libcamera Format stored in\n+cfg.pixelFormat to a V4L2PixelFormat using the helpers provided by the\n+V4L2VideoDevice to ensure that any multiplanar formats are handled\n+correctly and accordingly.\n+\n+Following the call to set the format using the Kernel API, if the format\n+has been adjusted in any way by the kernel driver, then we have failed\n+to correctly handle the validation stages, and thus the configure\n+operation is idendified has having failed.\n+\n+Finally stream specific data can be directly stored and set as\n+reflecting the state of the stream.\n+\n+[NOTE: the cfg.setStream() call here associates the stream to the\n+StreamConfiguration however that should quite likely be done as part of\n+the validation process. TBD]\n+\n+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+---\n+ src/libcamera/pipeline/vivid/vivid.cpp | 21 ++++++++++++++++++++-\n+ 1 file changed, 20 insertions(+), 1 deletion(-)\n+\n+diff --git a/src/libcamera/pipeline/vivid/vivid.cpp b/src/libcamera/pipeline/vivid/vivid.cpp\n+index 9e95bae8bc30..dbc19424e75a 100644\n+--- a/src/libcamera/pipeline/vivid/vivid.cpp\n++++ b/src/libcamera/pipeline/vivid/vivid.cpp\n+@@ -150,7 +150,26 @@ CameraConfiguration *PipelineHandlerVivid::generateConfiguration(Camera *camera,\n+ \n+ int PipelineHandlerVivid::configure(Camera *camera, CameraConfiguration *config)\n+ {\n+-\treturn -1;\n++\tVividCameraData *data = cameraData(camera);\n++\tStreamConfiguration &cfg = config->at(0);\n++\tint ret;\n++\n++\tV4L2DeviceFormat format = {};\n++\tformat.fourcc = data->video_->toV4L2PixelFormat(cfg.pixelFormat);\n++\tformat.size = cfg.size;\n++\n++\tret = data->video_->setFormat(&format);\n++\tif (ret)\n++\t\treturn ret;\n++\n++\tif (format.size != cfg.size ||\n++\t    format.fourcc != data->video_->toV4L2PixelFormat(cfg.pixelFormat))\n++\t\treturn -EINVAL;\n++\n++\tcfg.setStream(&data->stream_);\n++\tcfg.stride = format.planes[0].bpl;\n++\n++\treturn 0;\n+ }\n+ \n+ int PipelineHandlerVivid::exportFrameBuffers(Camera *camera, Stream *stream,\n+-- \n+2.25.1\n+\ndiff --git a/Documentation/vivid-pipeline-handler/0006-libcamera-pipeline-vivid-Buffer-handling-and-stream-.patch b/Documentation/vivid-pipeline-handler/0006-libcamera-pipeline-vivid-Buffer-handling-and-stream-.patch\nnew file mode 100644\nindex 000000000000..b04ef3e10473\n--- /dev/null\n+++ b/Documentation/vivid-pipeline-handler/0006-libcamera-pipeline-vivid-Buffer-handling-and-stream-.patch\n@@ -0,0 +1,102 @@\n+From 8b6d4200c60513bdb9c435c94d512efb4f59441c Mon Sep 17 00:00:00 2001\n+From: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+Date: Mon, 13 Jul 2020 10:46:26 +0100\n+Subject: [PATCH 6/9] libcamera: pipeline: vivid: Buffer handling and stream\n+ control\n+\n+We can now add buffer management, and connect up our bufferReady signal\n+to a callback.\n+\n+Note that we provide the ability to export buffers from our capture\n+device (data->video_) using the exportBuffers() functionality from the\n+V4L2VideoDevice which allows a FrameBufferAllocater to obtain buffers\n+from this device.\n+\n+When buffers are obtained through the exportFrameBuffers API, they are\n+orphaned and left unassociated with the device, and must be reimported\n+at start() time anyway. This allows the same interface to be used\n+whether internal buffers, or external buffers are used for the stream.\n+\n+When a buffer completes, we call the buffer completion handler on the\n+pipeline handler, and because we have only a single stream, we can also\n+immediately complete the request.\n+\n+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+---\n+ src/libcamera/pipeline/vivid/vivid.cpp | 35 ++++++++++++++++++++++++--\n+ 1 file changed, 33 insertions(+), 2 deletions(-)\n+\n+diff --git a/src/libcamera/pipeline/vivid/vivid.cpp b/src/libcamera/pipeline/vivid/vivid.cpp\n+index dbc19424e75a..1a945a744055 100644\n+--- a/src/libcamera/pipeline/vivid/vivid.cpp\n++++ b/src/libcamera/pipeline/vivid/vivid.cpp\n+@@ -32,6 +32,7 @@ public:\n+ \t}\n+ \n+ \tint init();\n++\tvoid bufferReady(FrameBuffer *buffer);\n+ \n+ \tMediaDevice *media_;\n+ \tV4L2VideoDevice *video_;\n+@@ -175,16 +176,36 @@ int PipelineHandlerVivid::configure(Camera *camera, CameraConfiguration *config)\n+ int PipelineHandlerVivid::exportFrameBuffers(Camera *camera, Stream *stream,\n+ \t\t\t\t\t     std::vector<std::unique_ptr<FrameBuffer>> *buffers)\n+ {\n+-\treturn -1;\n++\tVividCameraData *data = cameraData(camera);\n++\tunsigned int count = stream->configuration().bufferCount;\n++\n++\treturn data->video_->exportBuffers(count, buffers);\n+ }\n+ \n+ int PipelineHandlerVivid::start(Camera *camera)\n+ {\n+-\treturn -1;\n++\tVividCameraData *data = cameraData(camera);\n++\tunsigned int count = data->stream_.configuration().bufferCount;\n++\n++\tint ret = data->video_->importBuffers(count);\n++\tif (ret < 0)\n++\t\treturn ret;\n++\n++\tret = data->video_->streamOn();\n++\tif (ret < 0) {\n++\t\tdata->ipa_->stop();\n++\t\tdata->video_->releaseBuffers();\n++\t\treturn ret;\n++\t}\n++\n++\treturn 0;\n+ }\n+ \n+ void PipelineHandlerVivid::stop(Camera *camera)\n+ {\n++\tVividCameraData *data = cameraData(camera);\n++\tdata->video_->streamOff();\n++\tdata->video_->releaseBuffers();\n+ }\n+ \n+ int PipelineHandlerVivid::queueRequestDevice(Camera *camera, Request *request)\n+@@ -221,9 +242,19 @@ int VividCameraData::init()\n+ \tif (video_->open())\n+ \t\treturn -ENODEV;\n+ \n++\tvideo_->bufferReady.connect(this, &VividCameraData::bufferReady);\n++\n+ \treturn 0;\n+ }\n+ \n++void VividCameraData::bufferReady(FrameBuffer *buffer)\n++{\n++\tRequest *request = buffer->request();\n++\n++\tpipe_->completeBuffer(camera_, request, buffer);\n++\tpipe_->completeRequest(camera_, request);\n++}\n++\n+ REGISTER_PIPELINE_HANDLER(PipelineHandlerVivid);\n+ \n+ } /* namespace libcamera */\n+-- \n+2.25.1\n+\ndiff --git a/Documentation/vivid-pipeline-handler/0007-libcamera-pipeline-vivid-Queue-requests.patch b/Documentation/vivid-pipeline-handler/0007-libcamera-pipeline-vivid-Queue-requests.patch\nnew file mode 100644\nindex 000000000000..a896e6d12e37\n--- /dev/null\n+++ b/Documentation/vivid-pipeline-handler/0007-libcamera-pipeline-vivid-Queue-requests.patch\n@@ -0,0 +1,45 @@\n+From 22e1f2c2736cd860a63086695f1dded0b2b2aa0e Mon Sep 17 00:00:00 2001\n+From: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+Date: Mon, 13 Jul 2020 11:35:11 +0100\n+Subject: [PATCH 7/9] libcamera: pipeline: vivid: Queue requests\n+\n+When a request is given to a pipeline handler, it must parse the request\n+and identify what actions the pipeline handler should take to enact on hardware.\n+\n+In the case of the VIVID pipeline handler, we identify the buffer from the only\n+supported stream, and queue it to the video capture device.\n+\n+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+---\n+ src/libcamera/pipeline/vivid/vivid.cpp | 15 ++++++++++++++-\n+ 1 file changed, 14 insertions(+), 1 deletion(-)\n+\n+diff --git a/src/libcamera/pipeline/vivid/vivid.cpp b/src/libcamera/pipeline/vivid/vivid.cpp\n+index 1a945a744055..4362e73f49a5 100644\n+--- a/src/libcamera/pipeline/vivid/vivid.cpp\n++++ b/src/libcamera/pipeline/vivid/vivid.cpp\n+@@ -210,7 +210,20 @@ void PipelineHandlerVivid::stop(Camera *camera)\n+ \n+ int PipelineHandlerVivid::queueRequestDevice(Camera *camera, Request *request)\n+ {\n+-\treturn -1;\n++\tVividCameraData *data = cameraData(camera);\n++\tFrameBuffer *buffer = request->findBuffer(&data->stream_);\n++\tif (!buffer) {\n++\t\tLOG(VIVID, Error)\n++\t\t\t<< \"Attempt to queue request with invalid stream\";\n++\n++\t\treturn -ENOENT;\n++\t}\n++\n++\tint ret = data->video_->queueBuffer(buffer);\n++\tif (ret < 0)\n++\t\treturn ret;\n++\n++\treturn 0;\n+ }\n+ \n+ bool PipelineHandlerVivid::match(DeviceEnumerator *enumerator)\n+-- \n+2.25.1\n+\ndiff --git a/Documentation/vivid-pipeline-handler/0008-libcamera-pipeline-vivid-Initialise-key-controls.patch b/Documentation/vivid-pipeline-handler/0008-libcamera-pipeline-vivid-Initialise-key-controls.patch\nnew file mode 100644\nindex 000000000000..8e0fca45fa04\n--- /dev/null\n+++ b/Documentation/vivid-pipeline-handler/0008-libcamera-pipeline-vivid-Initialise-key-controls.patch\n@@ -0,0 +1,70 @@\n+From 703b1d24259934781c9f9ff80774e5845876c47f Mon Sep 17 00:00:00 2001\n+From: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+Date: Mon, 13 Jul 2020 12:48:37 +0100\n+Subject: [PATCH 8/9] libcamera: pipeline: vivid: Initialise key controls\n+\n+The VIVID pipeline handler retains state globally of it's controls.\n+Ensure that when we configure this specific pipeline we set initial\n+parameters on the device that suit our (specific) needs.\n+\n+This introduces how controls can be set directly on a device, however\n+under normal circumstances controls should usually be set from libcamera\n+controls as part of a request. These are VIVID specific only.\n+\n+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+---\n+ src/libcamera/pipeline/vivid/vivid.cpp | 31 ++++++++++++++++++++++++++\n+ 1 file changed, 31 insertions(+)\n+\n+diff --git a/src/libcamera/pipeline/vivid/vivid.cpp b/src/libcamera/pipeline/vivid/vivid.cpp\n+index 4362e73f49a5..1744d78f2f28 100644\n+--- a/src/libcamera/pipeline/vivid/vivid.cpp\n++++ b/src/libcamera/pipeline/vivid/vivid.cpp\n+@@ -14,6 +14,18 @@\n+ #include \"libcamera/internal/pipeline_handler.h\"\n+ #include \"libcamera/internal/v4l2_videodevice.h\"\n+ \n++#define VIVID_CID_VIVID_BASE            (0x00f00000 | 0xf000)\n++#define VIVID_CID_VIVID_CLASS           (0x00f00000 | 1)\n++#define VIVID_CID_TEST_PATTERN          (VIVID_CID_VIVID_BASE + 0)\n++#define VIVID_CID_OSD_TEXT_MODE         (VIVID_CID_VIVID_BASE + 1)\n++#define VIVID_CID_HOR_MOVEMENT          (VIVID_CID_VIVID_BASE + 2)\n++#define VIVID_CID_VERT_MOVEMENT         (VIVID_CID_VIVID_BASE + 3)\n++#define VIVID_CID_SHOW_BORDER           (VIVID_CID_VIVID_BASE + 4)\n++#define VIVID_CID_SHOW_SQUARE           (VIVID_CID_VIVID_BASE + 5)\n++#define VIVID_CID_INSERT_SAV            (VIVID_CID_VIVID_BASE + 6)\n++#define VIVID_CID_INSERT_EAV            (VIVID_CID_VIVID_BASE + 7)\n++#define VIVID_CID_VBI_CAP_INTERLACED    (VIVID_CID_VIVID_BASE + 8)\n++\n+ namespace libcamera {\n+ \n+ LOG_DEFINE_CATEGORY(VIVID)\n+@@ -167,6 +179,25 @@ int PipelineHandlerVivid::configure(Camera *camera, CameraConfiguration *config)\n+ \t    format.fourcc != data->video_->toV4L2PixelFormat(cfg.pixelFormat))\n+ \t\treturn -EINVAL;\n+ \n++\t/* Set initial controls specific to VIVID */\n++\tControlList controls(data->video_->controls());\n++\tcontrols.set(VIVID_CID_TEST_PATTERN, 0); /* Vertical Colour Bars */\n++\tcontrols.set(VIVID_CID_OSD_TEXT_MODE, 0); /* Display all OSD */\n++\n++\t/* Ensure clear colours configured. */\n++\tcontrols.set(V4L2_CID_BRIGHTNESS, 128);\n++\tcontrols.set(V4L2_CID_CONTRAST, 128);\n++\tcontrols.set(V4L2_CID_SATURATION, 128);\n++\n++\t/* Enable movement to visualise buffer updates. */\n++\tcontrols.set(VIVID_CID_HOR_MOVEMENT, 5);\n++\n++\tret = data->video_->setControls(&controls);\n++\tif (ret) {\n++\t\tLOG(VIVID, Error) << \"Failed to set controls: \" << ret;\n++\t\treturn ret < 0 ? ret : -EINVAL;\n++\t}\n++\n+ \tcfg.setStream(&data->stream_);\n+ \tcfg.stride = format.planes[0].bpl;\n+ \n+-- \n+2.25.1\n+\ndiff --git a/Documentation/vivid-pipeline-handler/0009-libcamera-pipeline-vivid-Handle-controls.patch b/Documentation/vivid-pipeline-handler/0009-libcamera-pipeline-vivid-Handle-controls.patch\nnew file mode 100644\nindex 000000000000..ea88ef44c102\n--- /dev/null\n+++ b/Documentation/vivid-pipeline-handler/0009-libcamera-pipeline-vivid-Handle-controls.patch\n@@ -0,0 +1,133 @@\n+From 03bbac3265554b73e6ddcdebaf95090062e3669f Mon Sep 17 00:00:00 2001\n+From: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+Date: Mon, 13 Jul 2020 12:56:11 +0100\n+Subject: [PATCH 9/9] libcamera: pipeline: vivid: Handle controls\n+\n+When constructing the camera, we parse the available controls on the\n+video capture device, and map supported controls to libcamera controls,\n+and initialise the defaults.\n+\n+The controls are handled during queueRequestDevice for each request and\n+applied to the device through the capture node.\n+\n+Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n+---\n+ src/libcamera/pipeline/vivid/vivid.cpp | 80 +++++++++++++++++++++++++-\n+ 1 file changed, 79 insertions(+), 1 deletion(-)\n+\n+diff --git a/src/libcamera/pipeline/vivid/vivid.cpp b/src/libcamera/pipeline/vivid/vivid.cpp\n+index 1744d78f2f28..b8b8e3ae0287 100644\n+--- a/src/libcamera/pipeline/vivid/vivid.cpp\n++++ b/src/libcamera/pipeline/vivid/vivid.cpp\n+@@ -5,7 +5,11 @@\n+  * vivid.cpp - Pipeline handler for the vivid capture device\n+  */\n+ \n++#include <math.h>\n++\n+ #include <libcamera/camera.h>\n++#include <libcamera/control_ids.h>\n++#include <libcamera/controls.h>\n+ #include <libcamera/formats.h>\n+ \n+ #include \"libcamera/internal/device_enumerator.h\"\n+@@ -239,6 +243,46 @@ void PipelineHandlerVivid::stop(Camera *camera)\n+ \tdata->video_->releaseBuffers();\n+ }\n+ \n++int PipelineHandlerVivid::processControls(VividCameraData *data, Request *request)\n++{\n++\tControlList controls(data->video_->controls());\n++\n++\tfor (auto it : request->controls()) {\n++\t\tunsigned int id = it.first;\n++\t\tunsigned int offset;\n++\t\tuint32_t cid;\n++\n++\t\tif (id == controls::Brightness) {\n++\t\t\tcid = V4L2_CID_BRIGHTNESS;\n++\t\t\toffset = 128;\n++\t\t} else if (id == controls::Contrast) {\n++\t\t\tcid = V4L2_CID_CONTRAST;\n++\t\t\toffset = 0;\n++\t\t} else if (id == controls::Saturation) {\n++\t\t\tcid = V4L2_CID_SATURATION;\n++\t\t\toffset = 0;\n++\t\t} else {\n++\t\t\tcontinue;\n++\t\t}\n++\n++\t\tint32_t value = lroundf(it.second.get<float>() * 128 + offset);\n++\t\tcontrols.set(cid, utils::clamp(value, 0, 255));\n++\t}\n++\n++\tfor (const auto &ctrl : controls)\n++\t\tLOG(VIVID, Debug)\n++\t\t\t<< \"Setting control \" << utils::hex(ctrl.first)\n++\t\t\t<< \" to \" << ctrl.second.toString();\n++\n++\tint ret = data->video_->setControls(&controls);\n++\tif (ret) {\n++\t\tLOG(VIVID, Error) << \"Failed to set controls: \" << ret;\n++\t\treturn ret < 0 ? ret : -EINVAL;\n++\t}\n++\n++\treturn ret;\n++}\n++\n+ int PipelineHandlerVivid::queueRequestDevice(Camera *camera, Request *request)\n+ {\n+ \tVividCameraData *data = cameraData(camera);\n+@@ -250,7 +294,11 @@ int PipelineHandlerVivid::queueRequestDevice(Camera *camera, Request *request)\n+ \t\treturn -ENOENT;\n+ \t}\n+ \n+-\tint ret = data->video_->queueBuffer(buffer);\n++\tint ret = processControls(data, request);\n++\tif (ret < 0)\n++\t\treturn ret;\n++\n++\tret = data->video_->queueBuffer(buffer);\n+ \tif (ret < 0)\n+ \t\treturn ret;\n+ \n+@@ -288,6 +336,36 @@ int VividCameraData::init()\n+ \n+ \tvideo_->bufferReady.connect(this, &VividCameraData::bufferReady);\n+ \n++\t/* Initialise the supported controls. */\n++\tconst ControlInfoMap &controls = video_->controls();\n++\tControlInfoMap::Map ctrls;\n++\n++\tfor (const auto &ctrl : controls) {\n++\t\tconst ControlId *id;\n++\t\tControlInfo info;\n++\n++\t\tswitch (ctrl.first->id()) {\n++\t\tcase V4L2_CID_BRIGHTNESS:\n++\t\t\tid = &controls::Brightness;\n++\t\t\tinfo = ControlInfo{ { -1.0f }, { 1.0f }, { 0.0f } };\n++\t\t\tbreak;\n++\t\tcase V4L2_CID_CONTRAST:\n++\t\t\tid = &controls::Contrast;\n++\t\t\tinfo = ControlInfo{ { 0.0f }, { 2.0f }, { 1.0f } };\n++\t\t\tbreak;\n++\t\tcase V4L2_CID_SATURATION:\n++\t\t\tid = &controls::Saturation;\n++\t\t\tinfo = ControlInfo{ { 0.0f }, { 2.0f }, { 1.0f } };\n++\t\t\tbreak;\n++\t\tdefault:\n++\t\t\tcontinue;\n++\t\t}\n++\n++\t\tctrls.emplace(id, info);\n++\t}\n++\n++\tcontrolInfo_ = std::move(ctrls);\n++\n+ \treturn 0;\n+ }\n+ \n+-- \n+2.25.1\n+\n",
    "prefixes": [
        "libcamera-devel"
    ]
}