[{"id":4690,"web_url":"https://patchwork.libcamera.org/comment/4690/","msgid":"<20200430194417.GW5856@pendragon.ideasonboard.com>","date":"2020-04-30T19:44:17","subject":"Re: [libcamera-devel] [RFC/PATCH 5/5] qcam: Add RAW capture support","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Niklas,\n\nThank you for the patch.\n\nOn Thu, Apr 30, 2020 at 02:36:04AM +0200, Niklas Söderlund wrote:\n> Add a toolbar button that captures RAW data to disk. The button is only\n> enabled if the camera is configured to provide a raw stream to the\n> application.\n> \n> Only when the capture action is triggered will a request with a raw\n> buffer be queued to the camera.\n> \n> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> ---\n>  src/qcam/assets/feathericons/feathericons.qrc |  1 +\n>  src/qcam/main_window.cpp                      | 94 ++++++++++++++++++-\n>  src/qcam/main_window.h                        |  4 +\n>  3 files changed, 98 insertions(+), 1 deletion(-)\n> \n> diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc\n> index c4eb7a0be6884373..fc8213928ece70ea 100644\n> --- a/src/qcam/assets/feathericons/feathericons.qrc\n> +++ b/src/qcam/assets/feathericons/feathericons.qrc\n> @@ -1,5 +1,6 @@\n>  <!DOCTYPE RCC><RCC version=\"1.0\">\n>  <qresource>\n> +<file>./aperture.svg</file>\n>  <file>./camera-off.svg</file>\n>  <file>./play-circle.svg</file>\n>  <file>./save.svg</file>\n> diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp\n> index f57aaf4a27e5f4ca..535fa53d6705a1a9 100644\n> --- a/src/qcam/main_window.cpp\n> +++ b/src/qcam/main_window.cpp\n> @@ -7,10 +7,13 @@\n>  \n>  #include \"main_window.h\"\n>  \n> +#include <fcntl.h>\n>  #include <iomanip>\n>  #include <sstream>\n>  #include <string>\n>  #include <sys/mman.h>\n> +#include <sys/stat.h>\n> +#include <unistd.h>\n>  \n>  #include <QComboBox>\n>  #include <QCoreApplication>\n> @@ -49,7 +52,8 @@ public:\n>  };\n>  \n>  MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options)\n> -\t: options_(options), cm_(cm), allocator_(nullptr), isCapturing_(false)\n> +\t: options_(options), cm_(cm), allocator_(nullptr), isCapturing_(false),\n> +\t  captureRaw_(false)\n>  {\n>  \tint ret;\n>  \n> @@ -149,6 +153,14 @@ int MainWindow::createToolbars()\n>  \t\t\t\t     \"Save As...\");\n>  \tconnect(action, &QAction::triggered, this, &MainWindow::saveViewfinder);\n>  \n> +\t/* Save Raw action. */\n> +\taction = toolbar_->addAction(QIcon::fromTheme(\"document-save-as\",\n\nThis will end up using the same icon as for the regulare image capture\non platforms whose theme offer document-save-as. Could we pick a\ndifferent one ?\n\n> +\t\t\t\t\t\t      QIcon(\":aperture.svg\")),\n> +\t\t\t\t     \"Save Raw\");\n> +\taction->setEnabled(false);\n> +\tconnect(action, &QAction::triggered, this, &MainWindow::saveRaw);\n> +\tsaveRaw_ = action;\n> +\n>  \treturn 0;\n>  }\n>  \n> @@ -369,6 +381,9 @@ int MainWindow::startCapture()\n>  \n>  \tadjustSize();\n>  \n> +\t/* Configure the raw capture button. */\n> +\tsaveRaw_->setEnabled(config_->size() == 2);\n\nShouldn't the normal save button be enabled and disabled when starting\nand stopping capture too ?\n\n> +\n>  \t/* Allocate and map buffers. */\n>  \tallocator_ = new FrameBufferAllocator(camera_);\n>  \tfor (StreamConfiguration &config : *config_) {\n> @@ -474,6 +489,7 @@ void MainWindow::stopCapture()\n>  \t\treturn;\n>  \n>  \tviewfinder_->stop();\n> +\tsaveRaw_->setEnabled(false);\n>  \n>  \tint ret = camera_->stop();\n>  \tif (ret)\n> @@ -514,6 +530,11 @@ void MainWindow::saveViewfinder()\n>  \tsaveViewfinder_ = true;\n>  }\n>  \n> +void MainWindow::saveRaw()\n> +{\n> +\tcaptureRaw_ = true;\n> +}\n> +\n>  /* -----------------------------------------------------------------------------\n>   * Request Completion Handling\n>   */\n> @@ -558,6 +579,9 @@ void MainWindow::processCapture()\n>  \t\tif (buffers.count(vfStream_))\n>  \t\t\tprocessViewfinder(buffers[vfStream_]);\n>  \n> +\t\tif (buffers.count(rawStream_))\n> +\t\t\tprocessRaw(buffers[rawStream_]);\n> +\n>  \t\t/*\n>  \t\t * Return buffers so they can be reused. No processing involving\n>  \t\t * a buffer can happen after they are returned to the free list.\n> @@ -618,6 +642,61 @@ void MainWindow::processViewfinder(FrameBuffer *buffer)\n>  \t}\n>  }\n>  \n> +void MainWindow::processRaw(FrameBuffer *raw)\n\ns/raw/buffer/ ?\n\n> +{\n> +\t/* TODO: Should write a DNG file instead of a .raw and .jpeg file.  */\n> +\n> +\tunsigned int seq = raw->metadata().sequence;\n> +\tstd::string filename;\n> +\tint fd, ret = 0;\n> +\tsize_t pos;\n> +\n> +\t/* Write .raw */\n> +\tfilename = defaultPath_.toStdString() + \"/raw-#.raw\";\n> +\tpos = filename.find_first_of('#');\n> +\tif (pos != std::string::npos) {\n> +\t\tstd::stringstream ss;\n> +\t\tss << std::setw(6) << std::setfill('0') << seq;\n> +\t\tfilename.replace(pos, 1, ss.str());\n> +\t}\n\nSame comment as for the previous patch, use QString.\n\n> +\tqInfo() << \"Saving\" << filename.c_str();\n> +\n> +\tfd = open(filename.c_str(), O_CREAT | O_WRONLY |\n> +\t\t  (pos == std::string::npos ? O_APPEND : O_TRUNC),\n> +\t\t  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);\n> +\tif (fd == -1) {\n> +\t\tqWarning() << \"Failed to open raw output file\";\n> +\t\treturn;\n> +\t}\n\nAnd use QFile :-)\n\n> +\n> +\tconst MappedBuffer &info = mappedBuffers_[raw];\n> +\tret = ::write(fd, info.memory, info.size);\n> +\tif (ret < 0) {\n> +\t\tret = -errno;\n> +\t\tqWarning() << \"write error: \" << strerror(-ret);\n> +\t} else if (ret != (int)info.size) {\n> +\t\tqWarning() << \"write error: only \" << ret\n> +\t\t\t   << \" bytes written instead of \" << info.size;\n> +\t}\n> +\n> +\t::close(fd);\n> +\n> +\t/* Write scaled thumbnail .jpeg */\n> +\tfilename = defaultPath_.toStdString() + \"/raw-#.jpeg\";\n> +\tpos = filename.find_first_of('#');\n> +\tif (pos != std::string::npos) {\n> +\t\tstd::stringstream ss;\n> +\t\tss << std::setw(6) << std::setfill('0') << seq;\n> +\t\tfilename.replace(pos, 1, ss.str());\n> +\t}\n> +\tqInfo() << \"Saving\" << filename.c_str();\n> +\n> +\tQImage image = viewfinder_->getCurrentImage().scaledToHeight(640);\n\nThat's a big thumbnail. And a weird height value, did you mean\nscaledToWidth(), or 480 instead of 640 ?\n\n> +\tQImageWriter writer(QString::fromUtf8(filename.c_str()));\n> +\twriter.setQuality(95);\n> +\twriter.write(image);\n> +}\n> +\n>  void MainWindow::queueRequest(FrameBuffer *buffer)\n>  {\n>  \tRequest *request = camera_->createRequest();\n> @@ -628,5 +707,18 @@ void MainWindow::queueRequest(FrameBuffer *buffer)\n>  \n>  \trequest->addBuffer(vfStream_, buffer);\n>  \n> +\tif (captureRaw_) {\n> +\t\tQMutexLocker locker(&mutex_);\n> +\n> +\t\tif (freeBuffers_[rawStream_].isEmpty()) {\n> +\t\t\tqWarning() << \"Raw stream buffer empty\";\n> +\t\t\treturn;\n\nShouldn't we still queue the request, without a raw buffer ?\n\n> +\t\t}\n> +\n> +\t\trequest->addBuffer(rawStream_,\n> +\t\t\t\t   freeBuffers_[rawStream_].dequeue());\n> +\t\tcaptureRaw_ = false;\n> +\t}\n> +\n>  \tcamera_->queueRequest(request);\n>  }\n> diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h\n> index 580bcac146fabe07..37a1d95351e144e0 100644\n> --- a/src/qcam/main_window.h\n> +++ b/src/qcam/main_window.h\n> @@ -55,6 +55,7 @@ private Q_SLOTS:\n>  \tvoid toggleCapture(bool start);\n>  \n>  \tvoid saveViewfinder();\n> +\tvoid saveRaw();\n>  \n>  \tvoid queueRequest(FrameBuffer *buffer);\n>  \n> @@ -70,10 +71,12 @@ private:\n>  \tvoid requestComplete(Request *request);\n>  \tvoid processCapture();\n>  \tvoid processViewfinder(FrameBuffer *buffer);\n> +\tvoid processRaw(FrameBuffer *raw);\n\ns/raw/buffer/ ?\n\n>  \n>  \t/* UI elements */\n>  \tQToolBar *toolbar_;\n>  \tQAction *startStopAction_;\n> +\tQAction *saveRaw_;\n>  \tViewFinder *viewfinder_;\n>  \n>  \tQIcon iconPlay_;\n> @@ -97,6 +100,7 @@ private:\n>  \t/* Capture state, buffers queue and statistics */\n>  \tbool isCapturing_;\n>  \tbool saveViewfinder_;\n> +\tbool captureRaw_;\n>  \tStream *vfStream_;\n>  \tStream *rawStream_;\n>  \tstd::map<Stream *, QQueue<FrameBuffer *>> freeBuffers_;","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 074BF613A8\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 30 Apr 2020 21:44:19 +0200 (CEST)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 77DC272C;\n\tThu, 30 Apr 2020 21:44:18 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"eW4G28gf\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1588275858;\n\tbh=qST6sgfHW0kwBW7aPXrLCoqcymc2xHBIwSPw11Og2ls=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=eW4G28gfRJWRneft/yqrH/Y9EaZ+W0JefmJhhsa5gkteyHfxChMEYrwFMYnL6nfGb\n\tIe8KoNBGSFfEj/3a4N5VwDeXR6L8jw6dCA3+PtYXjt5QzawN1AkczaxJG7uu5bbN0T\n\tzMcZt02bbWu+Xi21FVwqzlby4czdwXI6qQZhZ040=","Date":"Thu, 30 Apr 2020 22:44:17 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20200430194417.GW5856@pendragon.ideasonboard.com>","References":"<20200430003604.2423018-1-niklas.soderlund@ragnatech.se>\n\t<20200430003604.2423018-6-niklas.soderlund@ragnatech.se>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20200430003604.2423018-6-niklas.soderlund@ragnatech.se>","Subject":"Re: [libcamera-devel] [RFC/PATCH 5/5] qcam: Add RAW capture support","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Thu, 30 Apr 2020 19:44:19 -0000"}},{"id":4697,"web_url":"https://patchwork.libcamera.org/comment/4697/","msgid":"<20200501122943.GB2479064@oden.dyn.berto.se>","date":"2020-05-01T12:29:43","subject":"Re: [libcamera-devel] [RFC/PATCH 5/5] qcam: Add RAW capture support","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"Hi Laurent,\n\nThanks for your feedback.\n\nOn 2020-04-30 22:44:17 +0300, Laurent Pinchart wrote:\n> Hi Niklas,\n> \n> Thank you for the patch.\n> \n> On Thu, Apr 30, 2020 at 02:36:04AM +0200, Niklas Söderlund wrote:\n> > Add a toolbar button that captures RAW data to disk. The button is only\n> > enabled if the camera is configured to provide a raw stream to the\n> > application.\n> > \n> > Only when the capture action is triggered will a request with a raw\n> > buffer be queued to the camera.\n> > \n> > Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> > ---\n> >  src/qcam/assets/feathericons/feathericons.qrc |  1 +\n> >  src/qcam/main_window.cpp                      | 94 ++++++++++++++++++-\n> >  src/qcam/main_window.h                        |  4 +\n> >  3 files changed, 98 insertions(+), 1 deletion(-)\n> > \n> > diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc\n> > index c4eb7a0be6884373..fc8213928ece70ea 100644\n> > --- a/src/qcam/assets/feathericons/feathericons.qrc\n> > +++ b/src/qcam/assets/feathericons/feathericons.qrc\n> > @@ -1,5 +1,6 @@\n> >  <!DOCTYPE RCC><RCC version=\"1.0\">\n> >  <qresource>\n> > +<file>./aperture.svg</file>\n> >  <file>./camera-off.svg</file>\n> >  <file>./play-circle.svg</file>\n> >  <file>./save.svg</file>\n> > diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp\n> > index f57aaf4a27e5f4ca..535fa53d6705a1a9 100644\n> > --- a/src/qcam/main_window.cpp\n> > +++ b/src/qcam/main_window.cpp\n> > @@ -7,10 +7,13 @@\n> >  \n> >  #include \"main_window.h\"\n> >  \n> > +#include <fcntl.h>\n> >  #include <iomanip>\n> >  #include <sstream>\n> >  #include <string>\n> >  #include <sys/mman.h>\n> > +#include <sys/stat.h>\n> > +#include <unistd.h>\n> >  \n> >  #include <QComboBox>\n> >  #include <QCoreApplication>\n> > @@ -49,7 +52,8 @@ public:\n> >  };\n> >  \n> >  MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options)\n> > -\t: options_(options), cm_(cm), allocator_(nullptr), isCapturing_(false)\n> > +\t: options_(options), cm_(cm), allocator_(nullptr), isCapturing_(false),\n> > +\t  captureRaw_(false)\n> >  {\n> >  \tint ret;\n> >  \n> > @@ -149,6 +153,14 @@ int MainWindow::createToolbars()\n> >  \t\t\t\t     \"Save As...\");\n> >  \tconnect(action, &QAction::triggered, this, &MainWindow::saveViewfinder);\n> >  \n> > +\t/* Save Raw action. */\n> > +\taction = toolbar_->addAction(QIcon::fromTheme(\"document-save-as\",\n> \n> This will end up using the same icon as for the regulare image capture\n> on platforms whose theme offer document-save-as. Could we pick a\n> different one ?\n\nGood point.\n\n> \n> > +\t\t\t\t\t\t      QIcon(\":aperture.svg\")),\n> > +\t\t\t\t     \"Save Raw\");\n> > +\taction->setEnabled(false);\n> > +\tconnect(action, &QAction::triggered, this, &MainWindow::saveRaw);\n> > +\tsaveRaw_ = action;\n> > +\n> >  \treturn 0;\n> >  }\n> >  \n> > @@ -369,6 +381,9 @@ int MainWindow::startCapture()\n> >  \n> >  \tadjustSize();\n> >  \n> > +\t/* Configure the raw capture button. */\n> > +\tsaveRaw_->setEnabled(config_->size() == 2);\n> \n> Shouldn't the normal save button be enabled and disabled when starting\n> and stopping capture too ?\n\nMaybe but that is work for a different patch :-)\n\n> \n> > +\n> >  \t/* Allocate and map buffers. */\n> >  \tallocator_ = new FrameBufferAllocator(camera_);\n> >  \tfor (StreamConfiguration &config : *config_) {\n> > @@ -474,6 +489,7 @@ void MainWindow::stopCapture()\n> >  \t\treturn;\n> >  \n> >  \tviewfinder_->stop();\n> > +\tsaveRaw_->setEnabled(false);\n> >  \n> >  \tint ret = camera_->stop();\n> >  \tif (ret)\n> > @@ -514,6 +530,11 @@ void MainWindow::saveViewfinder()\n> >  \tsaveViewfinder_ = true;\n> >  }\n> >  \n> > +void MainWindow::saveRaw()\n> > +{\n> > +\tcaptureRaw_ = true;\n> > +}\n> > +\n> >  /* -----------------------------------------------------------------------------\n> >   * Request Completion Handling\n> >   */\n> > @@ -558,6 +579,9 @@ void MainWindow::processCapture()\n> >  \t\tif (buffers.count(vfStream_))\n> >  \t\t\tprocessViewfinder(buffers[vfStream_]);\n> >  \n> > +\t\tif (buffers.count(rawStream_))\n> > +\t\t\tprocessRaw(buffers[rawStream_]);\n> > +\n> >  \t\t/*\n> >  \t\t * Return buffers so they can be reused. No processing involving\n> >  \t\t * a buffer can happen after they are returned to the free list.\n> > @@ -618,6 +642,61 @@ void MainWindow::processViewfinder(FrameBuffer *buffer)\n> >  \t}\n> >  }\n> >  \n> > +void MainWindow::processRaw(FrameBuffer *raw)\n> \n> s/raw/buffer/ ?\n> \n> > +{\n> > +\t/* TODO: Should write a DNG file instead of a .raw and .jpeg file.  */\n> > +\n> > +\tunsigned int seq = raw->metadata().sequence;\n> > +\tstd::string filename;\n> > +\tint fd, ret = 0;\n> > +\tsize_t pos;\n> > +\n> > +\t/* Write .raw */\n> > +\tfilename = defaultPath_.toStdString() + \"/raw-#.raw\";\n> > +\tpos = filename.find_first_of('#');\n> > +\tif (pos != std::string::npos) {\n> > +\t\tstd::stringstream ss;\n> > +\t\tss << std::setw(6) << std::setfill('0') << seq;\n> > +\t\tfilename.replace(pos, 1, ss.str());\n> > +\t}\n> \n> Same comment as for the previous patch, use QString.\n> \n> > +\tqInfo() << \"Saving\" << filename.c_str();\n> > +\n> > +\tfd = open(filename.c_str(), O_CREAT | O_WRONLY |\n> > +\t\t  (pos == std::string::npos ? O_APPEND : O_TRUNC),\n> > +\t\t  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);\n> > +\tif (fd == -1) {\n> > +\t\tqWarning() << \"Failed to open raw output file\";\n> > +\t\treturn;\n> > +\t}\n> \n> And use QFile :-)\n> \n> > +\n> > +\tconst MappedBuffer &info = mappedBuffers_[raw];\n> > +\tret = ::write(fd, info.memory, info.size);\n> > +\tif (ret < 0) {\n> > +\t\tret = -errno;\n> > +\t\tqWarning() << \"write error: \" << strerror(-ret);\n> > +\t} else if (ret != (int)info.size) {\n> > +\t\tqWarning() << \"write error: only \" << ret\n> > +\t\t\t   << \" bytes written instead of \" << info.size;\n> > +\t}\n> > +\n> > +\t::close(fd);\n> > +\n> > +\t/* Write scaled thumbnail .jpeg */\n> > +\tfilename = defaultPath_.toStdString() + \"/raw-#.jpeg\";\n> > +\tpos = filename.find_first_of('#');\n> > +\tif (pos != std::string::npos) {\n> > +\t\tstd::stringstream ss;\n> > +\t\tss << std::setw(6) << std::setfill('0') << seq;\n> > +\t\tfilename.replace(pos, 1, ss.str());\n> > +\t}\n> > +\tqInfo() << \"Saving\" << filename.c_str();\n> > +\n> > +\tQImage image = viewfinder_->getCurrentImage().scaledToHeight(640);\n> \n> That's a big thumbnail. And a weird height value, did you mean\n> scaledToWidth(), or 480 instead of 640 ?\n> \n> > +\tQImageWriter writer(QString::fromUtf8(filename.c_str()));\n> > +\twriter.setQuality(95);\n> > +\twriter.write(image);\n> > +}\n> > +\n> >  void MainWindow::queueRequest(FrameBuffer *buffer)\n> >  {\n> >  \tRequest *request = camera_->createRequest();\n> > @@ -628,5 +707,18 @@ void MainWindow::queueRequest(FrameBuffer *buffer)\n> >  \n> >  \trequest->addBuffer(vfStream_, buffer);\n> >  \n> > +\tif (captureRaw_) {\n> > +\t\tQMutexLocker locker(&mutex_);\n> > +\n> > +\t\tif (freeBuffers_[rawStream_].isEmpty()) {\n> > +\t\t\tqWarning() << \"Raw stream buffer empty\";\n> > +\t\t\treturn;\n> \n> Shouldn't we still queue the request, without a raw buffer ?\n\nGood point!\n\n> \n> > +\t\t}\n> > +\n> > +\t\trequest->addBuffer(rawStream_,\n> > +\t\t\t\t   freeBuffers_[rawStream_].dequeue());\n> > +\t\tcaptureRaw_ = false;\n> > +\t}\n> > +\n> >  \tcamera_->queueRequest(request);\n> >  }\n> > diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h\n> > index 580bcac146fabe07..37a1d95351e144e0 100644\n> > --- a/src/qcam/main_window.h\n> > +++ b/src/qcam/main_window.h\n> > @@ -55,6 +55,7 @@ private Q_SLOTS:\n> >  \tvoid toggleCapture(bool start);\n> >  \n> >  \tvoid saveViewfinder();\n> > +\tvoid saveRaw();\n> >  \n> >  \tvoid queueRequest(FrameBuffer *buffer);\n> >  \n> > @@ -70,10 +71,12 @@ private:\n> >  \tvoid requestComplete(Request *request);\n> >  \tvoid processCapture();\n> >  \tvoid processViewfinder(FrameBuffer *buffer);\n> > +\tvoid processRaw(FrameBuffer *raw);\n> \n> s/raw/buffer/ ?\n> \n> >  \n> >  \t/* UI elements */\n> >  \tQToolBar *toolbar_;\n> >  \tQAction *startStopAction_;\n> > +\tQAction *saveRaw_;\n> >  \tViewFinder *viewfinder_;\n> >  \n> >  \tQIcon iconPlay_;\n> > @@ -97,6 +100,7 @@ private:\n> >  \t/* Capture state, buffers queue and statistics */\n> >  \tbool isCapturing_;\n> >  \tbool saveViewfinder_;\n> > +\tbool captureRaw_;\n> >  \tStream *vfStream_;\n> >  \tStream *rawStream_;\n> >  \tstd::map<Stream *, QQueue<FrameBuffer *>> freeBuffers_;\n> \n> -- \n> Regards,\n> \n> Laurent Pinchart","headers":{"Return-Path":"<niklas.soderlund@ragnatech.se>","Received":["from mail-lj1-x244.google.com (mail-lj1-x244.google.com\n\t[IPv6:2a00:1450:4864:20::244])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7788E603F3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri,  1 May 2020 14:29:45 +0200 (CEST)","by mail-lj1-x244.google.com with SMTP id u6so2457875ljl.6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 01 May 2020 05:29:45 -0700 (PDT)","from localhost (h-209-203.A463.priv.bahnhof.se. [155.4.209.203])\n\tby smtp.gmail.com with ESMTPSA id\n\tc21sm2142891lfh.16.2020.05.01.05.29.43\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tFri, 01 May 2020 05:29:43 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected)\n\theader.d=ragnatech-se.20150623.gappssmtp.com\n\theader.i=@ragnatech-se.20150623.gappssmtp.com header.b=\"LFzsOghP\"; \n\tdkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=ragnatech-se.20150623.gappssmtp.com; s=20150623;\n\th=date:from:to:cc:subject:message-id:references:mime-version\n\t:content-disposition:content-transfer-encoding:in-reply-to;\n\tbh=sWm1FyjTEfu2vQ8UD/5NbyRiPcaJqpsa3eWu+B+LRuU=;\n\tb=LFzsOghPd227zj8Vtk8D8nLvO4BUy80m9Ul5knp1ME5YVKta+zvKJJTj6iTRqdvt8n\n\tgwtEUZJvEo8YgJPgjqLj3TTMyMzbOk+jmztyfvHmpzaGouzwYZZbYhJ6UVRe5TFSZlvb\n\t66O4psEXVpOBmbsqQ1WxbZfOh/AytaVYN0YaGzSt+u3R6FsVx2Ol2aRbL+30QLfYCTH1\n\tB9KS1GfpCMfrVIPV/uCBOwMgBAWBVyjj3h3vwJSc9tFwx+LGfSateDQrkd7BhD6Rc62R\n\tX3ChTwTpMJ89WyXuUL+a7vZ+EourTSV5GS7RjgmsZZ8Dqd0gGasiXMlPh3R0KaeEXD/l\n\tSNLw==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:content-transfer-encoding\n\t:in-reply-to;\n\tbh=sWm1FyjTEfu2vQ8UD/5NbyRiPcaJqpsa3eWu+B+LRuU=;\n\tb=gbvdB5fx/7fKM0G1NBjtfItb/mM2ppR49xi6E0lvGDKvBwVtivegGWFH+zEqRI9SwT\n\txwmix7DklGBJZ/ATwOGW93WMGLxuHsnuLYxu/l/Ioi3YKtRb1x8u0ENZQc9lmNxBdgvV\n\tTW8h3tghnd2oVyFXxEyz8pQo79NsaT24fi3Aaqh5VrtsRK3wPW4o0G9T7/4Kt7JuQMwJ\n\tAD1C5hBab81jOpaZBg9l2R0UfpHAp6FEHhKmhM2fXRO0oCBX8mPeBto80HoaV9oGATiu\n\tAaZNDe/xYjh/JTKiDXtyuB2ornfYBWSKYcQOcCHkX/PdUXqi6bMvyHpf5US/DelUBH02\n\tWIIA==","X-Gm-Message-State":"AGi0PuZS71NlXxfqThMoCSvVH2T0HSOzH8m5EmcN6T0z7bRfG94SsrtC\n\tBv7cmB9VCmy/xqFIphhpMGQw4ofpiqQ=","X-Google-Smtp-Source":"APiQypK7LyeYY7sduJiXluotJsmDTzv3PUp9RCoNG5G3GSjKbc2JMHqr9hyucE6WkccyNKSnTeWRbg==","X-Received":"by 2002:a2e:81d5:: with SMTP id\n\ts21mr2267680ljg.258.1588336184753; \n\tFri, 01 May 2020 05:29:44 -0700 (PDT)","Date":"Fri, 1 May 2020 14:29:43 +0200","From":"Niklas =?iso-8859-1?q?S=F6derlund?= <niklas.soderlund@ragnatech.se>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20200501122943.GB2479064@oden.dyn.berto.se>","References":"<20200430003604.2423018-1-niklas.soderlund@ragnatech.se>\n\t<20200430003604.2423018-6-niklas.soderlund@ragnatech.se>\n\t<20200430194417.GW5856@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20200430194417.GW5856@pendragon.ideasonboard.com>","Subject":"Re: [libcamera-devel] [RFC/PATCH 5/5] qcam: Add RAW capture support","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Fri, 01 May 2020 12:29:45 -0000"}}]