Patch Detail
Show a patch.
GET /api/1.1/patches/765/?format=api
{ "id": 765, "url": "https://patchwork.libcamera.org/api/1.1/patches/765/?format=api", "web_url": "https://patchwork.libcamera.org/patch/765/", "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": "<20190320163055.22056-20-jacopo@jmondi.org>", "date": "2019-03-20T16:30:43", "name": "[libcamera-devel,v4,19/31] libcamera: ipu3: Configure 'output' and 'viewfinder'", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "b676b82e696a3a360120110d1d31f86760c00c4e", "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/765/mbox/", "series": [ { "id": 214, "url": "https://patchwork.libcamera.org/api/1.1/series/214/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=214", "date": "2019-03-20T16:30:24", "name": "libcamera: ipu3: Add ImgU support + multiple streams", "version": 4, "mbox": "https://patchwork.libcamera.org/series/214/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/765/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/765/checks/", "tags": {}, "headers": { "Return-Path": "<jacopo@jmondi.org>", "Received": [ "from relay12.mail.gandi.net (relay12.mail.gandi.net\n\t[217.70.178.232])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C87D76110A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 20 Mar 2019 17:30:39 +0100 (CET)", "from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101])\n\t(Authenticated sender: jacopo@jmondi.org)\n\tby relay12.mail.gandi.net (Postfix) with ESMTPSA id 54FE6200012;\n\tWed, 20 Mar 2019 16:30:39 +0000 (UTC)" ], "From": "Jacopo Mondi <jacopo@jmondi.org>", "To": "libcamera-devel@lists.libcamera.org", "Date": "Wed, 20 Mar 2019 17:30:43 +0100", "Message-Id": "<20190320163055.22056-20-jacopo@jmondi.org>", "X-Mailer": "git-send-email 2.21.0", "In-Reply-To": "<20190320163055.22056-1-jacopo@jmondi.org>", "References": "<20190320163055.22056-1-jacopo@jmondi.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[libcamera-devel] [PATCH v4 19/31] libcamera: ipu3: Configure\n\t'output' and 'viewfinder'", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.23", "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": "Wed, 20 Mar 2019 16:30:40 -0000" }, "content": "Re-work stream configuration to handle the two video streams 'output'\nand 'viewfinder' separately.\n\nAs the IPU3 driver requires viewfinder and stat video nodes to be\noperated not to stall ImgU processing, keep track of which streams have\nbeen requested by the application, and configure 'output', 'viewfinder'\nand 'stat' regardless of the user requests.\n\nSigned-off-by: Jacopo Mondi <jacopo@jmondi.org>\n---\n src/libcamera/pipeline/ipu3/ipu3.cpp | 259 ++++++++++++++++++++++-----\n 1 file changed, 216 insertions(+), 43 deletions(-)", "diff": "diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\nindex 44e5eb48549e..4ed8c1fec1e3 100644\n--- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n@@ -140,6 +140,7 @@ private:\n \t\tImgUDevice *imgu;\n \n \t\tStream streams_[IPU3_STREAMS_COUNT];\n+\t\tunsigned int activeStreamsMask;\n \t};\n \n \tIPU3CameraData *cameraData(const Camera *camera)\n@@ -148,6 +149,44 @@ private:\n \t\t\tPipelineHandler::cameraData(camera));\n \t}\n \n+\tbool isOutput(IPU3CameraData *data, Stream *stream)\n+\t{\n+\t\treturn &data->streams_[IPU3_STREAM_OUTPUT] == stream;\n+\t}\n+\tbool isOutputActive(IPU3CameraData *data)\n+\t{\n+\t\treturn (data->activeStreamsMask & (1 << IPU3_STREAM_OUTPUT)) ?\n+\t\t\ttrue : false;\n+\t}\n+\tvoid setOutputActive(IPU3CameraData *data)\n+\t{\n+\t\tdata->activeStreamsMask |= (1 << IPU3_STREAM_OUTPUT);\n+\t}\n+\tbool isViewfinder(IPU3CameraData *data, Stream *stream)\n+\t{\n+\t\treturn &data->streams_[IPU3_STREAM_VF] == stream;\n+\t}\n+\tbool isViewfinderActive(IPU3CameraData *data)\n+\t{\n+\t\treturn (data->activeStreamsMask & (1 << IPU3_STREAM_VF)) ?\n+\t\t\ttrue : false;\n+\t}\n+\tvoid setViewfinderActive(IPU3CameraData *data)\n+\t{\n+\t\tdata->activeStreamsMask |= (1 << IPU3_STREAM_VF);\n+\t}\n+\tbool isStreamActive(IPU3CameraData *data, Stream *stream)\n+\t{\n+\t\tif (isOutput(data, stream) &&\n+\t\t isOutputActive(data))\n+\t\t\treturn true;\n+\t\tif (isViewfinder(data, stream) &&\n+\t\t isViewfinderActive(data))\n+\t\t\treturn true;\n+\n+\t\treturn false;\n+\t}\n+\n \tint mediaBusToCIO2Format(unsigned int code);\n \tV4L2Device *openDevice(MediaDevice *media, const std::string &name);\n \tV4L2Subdevice *openSubdevice(MediaDevice *media,\n@@ -158,9 +197,17 @@ private:\n \n \tint initImgU(ImgUDevice *imgu);\n \n-\tint setImguFormat(ImgUDevice *imguDevice,\n-\t\t\t const StreamConfiguration &config,\n-\t\t\t Rectangle *rect);\n+\tint setInputFormat(ImgUDevice *imguDevice,\n+\t\t\t const StreamConfiguration &config,\n+\t\t\t Rectangle *rect);\n+\tint setOutputFormat(ImgUDevice *imguDevice,\n+\t\t\t V4L2Device *output,\n+\t\t\t const StreamConfiguration &config);\n+\tint setViewfinderFormat(ImgUDevice *imguDevice,\n+\t\t\t\tV4L2Device *Viewfinder,\n+\t\t\t\tconst StreamConfiguration &config);\n+\tint setStatFormat(ImgUDevice *imguDevice,\n+\t\t\t const StreamConfiguration &config);\n \tint setCIO2Format(CIO2Device *cio2Device,\n \t\t\t const StreamConfiguration &config,\n \t\t\t V4L2SubdeviceFormat *format);\n@@ -251,32 +298,66 @@ PipelineHandlerIPU3::streamConfiguration(Camera *camera,\n }\n \n int PipelineHandlerIPU3::configureStreams(Camera *camera,\n-\t\t\t\t\t std::map<Stream *, StreamConfiguration> &config)\n+\t\t\t\t\t std::map<Stream *,\n+\t\t\t\t\t\t StreamConfiguration> &config)\n {\n \tIPU3CameraData *data = cameraData(camera);\n-\tconst StreamConfiguration &cfg = config[&data->streams_[0]];\n \tV4L2Device *viewfinder = data->imgu->viewfinder;\n \tV4L2Device *output = data->imgu->output;\n \tV4L2Device *input = data->imgu->input;\n \tV4L2Device *cio2 = data->cio2.output;\n+\tStreamConfiguration CIO2Config = {};\n \tint ret;\n \n-\tLOG(IPU3, Info)\n-\t\t<< \"Requested image format: \" << cfg.width << \"x\"\n-\t\t<< cfg.height << \" - \" << std::hex << std::setw(8)\n-\t\t<< cfg.pixelFormat << \" on camera:'\" << camera->name() << \"'\";\n+\t/* Remove previously configured stream masks to store the new ones. */\n+\tdata->activeStreamsMask = 0;\n \n-\t/*\n-\t * Verify that the requested size respects the IPU3 alignement\n-\t * requirements: the image width shall be a multiple of 8 pixels and\n-\t * its height a multiple of 4 pixels.\n-\t *\n-\t * \\todo: consider the BDS scaling factor requirements:\n-\t * \"the downscaling factor must be an integer value multiple of 1/32\"\n-\t */\n-\tif (cfg.width % 8 || cfg.height % 4) {\n-\t\tLOG(IPU3, Error) << \"Stream format not support: bad alignement\";\n-\t\treturn -EINVAL;\n+\tfor (auto const &streamConfig : config) {\n+\t\tStream *stream = streamConfig.first;\n+\t\tconst StreamConfiguration &cfg = streamConfig.second;\n+\n+\t\t/*\n+\t\t * Verify that the requested size respects the IPU3 alignement\n+\t\t * requirements: the image width shall be a multiple of 8 pixels\n+\t\t * and its height a multiple of 4 pixels.\n+\t\t *\n+\t\t * \\todo: consider the BDS scaling factor requirements: \"the\n+\t\t * downscaling factor must be an integer value multiple of 1/32\"\n+\t\t */\n+\t\tif (cfg.width % 8 || cfg.height % 4) {\n+\t\t\tLOG(IPU3, Error)\n+\t\t\t\t<< \"Stream format not support: bad alignement\";\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tLOG(IPU3, Info)\n+\t\t\t<< \"Requested image format: \" << cfg.width << \"x\"\n+\t\t\t<< cfg.height << \" - \" << std::hex << std::setw(8)\n+\t\t\t<< cfg.pixelFormat << \" on camera:'\" << camera->name()\n+\t\t\t<< \"'\";\n+\n+\t\t/*\n+\t\t * FIXME: As viewfinder should be operated even when\n+\t\t * applications do not intend to use it, we need to keep track\n+\t\t * of which streams have to be configured, to make meaningful\n+\t\t * decisions at configure and request queueing time.\n+\t\t *\n+\t\t * Walk here all the streams to configure and collect the\n+\t\t * active ones in a bitmaks.\n+\t\t */\n+\t\tif (isOutput(data, stream))\n+\t\t\tsetOutputActive(data);\n+\t\tif (isViewfinder(data, stream))\n+\t\t\tsetViewfinderActive(data);\n+\n+\t\t/*\n+\t\t * Collect the maximum width and height: IPU3 can downscale\n+\t\t * only.\n+\t\t */\n+\t\tif (cfg.width > CIO2Config.width)\n+\t\t\tCIO2Config.width = cfg.width;\n+\t\tif (cfg.height > CIO2Config.height)\n+\t\t\tCIO2Config.height = cfg.height;\n \t}\n \n \t/*\n@@ -293,7 +374,7 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera,\n \t * input.\n \t */\n \tV4L2SubdeviceFormat sensorFormat = {};\n-\tret = setCIO2Format(&data->cio2, cfg, &sensorFormat);\n+\tret = setCIO2Format(&data->cio2, CIO2Config, &sensorFormat);\n \tif (ret)\n \t\treturn ret;\n \n@@ -307,41 +388,64 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera,\n \tif (ret)\n \t\treturn ret;\n \n-\tLOG(IPU3, Debug)\n-\t\t<< \"CIO2 output format = \" << cio2Format.toString();\n+\tLOG(IPU3, Debug) << \"CIO2 output format = \" << cio2Format.toString();\n \n \tret = input->setFormat(&cio2Format);\n \tif (ret)\n \t\treturn ret;\n \n-\t/* Apply pad formats and crop/compose rectangle to the ImgU. */\n+\t/* Apply pad formats and crop/compose rectangle to the ImgU input. */\n \tRectangle rect = {\n \t\t.x = 0,\n \t\t.y = 0,\n \t\t.w = cio2Format.width,\n \t\t.h = cio2Format.height,\n \t};\n-\tret = setImguFormat(data->imgu, cfg, &rect);\n+\tret = setInputFormat(data->imgu, CIO2Config, &rect);\n \tif (ret)\n \t\treturn ret;\n \n-\t/* Apply the format to the ImgU output and viewfinder devices. */\n-\tV4L2DeviceFormat outputFormat = {};\n-\toutputFormat.width = cfg.width;\n-\toutputFormat.height = cfg.height;\n-\toutputFormat.fourcc = V4L2_PIX_FMT_NV12;\n-\toutputFormat.planesCount = 2;\n+\tfor (auto const &streamConfig : config) {\n+\t\tStream *stream = streamConfig.first;\n+\t\tconst StreamConfiguration &cfg = streamConfig.second;\n \n-\tret = output->setFormat(&outputFormat);\n-\tif (ret)\n-\t\treturn ret;\n+\t\tif (isOutput(data, stream)) {\n+\t\t\tret = setOutputFormat(data->imgu, output, cfg);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n \n-\tLOG(IPU3, Debug)\n-\t\t<< \"ImgU output format = \" << outputFormat.toString();\n+\t\t\tret = setStatFormat(data->imgu, cfg);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n \n-\tret = viewfinder->setFormat(&outputFormat);\n-\tif (ret)\n-\t\treturn ret;\n+\t\t\t/*\n+\t\t\t * FIXME: even if viewfinder is not in use, we need to\n+\t\t\t * configure and operate it. Use the same size used\n+\t\t\t * for main output.\n+\t\t\t */\n+\t\t\tif (!isViewfinderActive(data)) {\n+\t\t\t\tret = setViewfinderFormat(data->imgu,\n+\t\t\t\t\t\t\t viewfinder, cfg);\n+\t\t\t\tif (ret)\n+\t\t\t\t\treturn ret;\n+\t\t\t}\n+\t\t} else if (isViewfinder(data, stream)) {\n+\t\t\tret = setViewfinderFormat(data->imgu, viewfinder, cfg);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\n+\t\t\t/* Operating the main output is mandatory. */\n+\t\t\tif (!isOutputActive(data)) {\n+\t\t\t\tret = setOutputFormat(data->imgu, output, cfg);\n+\t\t\t\tif (ret)\n+\t\t\t\t\treturn ret;\n+\n+\t\t\t\tret = setStatFormat(data->imgu, cfg);\n+\t\t\t\tif (ret)\n+\t\t\t\t\treturn ret;\n+\t\t\t}\n+\t\t}\n+\t}\n \n \treturn 0;\n }\n@@ -974,9 +1078,9 @@ void PipelineHandlerIPU3::deleteCIO2(CIO2Device *cio2)\n \tdelete cio2->sensor;\n }\n \n-int PipelineHandlerIPU3::setImguFormat(ImgUDevice *imguDevice,\n-\t\t\t\t const StreamConfiguration &config,\n-\t\t\t\t Rectangle *rect)\n+int PipelineHandlerIPU3::setInputFormat(ImgUDevice *imguDevice,\n+\t\t\t\t\tconst StreamConfiguration &config,\n+\t\t\t\t\tRectangle *rect)\n {\n \tV4L2Subdevice *imgu = imguDevice->imgu;\n \tint ret;\n@@ -1012,17 +1116,86 @@ int PipelineHandlerIPU3::setImguFormat(ImgUDevice *imguDevice,\n \tif (ret)\n \t\treturn ret;\n \n+\tLOG(IPU3, Debug) << \"ImgU GDC format = \" << imguFormat.toString();\n+\n+\treturn 0;\n+}\n+\n+int PipelineHandlerIPU3::setOutputFormat(ImgUDevice *imguDevice,\n+\t\t\t\t\t V4L2Device *output,\n+\t\t\t\t\t const StreamConfiguration &config)\n+{\n+\tV4L2Subdevice *imgu = imguDevice->imgu;\n+\tint ret;\n+\n+\tV4L2SubdeviceFormat imguFormat = {};\n+\timguFormat.width = config.width;\n+\timguFormat.height = config.height;\n+\timguFormat.mbus_code = MEDIA_BUS_FMT_FIXED;\n+\n \tret = imgu->setFormat(ImgUDevice::PAD_OUTPUT, &imguFormat);\n \tif (ret)\n \t\treturn ret;\n \n+\tV4L2DeviceFormat outputFormat = {};\n+\toutputFormat.width = config.width;\n+\toutputFormat.height = config.height;\n+\toutputFormat.fourcc = V4L2_PIX_FMT_NV12;\n+\toutputFormat.planesCount = 2;\n+\n+\tret = output->setFormat(&outputFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n \tLOG(IPU3, Debug)\n-\t\t<< \"ImgU GDC format = \" << imguFormat.toString();\n+\t\t<< \"ImgU output format = \" << outputFormat.toString();\n+\n+\treturn 0;\n+}\n+\n+int PipelineHandlerIPU3::setViewfinderFormat(ImgUDevice *imguDevice,\n+\t\t\t\t\t V4L2Device *viewfinder,\n+\t\t\t\t\t const StreamConfiguration &config)\n+{\n+\tV4L2Subdevice *imgu = imguDevice->imgu;\n+\tint ret;\n+\n+\tV4L2SubdeviceFormat imguFormat = {};\n+\timguFormat.width = config.width;\n+\timguFormat.height = config.height;\n+\timguFormat.mbus_code = MEDIA_BUS_FMT_FIXED;\n \n \tret = imgu->setFormat(ImgUDevice::PAD_VF, &imguFormat);\n \tif (ret)\n \t\treturn ret;\n \n+\tV4L2DeviceFormat viewfinderFormat = {};\n+\tviewfinderFormat.width = config.width;\n+\tviewfinderFormat.height = config.height;\n+\tviewfinderFormat.fourcc = V4L2_PIX_FMT_NV12;\n+\tviewfinderFormat.planesCount = 2;\n+\n+\tret = viewfinder->setFormat(&viewfinderFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tLOG(IPU3, Debug)\n+\t\t<< \"ImgU viewfinder format = \" << viewfinderFormat.toString();\n+\n+\treturn 0;\n+}\n+\n+int PipelineHandlerIPU3::setStatFormat(ImgUDevice *imguDevice,\n+\t\t\t\t const StreamConfiguration &config)\n+{\n+\tV4L2Subdevice *imgu = imguDevice->imgu;\n+\tint ret;\n+\n+\tV4L2SubdeviceFormat imguFormat = {};\n+\timguFormat.width = config.width;\n+\timguFormat.height = config.height;\n+\timguFormat.mbus_code = MEDIA_BUS_FMT_FIXED;\n+\n \tret = imgu->setFormat(ImgUDevice::PAD_STAT, &imguFormat);\n \tif (ret)\n \t\treturn ret;\n", "prefixes": [ "libcamera-devel", "v4", "19/31" ] }