[{"id":37031,"web_url":"https://patchwork.libcamera.org/comment/37031/","msgid":"<c932882dd4a3672957e91e08138ffda8@igalia.com>","date":"2025-11-24T15:41:15","subject":"Re: [PATCH v15 8/8] libcamera: simple: Make raw streams working","submitter":{"id":232,"url":"https://patchwork.libcamera.org/api/people/232/","name":"Umang Jain","email":"uajain@igalia.com"},"content":"Hi Milan,\n\nApologies for taking so long on this as I had been travelling last few\nweeks and didn't the proper setup to test this patch.\n\nThis series works as expected, however I do want a discussion on one of\nthe point below:\n\nOn 2025-11-04 21:04, Milan Zamazal wrote:\n> When a raw stream is requested, whether alone or together with a\n> processed stream, its buffers must be handled outside the software ISP\n> machinery.  They serve as output buffers, even when a processed stream\n> is produced.\n> \n> At most one raw stream and at most one processed stream are supported\n> and can be combined.  An example of producing both raw and processed\n> files using `cam' application:\n> \n>   cam -c1 -C100 -Ffile# \\\n>     -s role=viewfinder,width=1920,height=1080,pixelformat=RGB888 \\\n>     -s role=raw,width=3280,height=2464,pixelformat=SRGGB8 \\\n> \n> Note the difference in viewfinder and raw stream sizes due to the fact\n> that debayering requires enlarging the image width, which enforces\n> selecting a larger sensor resolution in this case.\n> \n> In order to track whether a raw stream is requested and which one it is,\n> SimpleCameraData::rawStream_ member variable is introduced.\n> \n> This is the final step to make raw streams working.\n> \n> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n> ---\n>  src/libcamera/pipeline/simple/simple.cpp | 41 +++++++++++++++++-------\n>  1 file changed, 29 insertions(+), 12 deletions(-)\n> \n> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n> index cb0b24f38..dd32b70f1 100644\n> --- a/src/libcamera/pipeline/simple/simple.cpp\n> +++ b/src/libcamera/pipeline/simple/simple.cpp\n> @@ -333,6 +333,7 @@ public:\n>  \t};\n>  \n>  \tstd::vector<Stream> streams_;\n> +\tStream *rawStream_;\n>  \n>  \t/*\n>  \t * All entities in the pipeline, from the camera sensor to the video\n> @@ -467,7 +468,7 @@ private:\n>  SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe,\n>  \t\t\t\t   unsigned int numStreams,\n>  \t\t\t\t   MediaEntity *sensor)\n> -\t: Camera::Private(pipe), streams_(numStreams)\n> +\t: Camera::Private(pipe), streams_(numStreams), rawStream_(nullptr)\n>  {\n>  \t/*\n>  \t * Find the shortest path from the camera sensor to a video capture\n> @@ -878,10 +879,13 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)\n>  \t * point converting an erroneous buffer.\n>  \t */\n>  \tif (buffer->metadata().status != FrameMetadata::FrameSuccess) {\n> -\t\tif (!useConversion_) {\n> +\t\tif (!useConversion_ || rawStream_) {\n>  \t\t\t/* No conversion, just complete the request. */\n>  \t\t\tRequest *request = buffer->request();\n>  \t\t\tpipe->completeBuffer(request, buffer);\n> +\t\t\tSimpleFrameInfo *info = frameInfo_.find(request->sequence());\n> +\t\t\tif (info)\n> +\t\t\t\tinfo->metadataRequired = false;\n>  \t\t\ttryCompleteRequest(request);\n>  \t\t\treturn;\n>  \t\t}\n> @@ -940,7 +944,8 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)\n>  \t */\n>  \tif (useConversion_) {\n>  \t\tif (conversionQueue_.empty()) {\n> -\t\t\tvideo_->queueBuffer(buffer);\n> +\t\t\tif (!rawStream_)\n> +\t\t\t\tvideo_->queueBuffer(buffer);\n>  \t\t\treturn;\n>  \t\t}\n>  \n> @@ -956,6 +961,8 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)\n>  \t\t\t\t\t     conversionQueue_.front().outputs);\n>  \n>  \t\tconversionQueue_.pop();\n> +\t\tif (rawStream_)\n> +\t\t\tpipe->completeBuffer(request, buffer);\n\nContext: We are here in the case where `useConversion_ = true` so, the\ncase is 1 RAW + 1 processed stream here. And the RAW buffer is queued to\nswISP/converter.\n\nI am not sure which is a better place to complete the RAW buffer in this\ncase. Should we complete here like you have done or probably in\nconversionInputDone() like in [1]. I think the interaction between\ncompleteBuffer() and swIsp_->inputBufferReady is not clear because it is\nprobably case to case basis, but with your implementation I see a risk\nof client application having access to the completed RAW buffer *while*\nit is still an input for the swISP/converter. This makes me slightly\nincline towards [1]. Do you have any opinions ?\n\n[1]:\nhttps://gitlab.freedesktop.org/uajain/libcamera/-/commit/d1749c4f08f\n\n>  \t\treturn;\n>  \t}\n>  \n> @@ -993,7 +1000,8 @@ void SimpleCameraData::tryCompleteRequest(Request *request)\n>  void SimpleCameraData::conversionInputDone(FrameBuffer *buffer)\n>  {\n>  \t/* Queue the input buffer back for capture. */\n> -\tvideo_->queueBuffer(buffer);\n> +\tif (!rawStream_)\n> +\t\tvideo_->queueBuffer(buffer);\n>  }\n>  \n>  void SimpleCameraData::conversionOutputDone(FrameBuffer *buffer)\n> @@ -1518,13 +1526,18 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n>  \tstd::vector<std::reference_wrapper<StreamConfiguration>> outputCfgs;\n>  \tdata->useConversion_ = config->needConversion();\n>  \n> +\tdata->rawStream_ = nullptr;\n>  \tfor (unsigned int i = 0; i < config->size(); ++i) {\n>  \t\tStreamConfiguration &cfg = config->at(i);\n> +\t\tbool rawStream = isRaw(cfg);\n>  \n>  \t\tcfg.setStream(&data->streams_[i]);\n>  \n> -\t\tif (data->useConversion_ && !isRaw(cfg))\n> +\t\tif (data->useConversion_ && !rawStream)\n>  \t\t\toutputCfgs.push_back(cfg);\n> +\n> +\t\tif (rawStream)\n> +\t\t\tdata->rawStream_ = &data->streams_[i];\n>  \t}\n>  \n>  \tif (outputCfgs.empty())\n> @@ -1555,7 +1568,7 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,\n>  \t * Export buffers on the converter or capture video node, depending on\n>  \t * whether the converter is used or not.\n>  \t */\n> -\tif (data->useConversion_)\n> +\tif (data->useConversion_ && stream != data->rawStream_)\n>  \t\treturn data->converter_\n>  \t\t\t       ? data->converter_->exportBuffers(stream, count, buffers)\n>  \t\t\t       : data->swIsp_->exportBuffers(stream, count, buffers);\n> @@ -1578,7 +1591,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL\n>  \t\treturn -EBUSY;\n>  \t}\n>  \n> -\tif (data->useConversion_) {\n> +\tif (data->useConversion_ && !data->rawStream_) {\n>  \t\t/*\n>  \t\t * When using the converter allocate a fixed number of internal\n>  \t\t * buffers.\n> @@ -1586,8 +1599,11 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL\n>  \t\tret = video->allocateBuffers(kNumInternalBuffers,\n>  \t\t\t\t\t     &data->conversionBuffers_);\n>  \t} else {\n> -\t\t/* Otherwise, prepare for using buffers from the only stream. */\n> -\t\tStream *stream = &data->streams_[0];\n> +\t\t/*\n> +\t\t * Otherwise, prepare for using buffers from either the raw stream, if\n> +\t\t * requested, or the only stream configured.\n> +\t\t */\n> +\t\tStream *stream = (data->rawStream_ ? data->rawStream_ : &data->streams_[0]);\n>  \t\tret = video->importBuffers(stream->configuration().bufferCount);\n>  \t}\n>  \tif (ret < 0) {\n> @@ -1628,8 +1644,9 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL\n>  \t\t}\n>  \n>  \t\t/* Queue all internal buffers for capture. */\n> -\t\tfor (std::unique_ptr<FrameBuffer> &buffer : data->conversionBuffers_)\n> -\t\t\tvideo->queueBuffer(buffer.get());\n> +\t\tif (!data->rawStream_)\n> +\t\t\tfor (std::unique_ptr<FrameBuffer> &buffer : data->conversionBuffers_)\n> +\t\t\t\tvideo->queueBuffer(buffer.get());\n>  \t}\n>  \n>  \treturn 0;\n> @@ -1680,7 +1697,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request)\n>  \t\t * queue, it will be handed to the converter in the capture\n>  \t\t * completion handler.\n>  \t\t */\n> -\t\tif (data->useConversion_) {\n> +\t\tif (data->useConversion_ && stream != data->rawStream_) {\n>  \t\t\tbuffers.emplace(stream, buffer);\n>  \t\t\tmetadataRequired = !!data->swIsp_;\n>  \t\t} else {","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 9EF01C326B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 24 Nov 2025 15:41:21 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7B81660A9D;\n\tMon, 24 Nov 2025 16:41:20 +0100 (CET)","from fanzine2.igalia.com (fanzine2.igalia.com [213.97.179.56])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 22BAB6096B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 24 Nov 2025 16:41:19 +0100 (CET)","from maestria.local.igalia.com ([192.168.10.14]\n\thelo=mail.igalia.com) by fanzine2.igalia.com with esmtps \n\t(Cipher TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256)\n\t(Exim) id 1vNYgo-004oOz-4A; Mon, 24 Nov 2025 16:41:18 +0100","from webmail.service.igalia.com ([192.168.21.45])\n\tby mail.igalia.com with esmtp (Exim)\n\tid 1vNYgl-00CWKP-Hk; Mon, 24 Nov 2025 16:41:17 +0100","from localhost ([127.0.0.1] helo=webmail.igalia.com)\n\tby webmail with esmtp (Exim 4.96) (envelope-from <uajain@igalia.com>)\n\tid 1vNYgl-002GQK-0F; Mon, 24 Nov 2025 16:41:15 +0100"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=igalia.com header.i=@igalia.com\n\theader.b=\"qagrxXbG\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com;\n\ts=20170329;\n\th=Content-Transfer-Encoding:Content-Type:Message-ID:References:\n\tIn-Reply-To:Subject:Cc:To:From:Date:MIME-Version:Sender:Reply-To:Content-ID:\n\tContent-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc\n\t:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:\n\tList-Post:List-Owner:List-Archive;\n\tbh=9bB9+kTcIbzHYmxJCmndgOFg6uvYjELYBjIFKYk0Bo4=;\n\tb=qagrxXbG4oYJQEWmAfGaJmFKF6\n\tlpPL97wVok2Wuq6SHkYJWVQK5L1ODfONqVyQqeLnGe5yxhjLcARwONn0X1ptHLHVYhxp1rDHH7+rB\n\t15VA7z9HejFIbf4ceuhd6WNWlLSHZqY9aDF1PX9xLcXQ6kqPn1DUIaRNrka+y57gYn8Zq0eBPHiYe\n\tqii99j4M3fR+7dgMlB0xW2MxEeGBZNyeIbJP57jCJuwxL7b86rQ5P/8Kw/M70upKXQm2DVQsOGh+D\n\tWaLYuRLDNKzzZnxFJrp+uJ63+PqtiQwLpgwX1HE03eWPjhH1zvd4SqcOLaotjS8vV3V2UpuKTjfay\n\t5AX7wlfg==;","MIME-Version":"1.0","Date":"Mon, 24 Nov 2025 21:11:15 +0530","From":"Umang Jain <uajain@igalia.com>","To":"Milan Zamazal <mzamazal@redhat.com>","Cc":"libcamera-devel@lists.libcamera.org, Laurent Pinchart\n\t<laurent.pinchart@ideasonboard.com>,\n\tKieran Bingham <kieran.bingham@ideasonboard.com>, =?utf-8?q?Barnab?=\n\t=?utf-8?b?w6FzIFDFkWN6ZQ==?= <barnabas.pocze@ideasonboard.com>,\n\tPaul Elder <paul.elder@ideasonboard.com>","Subject":"Re: [PATCH v15 8/8] libcamera: simple: Make raw streams working","In-Reply-To":"<20251104153501.34362-9-mzamazal@redhat.com>","References":"<20251104153501.34362-1-mzamazal@redhat.com>\n\t<20251104153501.34362-9-mzamazal@redhat.com>","Message-ID":"<c932882dd4a3672957e91e08138ffda8@igalia.com>","X-Sender":"uajain@igalia.com","Content-Type":"text/plain; charset=US-ASCII","Content-Transfer-Encoding":"7bit","X-Spam-Report":"NO, Score=-2.2, Tests=ALL_TRUSTED=-3, AWL=0.001, BAYES_50=0.8,\n\tURIBL_BLOCKED=0.001","X-Spam-Score":"-21","X-Spam-Bar":"--","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":37037,"web_url":"https://patchwork.libcamera.org/comment/37037/","msgid":"<85tsyjm8tm.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","date":"2025-11-24T21:15:01","subject":"Re: [PATCH v15 8/8] libcamera: simple: Make raw streams working","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Hi Umang,\n\nUmang Jain <uajain@igalia.com> writes:\n\n> Hi Milan,\n>\n> Apologies for taking so long on this as I had been travelling last few\n> weeks and didn't the proper setup to test this patch.\n>\n> This series works as expected, however I do want a discussion on one of\n> the point below:\n>\n> On 2025-11-04 21:04, Milan Zamazal wrote:\n>> When a raw stream is requested, whether alone or together with a\n>> processed stream, its buffers must be handled outside the software ISP\n>> machinery.  They serve as output buffers, even when a processed stream\n>> is produced.\n>> \n>> At most one raw stream and at most one processed stream are supported\n>> and can be combined.  An example of producing both raw and processed\n>> files using `cam' application:\n>> \n>>   cam -c1 -C100 -Ffile# \\\n>>     -s role=viewfinder,width=1920,height=1080,pixelformat=RGB888 \\\n>>     -s role=raw,width=3280,height=2464,pixelformat=SRGGB8 \\\n>> \n>> Note the difference in viewfinder and raw stream sizes due to the fact\n>> that debayering requires enlarging the image width, which enforces\n>> selecting a larger sensor resolution in this case.\n>> \n>> In order to track whether a raw stream is requested and which one it is,\n>> SimpleCameraData::rawStream_ member variable is introduced.\n>> \n>> This is the final step to make raw streams working.\n>> \n>> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n>> ---\n>>  src/libcamera/pipeline/simple/simple.cpp | 41 +++++++++++++++++-------\n>>  1 file changed, 29 insertions(+), 12 deletions(-)\n>> \n>> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\n>> index cb0b24f38..dd32b70f1 100644\n>> --- a/src/libcamera/pipeline/simple/simple.cpp\n>> +++ b/src/libcamera/pipeline/simple/simple.cpp\n>> @@ -333,6 +333,7 @@ public:\n>>  \t};\n>>  \n>>  \tstd::vector<Stream> streams_;\n>> +\tStream *rawStream_;\n>>  \n>>  \t/*\n>>  \t * All entities in the pipeline, from the camera sensor to the video\n>> @@ -467,7 +468,7 @@ private:\n>>  SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe,\n>>  \t\t\t\t   unsigned int numStreams,\n>>  \t\t\t\t   MediaEntity *sensor)\n>> -\t: Camera::Private(pipe), streams_(numStreams)\n>> +\t: Camera::Private(pipe), streams_(numStreams), rawStream_(nullptr)\n>>  {\n>>  \t/*\n>>  \t * Find the shortest path from the camera sensor to a video capture\n>> @@ -878,10 +879,13 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)\n>>  \t * point converting an erroneous buffer.\n>>  \t */\n>>  \tif (buffer->metadata().status != FrameMetadata::FrameSuccess) {\n>> -\t\tif (!useConversion_) {\n>> +\t\tif (!useConversion_ || rawStream_) {\n>>  \t\t\t/* No conversion, just complete the request. */\n>>  \t\t\tRequest *request = buffer->request();\n>>  \t\t\tpipe->completeBuffer(request, buffer);\n>> +\t\t\tSimpleFrameInfo *info = frameInfo_.find(request->sequence());\n>> +\t\t\tif (info)\n>> +\t\t\t\tinfo->metadataRequired = false;\n>>  \t\t\ttryCompleteRequest(request);\n>>  \t\t\treturn;\n>>  \t\t}\n>> @@ -940,7 +944,8 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)\n>>  \t */\n>>  \tif (useConversion_) {\n>>  \t\tif (conversionQueue_.empty()) {\n>> -\t\t\tvideo_->queueBuffer(buffer);\n>> +\t\t\tif (!rawStream_)\n>> +\t\t\t\tvideo_->queueBuffer(buffer);\n>>  \t\t\treturn;\n>>  \t\t}\n>>  \n>> @@ -956,6 +961,8 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)\n>>  \t\t\t\t\t     conversionQueue_.front().outputs);\n>>  \n>>  \t\tconversionQueue_.pop();\n>> +\t\tif (rawStream_)\n>> +\t\t\tpipe->completeBuffer(request, buffer);\n>\n> Context: We are here in the case where `useConversion_ = true` so, the\n> case is 1 RAW + 1 processed stream here. And the RAW buffer is queued to\n> swISP/converter.\n>\n> I am not sure which is a better place to complete the RAW buffer in this\n> case. Should we complete here like you have done or probably in\n> conversionInputDone() like in [1]. I think the interaction between\n> completeBuffer() and swIsp_->inputBufferReady is not clear because it is\n> probably case to case basis, but with your implementation I see a risk\n> of client application having access to the completed RAW buffer *while*\n> it is still an input for the swISP/converter. This makes me slightly\n> incline towards [1]. Do you have any opinions ?\n\nGood point.  Yes, [1] is a better solution for this.  I'll re-check the\nother differences with this context and update the patch series one way\nor the other.\n\n> [1]:\n> https://gitlab.freedesktop.org/uajain/libcamera/-/commit/d1749c4f08f\n>\n>>  \t\treturn;\n>>  \t}\n>>  \n>> @@ -993,7 +1000,8 @@ void SimpleCameraData::tryCompleteRequest(Request *request)\n>>  void SimpleCameraData::conversionInputDone(FrameBuffer *buffer)\n>>  {\n>>  \t/* Queue the input buffer back for capture. */\n>> -\tvideo_->queueBuffer(buffer);\n>> +\tif (!rawStream_)\n>> +\t\tvideo_->queueBuffer(buffer);\n>>  }\n>>  \n>>  void SimpleCameraData::conversionOutputDone(FrameBuffer *buffer)\n>> @@ -1518,13 +1526,18 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n>>  \tstd::vector<std::reference_wrapper<StreamConfiguration>> outputCfgs;\n>>  \tdata->useConversion_ = config->needConversion();\n>>  \n>> +\tdata->rawStream_ = nullptr;\n>>  \tfor (unsigned int i = 0; i < config->size(); ++i) {\n>>  \t\tStreamConfiguration &cfg = config->at(i);\n>> +\t\tbool rawStream = isRaw(cfg);\n>>  \n>>  \t\tcfg.setStream(&data->streams_[i]);\n>>  \n>> -\t\tif (data->useConversion_ && !isRaw(cfg))\n>> +\t\tif (data->useConversion_ && !rawStream)\n>>  \t\t\toutputCfgs.push_back(cfg);\n>> +\n>> +\t\tif (rawStream)\n>> +\t\t\tdata->rawStream_ = &data->streams_[i];\n>>  \t}\n>>  \n>>  \tif (outputCfgs.empty())\n>> @@ -1555,7 +1568,7 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,\n>>  \t * Export buffers on the converter or capture video node, depending on\n>>  \t * whether the converter is used or not.\n>>  \t */\n>> -\tif (data->useConversion_)\n>> +\tif (data->useConversion_ && stream != data->rawStream_)\n>>  \t\treturn data->converter_\n>>  \t\t\t       ? data->converter_->exportBuffers(stream, count, buffers)\n>>  \t\t\t       : data->swIsp_->exportBuffers(stream, count, buffers);\n>> @@ -1578,7 +1591,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL\n>>  \t\treturn -EBUSY;\n>>  \t}\n>>  \n>> -\tif (data->useConversion_) {\n>> +\tif (data->useConversion_ && !data->rawStream_) {\n>>  \t\t/*\n>>  \t\t * When using the converter allocate a fixed number of internal\n>>  \t\t * buffers.\n>> @@ -1586,8 +1599,11 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL\n>>  \t\tret = video->allocateBuffers(kNumInternalBuffers,\n>>  \t\t\t\t\t     &data->conversionBuffers_);\n>>  \t} else {\n>> -\t\t/* Otherwise, prepare for using buffers from the only stream. */\n>> -\t\tStream *stream = &data->streams_[0];\n>> +\t\t/*\n>> +\t\t * Otherwise, prepare for using buffers from either the raw stream, if\n>> +\t\t * requested, or the only stream configured.\n>> +\t\t */\n>> +\t\tStream *stream = (data->rawStream_ ? data->rawStream_ : &data->streams_[0]);\n>>  \t\tret = video->importBuffers(stream->configuration().bufferCount);\n>>  \t}\n>>  \tif (ret < 0) {\n>> @@ -1628,8 +1644,9 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL\n>>  \t\t}\n>>  \n>>  \t\t/* Queue all internal buffers for capture. */\n>> -\t\tfor (std::unique_ptr<FrameBuffer> &buffer : data->conversionBuffers_)\n>> -\t\t\tvideo->queueBuffer(buffer.get());\n>> +\t\tif (!data->rawStream_)\n>> +\t\t\tfor (std::unique_ptr<FrameBuffer> &buffer : data->conversionBuffers_)\n>> +\t\t\t\tvideo->queueBuffer(buffer.get());\n>>  \t}\n>>  \n>>  \treturn 0;\n>> @@ -1680,7 +1697,7 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request)\n>>  \t\t * queue, it will be handed to the converter in the capture\n>>  \t\t * completion handler.\n>>  \t\t */\n>> -\t\tif (data->useConversion_) {\n>> +\t\tif (data->useConversion_ && stream != data->rawStream_) {\n>>  \t\t\tbuffers.emplace(stream, buffer);\n>>  \t\t\tmetadataRequired = !!data->swIsp_;\n>>  \t\t} else {","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 969B6C32DE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 24 Nov 2025 21:15:12 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A6B8F60A9D;\n\tMon, 24 Nov 2025 22:15:11 +0100 (CET)","from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.133.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id EFFAA6096B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 24 Nov 2025 22:15:08 +0100 (CET)","from mail-wm1-f72.google.com (mail-wm1-f72.google.com\n\t[209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-602-_6kYIoZCONqdJNufBXT0iw-1; Mon, 24 Nov 2025 16:15:04 -0500","by mail-wm1-f72.google.com with SMTP id\n\t5b1f17b1804b1-4779b432aecso36934625e9.0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 24 Nov 2025 13:15:04 -0800 (PST)","from mzamazal-thinkpadp1gen7.tpbc.csb\n\t(ip-77-48-47-2.net.vodafone.cz. [77.48.47.2])\n\tby smtp.gmail.com with ESMTPSA id\n\tffacd0b85a97d-42cb7fb9190sm30321398f8f.33.2025.11.24.13.15.01\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tMon, 24 Nov 2025 13:15:02 -0800 (PST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"KUrYaYfm\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1764018907;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=kGbmkxMA25JWzckqnuICQwQDgJiMiCNnbuw7bc4ro64=;\n\tb=KUrYaYfmFErIQiITa9wpAQqngFlBlWK3wnLa0uYPQ+I+/92aJxVozZQ9Zkd2ORY1rRQ/j4\n\tO0pWujpv+JRbGoI/ZDOdmlwurx2065ebtUgJEQLpDxomzylo9j9EEv78HdNWPIRBmr7eMI\n\t+UxUSKXn7e0GDAJq6i1nsfOzJWSYXQc=","X-MC-Unique":"_6kYIoZCONqdJNufBXT0iw-1","X-Mimecast-MFC-AGG-ID":"_6kYIoZCONqdJNufBXT0iw_1764018904","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1764018903; x=1764623703;\n\th=mime-version:user-agent:message-id:date:references:in-reply-to\n\t:subject:cc:to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject\n\t:date:message-id:reply-to;\n\tbh=kGbmkxMA25JWzckqnuICQwQDgJiMiCNnbuw7bc4ro64=;\n\tb=oWSp0VPj2f9+gyd6h3h75peQvdMJYUj7IL7+Jg7wLrJ0pS3c/4aPWDJzC/fiqbzNro\n\tngZ3Hj+NrRY3v6wUGDDeG13e+mqkay/DFiCje2a4Uym9Wro7fZQ+IaLJTpf9X7suB/6j\n\tLNEgt29F5vbWLKLC/xiuGmsSLnxf8SpU0mxd1qRBLVMwIJssxs8JZZovMv0X5/EZTxhG\n\tuyPIYmzrangPuuUEDnEXzhfR1LI6rsT68Tt92iJItpWDtCTErdZqKk0TD0q5DcV6Qs6m\n\ttD9vvv8q4So2Ep9hE0lLNIf9oAV/LR8zhAfD7b1femR/jYdtoO5zrJX0JmUa2ULvitfC\n\tuK/w==","X-Gm-Message-State":"AOJu0YyzH4Ayqs4qxBYYD8C9UboPhKJmEkH8k1lIYgt5OUuJ324UHUNf\n\tc4XZzg+5fjWNwKlePe88CpsFj4oGoeCKvcbT3BBzzJ+zE9/INNo3nBMHIP/JzPeb7fsFnkv2OfP\n\t3aZthDNvcM4k65Y7Zd4QhfCVd698WX/z8UrArEyJerH95t528mjGH8cRKe4BU+TjEDfHtNy1Crj\n\tLpqYHm4Uw=","X-Gm-Gg":"ASbGnct8eNuhRz5CdZfOoKMTkjV8//zR+iEbKroHMI5CsZiCfL9txtIny65O1FbV8XT\n\t102ACIQwSg5pAzYRgcjcuvjBxklfMZf0EfOJhYoEbhyLjZAdF30N0qy6tmNS4wL5cUkI/G61BbU\n\tN950k23+54wRUt55/JMYPB+L2zi0Oq5EWU/4MjbPWIcujhSinn4n0kT/nxD/mjdvAOtxeNCkzRp\n\t3HCgErnppaQOH/O2jrA93qSvOhLwIivi5dYpN3BpKUHfn/61JTgrqcPFDOjh2WQlYZB3gh5GB8r\n\t+p8Nooh4zGfWPFki3n2Ac9Lfxi25fmC0+rEptug7lpxoPmiTlpoEmzCgyM/Bu4TDolZ6UkT7swC\n\td6QIS0cF90gwaehgIMHLl8BVQkri55UdpSQe/5gAa1Fax0CH/OUBeqI/5GY+q16A=","X-Received":["by 2002:a05:600c:3590:b0:477:54f9:6ac2 with SMTP id\n\t5b1f17b1804b1-477c104fc20mr161995625e9.0.1764018903051; \n\tMon, 24 Nov 2025 13:15:03 -0800 (PST)","by 2002:a05:600c:3590:b0:477:54f9:6ac2 with SMTP id\n\t5b1f17b1804b1-477c104fc20mr161995415e9.0.1764018902559; \n\tMon, 24 Nov 2025 13:15:02 -0800 (PST)"],"X-Google-Smtp-Source":"AGHT+IHF3YFmvoa0xcz5rODvwHyNOZvBRJny9gieFBgng+WwvvrBL84sLm/KaG/ohPn1drZYdN7jDg==","From":"Milan Zamazal <mzamazal@redhat.com>","To":"Umang Jain <uajain@igalia.com>","Cc":"libcamera-devel@lists.libcamera.org,  Laurent Pinchart\n\t<laurent.pinchart@ideasonboard.com>,\n\tKieran Bingham <kieran.bingham@ideasonboard.com>, =?utf-8?q?Barnab?=\n\t=?utf-8?b?w6FzIFDFkWN6ZQ==?=\n\t<barnabas.pocze@ideasonboard.com>, Paul Elder\n\t<paul.elder@ideasonboard.com>","Subject":"Re: [PATCH v15 8/8] libcamera: simple: Make raw streams working","In-Reply-To":"<c932882dd4a3672957e91e08138ffda8@igalia.com> (Umang Jain's\n\tmessage of \"Mon, 24 Nov 2025 21:11:15 +0530\")","References":"<20251104153501.34362-1-mzamazal@redhat.com>\n\t<20251104153501.34362-9-mzamazal@redhat.com>\n\t<c932882dd4a3672957e91e08138ffda8@igalia.com>","Date":"Mon, 24 Nov 2025 22:15:01 +0100","Message-ID":"<85tsyjm8tm.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"D9otdsTSvjoVD9G9-KVmm1z-xpoiVEGGmXhchDWYTP4_1764018904","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain","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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]