6#include <QtMultimedia/private/qplatformcamera_p.h>
7#include <QtMultimedia/private/qplatformimagecapture_p.h>
8#include <QtMultimedia/qvideoframeformat.h>
9#include <QtMultimedia/private/qmediastoragelocation_p.h>
10#include <QtCore/qdebug.h>
11#include <QtCore/qdir.h>
12#include <QtCore/qstandardpaths.h>
13#include <QtCore/qloggingcategory.h>
47 videoConvert(
std::move(videoconvert)),
48 encoder(
std::move(jpegenc)),
49 muxer(
std::move(jifmux))
55 queue.set(
"leaky", 2 );
56 queue.set(
"silent",
true);
65 sink.set(
"async",
false);
71 addProbeToPad(
queue.staticPad(
"src").pad(),
false);
73 sink.set(
"signal-handoffs",
true);
74 m_handoffConnection =
sink.connect(
"handoff", G_CALLBACK(&saveImageFilter),
this);
82 auto pendingFutures = [&] {
84 return std::move(m_pendingFutures);
87 for (QFuture<void> &pendingImage : pendingFutures)
88 pendingImage.waitForFinished();
94 return m_session && !passImage && cameraActive;
102 return doCapture(
path);
112 qCDebug(qLcImageCaptureGst) <<
"do capture";
117 invokeDeferred([
this] {
122 qCDebug(qLcImageCaptureGst) <<
"error 1";
125 if (!m_session->
camera()) {
126 invokeDeferred([
this] {
130 qCDebug(qLcImageCaptureGst) <<
"error 2";
134 invokeDeferred([
this] {
139 qCDebug(qLcImageCaptureGst) <<
"error 3";
153void QGstreamerImageCapture::setResolution(
const QSize &resolution)
156 if (padCaps.isNull()) {
157 qDebug() <<
"Camera not ready";
164 gst_caps_set_simple(caps.
caps(),
"width", G_TYPE_INT, resolution.
width(),
"height", G_TYPE_INT,
165 resolution.
height(),
nullptr);
170#if __cplusplus >= 202002L
171# define EQ_THIS_CAPTURE =, this
173# define EQ_THIS_CAPTURE =
182 qCDebug(qLcImageCaptureGst) <<
"probe buffer";
192 invokeDeferred([
this, ready] {
197 auto memoryFormat = caps.memoryFormat();
199 GstVideoInfo previewInfo;
201 auto optionalFormatAndVideoInfo = caps.formatAndVideoInfo();
202 if (optionalFormatAndVideoInfo)
203 std::tie(
fmt, previewInfo) = std::move(*optionalFormatAndVideoInfo);
205 int futureId = futureIDAllocator += 1;
212 m_pendingFutures.
remove(futureId);
216 qDebug() <<
"QGstreamerImageCapture::probeBuffer: no session";
222 std::move(bufferHandle), previewInfo,
sink,
fmt, memoryFormat,
228 qDebug() <<
"received a null image";
234 pendingImages.
head().metaData = std::move(imageMetaData);
235 PendingImage pendingImage = pendingImages.
head();
237 invokeDeferred([
this, pendingImage = std::move(pendingImage),
frame = std::move(
frame),
238 img = std::move(
img)]()
mutable {
240 qCDebug(qLcImageCaptureGst) <<
"Image available!";
252#undef EQ_THIS_CAPTURE
258 if (m_session == captureSession)
263 disconnect(m_session,
nullptr,
this,
nullptr);
265 pendingImages.
clear();
267 cameraActive =
false;
270 m_session = captureSession;
295 qCDebug(qLcImageCaptureGst) <<
"cameraActiveChanged" << cameraActive << active;
296 if (cameraActive == active)
298 cameraActive = active;
306 if (m_session->
camera()) {
315gboolean QGstreamerImageCapture::saveImageFilter(GstElement *, GstBuffer *
buffer, GstPad *,
322void QGstreamerImageCapture::saveBufferToImage(GstBuffer *
buffer)
334 int id = futureIDAllocator++;
344 m_pendingFutures.
remove(
id);
351 qCDebug(qLcImageCaptureGst) <<
" could not open image file for writing";
356 GstBuffer *
buffer = bufferHandle.get();
357 if (gst_buffer_map(
buffer, &
info, GST_MAP_READ)) {
358 f.write(
reinterpret_cast<const char *
>(
info.data),
info.size);
368 m_pendingFutures.
insert(
id, saveImageFuture);
381 setResolution(resolution);
389#include "moc_qgstreamerimagecapture_p.cpp"
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
static QGstBin create(const char *name)
bool setStateSync(GstState state, std::chrono::nanoseconds timeout=std::chrono::seconds(1))
QGstPad staticPad(const char *name) const
static QGstElement createFromFactory(const char *factory, const char *name=nullptr)
QGstCaps currentCaps() const
int capture(const QString &fileName) override
bool isReadyForCapture() const override
virtual ~QGstreamerImageCapture()
bool probeBuffer(GstBuffer *buffer) override
QImageEncoderSettings imageSettings() const override
int captureToBuffer() override
void setImageSettings(const QImageEncoderSettings &settings) override
void cameraActiveChanged(bool active)
void setMetaData(const QMediaMetaData &m) override
void setCaptureSession(QPlatformMediaCaptureSession *session)
bool isEmpty() const noexcept
iterator insert(const Key &key, const T &value)
size_type remove(const Key &key)
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
void enqueue(const T &t)
Adds value t to the tail of the queue.
T & head()
Returns a reference to the queue's head item.
T dequeue()
Removes the head item in the queue and returns it.
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
\macro QT_RESTRICTED_CAST_FROM_ASCII
The QVideoFrame class represents a frame of video data.
Combined button and popup list for selecting options.
QTCONCURRENT_RUN_NODISCARD auto run(QThreadPool *pool, Function &&f, Args &&...args)
QTextStream & bin(QTextStream &stream)
Calls QTextStream::setIntegerBase(2) on stream and returns stream.
DBusConnection const char DBusError * error
std::enable_if_t<(std::is_base_of_v< QGstElement, Ts > &&...), void qLinkGstElements)(const Ts &...ts)
QString errorMessageCannotFindElement(std::string_view element)
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLsizei const GLchar *const * path
GLsizei GLenum GLboolean sink
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
unsigned long long quint64
QVideoFrameFormat::PixelFormat fmt
QFuture< void > future
[5]
QSettings settings("MySoft", "Star Runner")
[0]
myObject disconnect()
[26]