Message ID | 20200323142205.28342-21-laurent.pinchart@ideasonboard.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
Hi Laurent, On 23/03/2020 14:22, Laurent Pinchart wrote: > When stopping capture, display an icon instead of the last frame. This > is required to be able to release the last buffer when the viewfinder > operators in zero-copy mode. This is actually really nice because it displays an icon when streams fail to start (I have a secondary IR camera on my laptop which is not supported, and this icon shows up if I try to stream that camera). However, it does remove a 'feature' that I had before, where we could 'pause' a running stream and have the last image still visible which could be useful when trying to catch a picture to save perhaps. But in general, I think this is a really good feature, and displaying an icon for a stream which can't run is more valuable than a pause feature which could be added later... Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > --- > src/qcam/assets/feathericons/feathericons.qrc | 1 + > src/qcam/main_window.cpp | 2 + > src/qcam/viewfinder.cpp | 44 ++++++++++++++++++- > src/qcam/viewfinder.h | 8 ++++ > 4 files changed, 54 insertions(+), 1 deletion(-) > > diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc > index 6ca3a846803c..c4eb7a0be688 100644 > --- a/src/qcam/assets/feathericons/feathericons.qrc > +++ b/src/qcam/assets/feathericons/feathericons.qrc > @@ -1,5 +1,6 @@ > <!DOCTYPE RCC><RCC version="1.0"> > <qresource> > +<file>./camera-off.svg</file> > <file>./play-circle.svg</file> > <file>./save.svg</file> > <file>./stop-circle.svg</file> > diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp > index b68e171c5e01..a77d10bb7076 100644 > --- a/src/qcam/main_window.cpp > +++ b/src/qcam/main_window.cpp > @@ -412,6 +412,8 @@ void MainWindow::stopCapture() > if (!isCapturing_) > return; > > + viewfinder_->stop(); > + > int ret = camera_->stop(); > if (ret) > qInfo() << "Failed to stop capture"; > diff --git a/src/qcam/viewfinder.cpp b/src/qcam/viewfinder.cpp > index 4c35659e24aa..a40b2b400daa 100644 > --- a/src/qcam/viewfinder.cpp > +++ b/src/qcam/viewfinder.cpp > @@ -20,6 +20,7 @@ > ViewFinder::ViewFinder(QWidget *parent) > : QWidget(parent), buffer_(nullptr) > { > + icon_ = QIcon(":camera-off.svg"); > } > > ViewFinder::~ViewFinder() > @@ -89,6 +90,18 @@ void ViewFinder::render(libcamera::FrameBuffer *buffer, MappedBuffer *map) > renderComplete(buffer); > } > > +void ViewFinder::stop() > +{ > + image_ = QImage(); > + > + if (buffer_) { > + renderComplete(buffer_); > + buffer_ = nullptr; > + } > + > + update(); > +} > + > QImage ViewFinder::getCurrentImage() > { > QMutexLocker locker(&mutex_); > @@ -99,7 +112,36 @@ QImage ViewFinder::getCurrentImage() > void ViewFinder::paintEvent(QPaintEvent *) > { > QPainter painter(this); > - painter.drawImage(rect(), image_, image_.rect()); > + > + /* If we have an image, draw it. */ > + if (!image_.isNull()) { > + painter.drawImage(rect(), image_, image_.rect()); > + return; > + } > + > + /* > + * Otherwise, draw the camera stopped icon. Render it to the pixmap if > + * the size has changed. > + */ > + constexpr int margin = 20; > + > + if (vfSize_ != size() || pixmap_.isNull()) { > + vfSize_ = size(); > + > + QSize pixmapSize{ 1, 1 }; > + pixmapSize.scale(vfSize_.shrunkBy({ margin, margin, margin, margin }), shrunkBy fails to compile on QT 5.12.2 ... but you already know (and have fixed) that... > + Qt::KeepAspectRatio); > + pixmap_ = icon_.pixmap(pixmapSize); > + } > + > + QPoint point{ margin, margin }; > + if (pixmap_.width() < width() - 2 * margin) > + point.setX((width() - pixmap_.width()) / 2); > + else > + point.setY((height() - pixmap_.height()) / 2); > + > + painter.setBackgroundMode(Qt::OpaqueMode); > + painter.drawPixmap(point, pixmap_); > } > > QSize ViewFinder::sizeHint() const > diff --git a/src/qcam/viewfinder.h b/src/qcam/viewfinder.h > index b5153160f70e..1a27f99ea202 100644 > --- a/src/qcam/viewfinder.h > +++ b/src/qcam/viewfinder.h > @@ -9,6 +9,7 @@ > > #include <stddef.h> > > +#include <QIcon> > #include <QImage> > #include <QMutex> > #include <QSize> > @@ -36,6 +37,7 @@ public: > > int setFormat(const libcamera::PixelFormat &format, const QSize &size); > void render(libcamera::FrameBuffer *buffer, MappedBuffer *map); > + void stop(); > > QImage getCurrentImage(); > > @@ -52,6 +54,12 @@ private: > libcamera::PixelFormat format_; > QSize size_; > > + /* Camera stopped icon */ > + QSize vfSize_; > + QIcon icon_; > + QPixmap pixmap_; > + > + /* Buffer and render image */ > libcamera::FrameBuffer *buffer_; > QImage image_; > QMutex mutex_; /* Prevent concurrent access to image_ */ >
Hi Kieran, On Mon, Mar 23, 2020 at 05:28:05PM +0000, Kieran Bingham wrote: > On 23/03/2020 14:22, Laurent Pinchart wrote: > > When stopping capture, display an icon instead of the last frame. This > > is required to be able to release the last buffer when the viewfinder > > operators in zero-copy mode. > > This is actually really nice because it displays an icon when streams > fail to start (I have a secondary IR camera on my laptop which is not > supported, and this icon shows up if I try to stream that camera). > > However, it does remove a 'feature' that I had before, where we could > 'pause' a running stream and have the last image still visible which > could be useful when trying to catch a picture to save perhaps. > > But in general, I think this is a really good feature, and displaying an > icon for a stream which can't run is more valuable than a pause feature > which could be added later... I agree with you, let's take a bit of time to design the pause feature correctly on top of this. > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > --- > > src/qcam/assets/feathericons/feathericons.qrc | 1 + > > src/qcam/main_window.cpp | 2 + > > src/qcam/viewfinder.cpp | 44 ++++++++++++++++++- > > src/qcam/viewfinder.h | 8 ++++ > > 4 files changed, 54 insertions(+), 1 deletion(-) > > > > diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc > > index 6ca3a846803c..c4eb7a0be688 100644 > > --- a/src/qcam/assets/feathericons/feathericons.qrc > > +++ b/src/qcam/assets/feathericons/feathericons.qrc > > @@ -1,5 +1,6 @@ > > <!DOCTYPE RCC><RCC version="1.0"> > > <qresource> > > +<file>./camera-off.svg</file> > > <file>./play-circle.svg</file> > > <file>./save.svg</file> > > <file>./stop-circle.svg</file> > > diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp > > index b68e171c5e01..a77d10bb7076 100644 > > --- a/src/qcam/main_window.cpp > > +++ b/src/qcam/main_window.cpp > > @@ -412,6 +412,8 @@ void MainWindow::stopCapture() > > if (!isCapturing_) > > return; > > > > + viewfinder_->stop(); > > + > > int ret = camera_->stop(); > > if (ret) > > qInfo() << "Failed to stop capture"; > > diff --git a/src/qcam/viewfinder.cpp b/src/qcam/viewfinder.cpp > > index 4c35659e24aa..a40b2b400daa 100644 > > --- a/src/qcam/viewfinder.cpp > > +++ b/src/qcam/viewfinder.cpp > > @@ -20,6 +20,7 @@ > > ViewFinder::ViewFinder(QWidget *parent) > > : QWidget(parent), buffer_(nullptr) > > { > > + icon_ = QIcon(":camera-off.svg"); > > } > > > > ViewFinder::~ViewFinder() > > @@ -89,6 +90,18 @@ void ViewFinder::render(libcamera::FrameBuffer *buffer, MappedBuffer *map) > > renderComplete(buffer); > > } > > > > +void ViewFinder::stop() > > +{ > > + image_ = QImage(); > > + > > + if (buffer_) { > > + renderComplete(buffer_); > > + buffer_ = nullptr; > > + } > > + > > + update(); > > +} > > + > > QImage ViewFinder::getCurrentImage() > > { > > QMutexLocker locker(&mutex_); > > @@ -99,7 +112,36 @@ QImage ViewFinder::getCurrentImage() > > void ViewFinder::paintEvent(QPaintEvent *) > > { > > QPainter painter(this); > > - painter.drawImage(rect(), image_, image_.rect()); > > + > > + /* If we have an image, draw it. */ > > + if (!image_.isNull()) { > > + painter.drawImage(rect(), image_, image_.rect()); > > + return; > > + } > > + > > + /* > > + * Otherwise, draw the camera stopped icon. Render it to the pixmap if > > + * the size has changed. > > + */ > > + constexpr int margin = 20; > > + > > + if (vfSize_ != size() || pixmap_.isNull()) { > > + vfSize_ = size(); > > + > > + QSize pixmapSize{ 1, 1 }; > > + pixmapSize.scale(vfSize_.shrunkBy({ margin, margin, margin, margin }), > > shrunkBy fails to compile on QT 5.12.2 ... but you already know (and > have fixed) that... > > > + Qt::KeepAspectRatio); > > + pixmap_ = icon_.pixmap(pixmapSize); > > + } > > + > > + QPoint point{ margin, margin }; > > + if (pixmap_.width() < width() - 2 * margin) > > + point.setX((width() - pixmap_.width()) / 2); > > + else > > + point.setY((height() - pixmap_.height()) / 2); > > + > > + painter.setBackgroundMode(Qt::OpaqueMode); > > + painter.drawPixmap(point, pixmap_); > > } > > > > QSize ViewFinder::sizeHint() const > > diff --git a/src/qcam/viewfinder.h b/src/qcam/viewfinder.h > > index b5153160f70e..1a27f99ea202 100644 > > --- a/src/qcam/viewfinder.h > > +++ b/src/qcam/viewfinder.h > > @@ -9,6 +9,7 @@ > > > > #include <stddef.h> > > > > +#include <QIcon> > > #include <QImage> > > #include <QMutex> > > #include <QSize> > > @@ -36,6 +37,7 @@ public: > > > > int setFormat(const libcamera::PixelFormat &format, const QSize &size); > > void render(libcamera::FrameBuffer *buffer, MappedBuffer *map); > > + void stop(); > > > > QImage getCurrentImage(); > > > > @@ -52,6 +54,12 @@ private: > > libcamera::PixelFormat format_; > > QSize size_; > > > > + /* Camera stopped icon */ > > + QSize vfSize_; > > + QIcon icon_; > > + QPixmap pixmap_; > > + > > + /* Buffer and render image */ > > libcamera::FrameBuffer *buffer_; > > QImage image_; > > QMutex mutex_; /* Prevent concurrent access to image_ */
diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc index 6ca3a846803c..c4eb7a0be688 100644 --- a/src/qcam/assets/feathericons/feathericons.qrc +++ b/src/qcam/assets/feathericons/feathericons.qrc @@ -1,5 +1,6 @@ <!DOCTYPE RCC><RCC version="1.0"> <qresource> +<file>./camera-off.svg</file> <file>./play-circle.svg</file> <file>./save.svg</file> <file>./stop-circle.svg</file> diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index b68e171c5e01..a77d10bb7076 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -412,6 +412,8 @@ void MainWindow::stopCapture() if (!isCapturing_) return; + viewfinder_->stop(); + int ret = camera_->stop(); if (ret) qInfo() << "Failed to stop capture"; diff --git a/src/qcam/viewfinder.cpp b/src/qcam/viewfinder.cpp index 4c35659e24aa..a40b2b400daa 100644 --- a/src/qcam/viewfinder.cpp +++ b/src/qcam/viewfinder.cpp @@ -20,6 +20,7 @@ ViewFinder::ViewFinder(QWidget *parent) : QWidget(parent), buffer_(nullptr) { + icon_ = QIcon(":camera-off.svg"); } ViewFinder::~ViewFinder() @@ -89,6 +90,18 @@ void ViewFinder::render(libcamera::FrameBuffer *buffer, MappedBuffer *map) renderComplete(buffer); } +void ViewFinder::stop() +{ + image_ = QImage(); + + if (buffer_) { + renderComplete(buffer_); + buffer_ = nullptr; + } + + update(); +} + QImage ViewFinder::getCurrentImage() { QMutexLocker locker(&mutex_); @@ -99,7 +112,36 @@ QImage ViewFinder::getCurrentImage() void ViewFinder::paintEvent(QPaintEvent *) { QPainter painter(this); - painter.drawImage(rect(), image_, image_.rect()); + + /* If we have an image, draw it. */ + if (!image_.isNull()) { + painter.drawImage(rect(), image_, image_.rect()); + return; + } + + /* + * Otherwise, draw the camera stopped icon. Render it to the pixmap if + * the size has changed. + */ + constexpr int margin = 20; + + if (vfSize_ != size() || pixmap_.isNull()) { + vfSize_ = size(); + + QSize pixmapSize{ 1, 1 }; + pixmapSize.scale(vfSize_.shrunkBy({ margin, margin, margin, margin }), + Qt::KeepAspectRatio); + pixmap_ = icon_.pixmap(pixmapSize); + } + + QPoint point{ margin, margin }; + if (pixmap_.width() < width() - 2 * margin) + point.setX((width() - pixmap_.width()) / 2); + else + point.setY((height() - pixmap_.height()) / 2); + + painter.setBackgroundMode(Qt::OpaqueMode); + painter.drawPixmap(point, pixmap_); } QSize ViewFinder::sizeHint() const diff --git a/src/qcam/viewfinder.h b/src/qcam/viewfinder.h index b5153160f70e..1a27f99ea202 100644 --- a/src/qcam/viewfinder.h +++ b/src/qcam/viewfinder.h @@ -9,6 +9,7 @@ #include <stddef.h> +#include <QIcon> #include <QImage> #include <QMutex> #include <QSize> @@ -36,6 +37,7 @@ public: int setFormat(const libcamera::PixelFormat &format, const QSize &size); void render(libcamera::FrameBuffer *buffer, MappedBuffer *map); + void stop(); QImage getCurrentImage(); @@ -52,6 +54,12 @@ private: libcamera::PixelFormat format_; QSize size_; + /* Camera stopped icon */ + QSize vfSize_; + QIcon icon_; + QPixmap pixmap_; + + /* Buffer and render image */ libcamera::FrameBuffer *buffer_; QImage image_; QMutex mutex_; /* Prevent concurrent access to image_ */
When stopping capture, display an icon instead of the last frame. This is required to be able to release the last buffer when the viewfinder operators in zero-copy mode. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> --- src/qcam/assets/feathericons/feathericons.qrc | 1 + src/qcam/main_window.cpp | 2 + src/qcam/viewfinder.cpp | 44 ++++++++++++++++++- src/qcam/viewfinder.h | 8 ++++ 4 files changed, 54 insertions(+), 1 deletion(-)