Show a patch.

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

{
    "id": 9386,
    "url": "https://patchwork.libcamera.org/api/patches/9386/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/9386/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/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": "<20200826110926.67192-3-paul.elder@ideasonboard.com>",
    "date": "2020-08-26T11:09:11",
    "name": "[libcamera-devel,RFC,02/17] libcamera: pipeline: raspberrypi: Use generated IPARPiInterface",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "30baad6711249dea4a886023b90af0804f749692",
    "submitter": {
        "id": 17,
        "url": "https://patchwork.libcamera.org/api/people/17/?format=api",
        "name": "Paul Elder",
        "email": "paul.elder@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/9386/mbox/",
    "series": [
        {
            "id": 1243,
            "url": "https://patchwork.libcamera.org/api/series/1243/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=1243",
            "date": "2020-08-26T11:09:09",
            "name": "[libcamera-devel,RFC,01/17] IPA: IPC: raspberrypi: Add data definition and generated header",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/1243/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/9386/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/9386/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 ADC45BD87E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 26 Aug 2020 11:09:54 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7A3A6628FB;\n\tWed, 26 Aug 2020 13:09:54 +0200 (CEST)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 595FB628F3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 26 Aug 2020 13:09:53 +0200 (CEST)",
            "from pyrite.rasen.tech (unknown\n\t[IPv6:2400:4051:61:600:2c71:1b79:d06d:5032])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 989DAB1A;\n\tWed, 26 Aug 2020 13:09:51 +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=\"ivwyO3IG\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1598440193;\n\tbh=/0ZrAwhrufuHQsETJWT0Htdeae5oD1X0A00R0YVDKoE=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=ivwyO3IG2qzUSLINhYC8pBXFZHI45XeMeIKYULMeEHwSioe2nExbeCfPMZf1F4bav\n\t6HRd/sLf5eL9aNQPyUlDHTOm3wpeOTbIBBc4CE29Bb1JwR10/JI3oWKsZO9LmP2Zny\n\trSpf2LDhp0Sfa1kykrdNNxTTUzvw7XaJa31DVDdE=",
        "From": "Paul Elder <paul.elder@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Wed, 26 Aug 2020 20:09:11 +0900",
        "Message-Id": "<20200826110926.67192-3-paul.elder@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.27.0",
        "In-Reply-To": "<20200826110926.67192-1-paul.elder@ideasonboard.com>",
        "References": "<20200826110926.67192-1-paul.elder@ideasonboard.com>",
        "MIME-Version": "1.0",
        "Subject": "[libcamera-devel] [RFC PATCH 02/17] libcamera: pipeline:\n\traspberrypi: Use generated IPARPiInterface",
        "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": "This patch shows how the pipeline would use the generated IPA interface.\n\nraspberrypi_wrapper.h is included, since that contains the\ndefinitions of all the custom data structures. ipa_proxy_raspberrypi.h\nis also included, so that the pipeline handler can create the\nIPAProxyRPi. Due to the custom IPA interface, the generic IPAProxy can\nno longer be used. This will be elaborated on in a few patches.\n\nOther than that, the rest of the patch should be straightforward. The\nonly changes are just fiddling the code to use the new structures. Most\nnoteworthy is that the pipeline handler does not know nor care if it is\ncommunicating with the IPA isolated or direct. This is one of our main\ngoals.\n\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\n---\n .../pipeline/raspberrypi/raspberrypi.cpp      | 125 ++++++++++--------\n 1 file changed, 69 insertions(+), 56 deletions(-)",
    "diff": "diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\nindex 42c9caa0..214dba8f 100644\n--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n@@ -16,6 +16,7 @@\n #include <libcamera/file_descriptor.h>\n #include <libcamera/formats.h>\n #include <libcamera/ipa/raspberrypi.h>\n+#include <libcamera/ipa/raspberrypi_wrapper.h>\n #include <libcamera/logging.h>\n #include <libcamera/property_ids.h>\n #include <libcamera/request.h>\n@@ -35,6 +36,8 @@\n #include \"dma_heaps.h\"\n #include \"staggered_ctrl.h\"\n \n+#include \"libcamera/internal/ipa_proxy_raspberrypi.h\"\n+\n namespace libcamera {\n \n LOG_DEFINE_CATEGORY(RPI)\n@@ -296,7 +299,7 @@ public:\n \tint loadIPA();\n \tint configureIPA();\n \n-\tvoid queueFrameAction(unsigned int frame, const IPAOperationData &action);\n+\tvoid queueFrameAction(unsigned int frame, const RPiActionParams &action);\n \n \t/* bufferComplete signal handlers. */\n \tvoid unicamBufferDequeue(FrameBuffer *buffer);\n@@ -307,6 +310,8 @@ public:\n \tvoid handleStreamBuffer(FrameBuffer *buffer, const RPiStream *stream);\n \tvoid handleState();\n \n+\tstd::unique_ptr<IPAProxyRPi> ipa_;\n+\n \tCameraSensor *sensor_;\n \t/* Array of Unicam and ISP device streams and associated buffers/streams. */\n \tRPiDevice<Unicam, 2> unicam_;\n@@ -1094,7 +1099,9 @@ void RPiCameraData::frameStarted(uint32_t sequence)\n \n int RPiCameraData::loadIPA()\n {\n-\tipa_ = IPAManager::createIPA(pipe_, 1, 1);\n+\tstd::unique_ptr<IPAProxy> ptr = IPAManager::createIPA(pipe_, 1, 1);\n+\tipa_ = std::unique_ptr<IPAProxyRPi>{static_cast<IPAProxyRPi*>(std::move(ptr).release())};\n+\n \tif (!ipa_)\n \t\treturn -ENOENT;\n \n@@ -1110,8 +1117,8 @@ int RPiCameraData::loadIPA()\n int RPiCameraData::configureIPA()\n {\n \tstd::map<unsigned int, IPAStream> streamConfig;\n-\tstd::map<unsigned int, const ControlInfoMap &> entityControls;\n-\tIPAOperationData ipaConfig = {};\n+\tstd::map<unsigned int, const ControlInfoMap> entityControls;\n+\tRPiConfigureParams ipaConfig;\n \n \t/* Get the device format to pass to the IPA. */\n \tV4L2DeviceFormat sensorFormat;\n@@ -1136,8 +1143,11 @@ int RPiCameraData::configureIPA()\n \t\t\treturn -ENOMEM;\n \n \t\t/* Allow the IPA to mmap the LS table via the file descriptor. */\n-\t\tipaConfig.operation = RPI_IPA_CONFIG_LS_TABLE;\n-\t\tipaConfig.data = { static_cast<unsigned int>(lsTable_.fd()) };\n+\t\tRPiConfigurePayload payload;\n+\t\tpayload.op_ = RPI_IPA_CONFIG_LS_TABLE;\n+\t\tpayload.lsTableHandle_ = lsTable_;\n+\t\tpayload.lsTableHandleStatic_ = lsTable_.fd();\n+\t\tipaConfig.payload_.push_back(payload);\n \t}\n \n \tCameraSensorInfo sensorInfo = {};\n@@ -1148,60 +1158,66 @@ int RPiCameraData::configureIPA()\n \t}\n \n \t/* Ready the IPA - it must know about the sensor resolution. */\n-\tIPAOperationData result;\n+\tRPiConfigureParams results;\n \n \tipa_->configure(sensorInfo, streamConfig, entityControls, ipaConfig,\n-\t\t\t&result);\n+\t\t\t&results);\n \n-\tif (result.operation & RPI_IPA_CONFIG_STAGGERED_WRITE) {\n-\t\t/*\n-\t\t * Setup our staggered control writer with the sensor default\n-\t\t * gain and exposure delays.\n-\t\t */\n-\t\tif (!staggeredCtrl_) {\n-\t\t\tstaggeredCtrl_.init(unicam_[Unicam::Image].dev(),\n-\t\t\t\t\t    { { V4L2_CID_ANALOGUE_GAIN, result.data[0] },\n-\t\t\t\t\t      { V4L2_CID_EXPOSURE, result.data[1] } });\n-\t\t\tsensorMetadata_ = result.data[2];\n-\t\t}\n+\tfor (RPiConfigurePayload &result : results.payload_) {\n+\t\tif (result.op_ == RPI_IPA_CONFIG_STAGGERED_WRITE) {\n \n-\t\t/* Configure the H/V flip controls based on the sensor rotation. */\n-\t\tControlList ctrls(unicam_[Unicam::Image].dev()->controls());\n-\t\tint32_t rotation = sensor_->properties().get(properties::Rotation);\n-\t\tctrls.set(V4L2_CID_HFLIP, static_cast<int32_t>(!!rotation));\n-\t\tctrls.set(V4L2_CID_VFLIP, static_cast<int32_t>(!!rotation));\n-\t\tunicam_[Unicam::Image].dev()->setControls(&ctrls);\n-\t}\n+\t\t\t/*\n+\t\t\t * Setup our staggered control writer with the sensor default\n+\t\t\t * gain and exposure delays.\n+\t\t\t */\n+\t\t\tif (!staggeredCtrl_) {\n+\t\t\t\tstaggeredCtrl_.init(unicam_[Unicam::Image].dev(),\n+\t\t\t\t\t\t{ { V4L2_CID_ANALOGUE_GAIN, result.staggeredWriteResult_.gainDelay_ },\n+\t\t\t\t\t\t{ V4L2_CID_EXPOSURE, result.staggeredWriteResult_.exposureDelay_ } });\n+\t\t\t\tsensorMetadata_ = result.staggeredWriteResult_.sensorMetadata_;\n+\t\t\t}\n \n-\tif (result.operation & RPI_IPA_CONFIG_SENSOR) {\n-\t\tconst ControlList &ctrls = result.controls[0];\n-\t\tif (!staggeredCtrl_.set(ctrls))\n-\t\t\tLOG(RPI, Error) << \"V4L2 staggered set failed\";\n+\t\t\t/* Configure the H/V flip controls based on the sensor rotation. */\n+\t\t\tControlList ctrls(unicam_[Unicam::Image].dev()->controls());\n+\t\t\tint32_t rotation = sensor_->properties().get(properties::Rotation);\n+\t\t\tctrls.set(V4L2_CID_HFLIP, static_cast<int32_t>(!!rotation));\n+\t\t\tctrls.set(V4L2_CID_VFLIP, static_cast<int32_t>(!!rotation));\n+\t\t\tunicam_[Unicam::Image].dev()->setControls(&ctrls);\n+\t\t}\n+\n+\t\tif (result.op_ == RPI_IPA_CONFIG_SENSOR) {\n+\t\t\tconst ControlList &ctrls = result.controls_;\n+\t\t\tif (!staggeredCtrl_.set(ctrls))\n+\t\t\t\tLOG(RPI, Error) << \"V4L2 staggered set failed\";\n+\t\t}\n \t}\n \n \treturn 0;\n }\n \n void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame,\n-\t\t\t\t     const IPAOperationData &action)\n+\t\t\t\t     const RPiActionParams &action)\n {\n \t/*\n \t * The following actions can be handled when the pipeline handler is in\n \t * a stopped state.\n \t */\n-\tswitch (action.operation) {\n+\tswitch (action.op_) {\n \tcase RPI_IPA_ACTION_V4L2_SET_STAGGERED: {\n-\t\tconst ControlList &controls = action.controls[0];\n+\t\tconst ControlList &controls = action.controls_;\n \t\tif (!staggeredCtrl_.set(controls))\n \t\t\tLOG(RPI, Error) << \"V4L2 staggered set failed\";\n \t\tgoto done;\n \t}\n \n \tcase RPI_IPA_ACTION_V4L2_SET_ISP: {\n-\t\tControlList controls = action.controls[0];\n+\t\tControlList controls = action.controls_;\n \t\tisp_[Isp::Input].dev()->setControls(&controls);\n \t\tgoto done;\n \t}\n+\n+\tdefault:\n+\t\tbreak;\n \t}\n \n \tif (state_ == State::Stopped)\n@@ -1211,20 +1227,20 @@ void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame,\n \t * The following actions must not be handled when the pipeline handler\n \t * is in a stopped state.\n \t */\n-\tswitch (action.operation) {\n+\tswitch (action.op_) {\n \tcase RPI_IPA_ACTION_STATS_METADATA_COMPLETE: {\n-\t\tunsigned int bufferId = action.data[0];\n+\t\tunsigned int bufferId = action.statsComplete_.bufferId_;\n \t\tFrameBuffer *buffer = isp_[Isp::Stats].getBuffers()->at(bufferId).get();\n \n \t\thandleStreamBuffer(buffer, &isp_[Isp::Stats]);\n \t\t/* Fill the Request metadata buffer with what the IPA has provided */\n-\t\trequestQueue_.front()->metadata() = std::move(action.controls[0]);\n+\t\trequestQueue_.front()->metadata() = std::move(action.statsComplete_.controls_);\n \t\tstate_ = State::IpaComplete;\n \t\tbreak;\n \t}\n \n \tcase RPI_IPA_ACTION_EMBEDDED_COMPLETE: {\n-\t\tunsigned int bufferId = action.data[0];\n+\t\tunsigned int bufferId = action.bufferId_;\n \t\tFrameBuffer *buffer = unicam_[Unicam::Embedded].getBuffers()->at(bufferId).get();\n \t\thandleStreamBuffer(buffer, &unicam_[Unicam::Embedded]);\n \t\tbreak;\n@@ -1232,20 +1248,17 @@ void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame,\n \n \tcase RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME:\n \tcase RPI_IPA_ACTION_RUN_ISP: {\n-\t\tunsigned int bufferId = action.data[0];\n+\t\tunsigned int bufferId = action.bufferId_;\n \t\tFrameBuffer *buffer = unicam_[Unicam::Image].getBuffers()->at(bufferId).get();\n \n-\t\tLOG(RPI, Debug) << \"Input re-queue to ISP, buffer id \" << buffer->cookie()\n-\t\t\t\t<< \", timestamp: \" << buffer->metadata().timestamp;\n-\n \t\tisp_[Isp::Input].dev()->queueBuffer(buffer);\n-\t\tdropFrame_ = (action.operation == RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME) ? true : false;\n+\t\tdropFrame_ = (action.op_ == RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME) ? true : false;\n \t\tispOutputCount_ = 0;\n \t\tbreak;\n \t}\n \n \tdefault:\n-\t\tLOG(RPI, Error) << \"Unknown action \" << action.operation;\n+\t\tLOG(RPI, Error) << \"Unknown action \" << action.op_;\n \t\tbreak;\n \t}\n \n@@ -1345,10 +1358,10 @@ void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer)\n \n \t/* If this is a stats output, hand it to the IPA now. */\n \tif (stream == &isp_[Isp::Stats]) {\n-\t\tIPAOperationData op;\n-\t\top.operation = RPI_IPA_EVENT_SIGNAL_STAT_READY;\n-\t\top.data = { RPiIpaMask::STATS | buffer->cookie() };\n-\t\tipa_->processEvent(op);\n+\t\tRPiEventParams ev;\n+\t\tev.ev_ = RPI_IPA_EVENT_SIGNAL_STAT_READY;\n+\t\tev.bufferId_ = { RPiIpaMask::STATS | buffer->cookie() };\n+\t\tipa_->processEvent(ev);\n \t}\n \n \thandleState();\n@@ -1491,7 +1504,7 @@ void RPiCameraData::checkRequestCompleted()\n void RPiCameraData::tryRunPipeline()\n {\n \tFrameBuffer *bayerBuffer, *embeddedBuffer;\n-\tIPAOperationData op;\n+\tRPiEventParams ev;\n \n \t/* If any of our request or buffer queues are empty, we cannot proceed. */\n \tif (state_ != State::Idle || requestQueue_.empty() ||\n@@ -1546,9 +1559,9 @@ void RPiCameraData::tryRunPipeline()\n \t * queue the ISP output buffer listed in the request to start the HW\n \t * pipeline.\n \t */\n-\top.operation = RPI_IPA_EVENT_QUEUE_REQUEST;\n-\top.controls = { request->controls() };\n-\tipa_->processEvent(op);\n+\tev.ev_ = RPI_IPA_EVENT_QUEUE_REQUEST;\n+\tev.controls_ = { request->controls() };\n+\tipa_->processEvent(ev);\n \n \t/* Queue up any ISP buffers passed into the request. */\n \tfor (auto &stream : isp_) {\n@@ -1567,10 +1580,10 @@ void RPiCameraData::tryRunPipeline()\n \t\t\t<< \" Bayer buffer id: \" << bayerBuffer->cookie()\n \t\t\t<< \" Embedded buffer id: \" << embeddedBuffer->cookie();\n \n-\top.operation = RPI_IPA_EVENT_SIGNAL_ISP_PREPARE;\n-\top.data = { RPiIpaMask::EMBEDDED_DATA | embeddedBuffer->cookie(),\n-\t\t    RPiIpaMask::BAYER_DATA | bayerBuffer->cookie() };\n-\tipa_->processEvent(op);\n+\tev.ev_ = RPI_IPA_EVENT_SIGNAL_ISP_PREPARE;\n+\tev.ispPrepare_.embeddedbufferId_ = RPiIpaMask::EMBEDDED_DATA | embeddedBuffer->cookie();\n+\tev.ispPrepare_.bayerbufferId_    = RPiIpaMask::BAYER_DATA | bayerBuffer->cookie();\n+\tipa_->processEvent(ev);\n }\n \n void RPiCameraData::tryFlushQueues()\n",
    "prefixes": [
        "libcamera-devel",
        "RFC",
        "02/17"
    ]
}