summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/multimedia/camera/qcameraimagecapture.cpp42
-rw-r--r--src/multimedia/platform/darwin/camera/avfcameraimagecapture.mm83
-rw-r--r--src/multimedia/platform/darwin/camera/avfcameraimagecapture_p.h16
-rw-r--r--src/multimedia/platform/darwin/camera/avfcamerarenderer.mm1
-rw-r--r--src/multimedia/platform/darwin/camera/avfcamerarenderer_p.h3
-rw-r--r--src/multimedia/platform/darwin/camera/avfcameraservice.mm27
-rw-r--r--src/multimedia/platform/darwin/camera/avfcameraservice_p.h5
-rw-r--r--src/multimedia/platform/darwin/camera/avfcamerasession_p.h1
-rw-r--r--src/multimedia/platform/darwin/qdarwinintegration.cpp5
-rw-r--r--src/multimedia/platform/darwin/qdarwinintegration_p.h2
-rw-r--r--src/multimedia/platform/gstreamer/mediacapture/qgstreamercameraimagecapture.cpp69
-rw-r--r--src/multimedia/platform/gstreamer/mediacapture/qgstreamercameraimagecapture_p.h8
-rw-r--r--src/multimedia/platform/gstreamer/mediacapture/qgstreamermediacapture.cpp33
-rw-r--r--src/multimedia/platform/gstreamer/mediacapture/qgstreamermediacapture_p.h2
-rw-r--r--src/multimedia/platform/gstreamer/qgstreamerintegration.cpp4
-rw-r--r--src/multimedia/platform/gstreamer/qgstreamerintegration_p.h2
-rw-r--r--src/multimedia/platform/qplatformcameraimagecapture.cpp5
-rw-r--r--src/multimedia/platform/qplatformcameraimagecapture_p.h8
-rw-r--r--src/multimedia/platform/qplatformmediacapture_p.h3
-rw-r--r--src/multimedia/platform/qplatformmediaintegration_p.h4
-rw-r--r--src/multimediaquick/qtmultimediaquicktypes_p.h2
-rw-r--r--tests/auto/unit/mockbackend/qmockimagecapture.cpp9
-rw-r--r--tests/auto/unit/mockbackend/qmockimagecapture.h13
-rw-r--r--tests/auto/unit/mockbackend/qmockintegration.cpp6
-rw-r--r--tests/auto/unit/mockbackend/qmockintegration_p.h2
-rw-r--r--tests/auto/unit/mockbackend/qmockmediacapturesession.h9
-rw-r--r--tests/auto/unit/multimedia/qcameraimagecapture/tst_qcameraimagecapture.cpp10
27 files changed, 262 insertions, 112 deletions
diff --git a/src/multimedia/camera/qcameraimagecapture.cpp b/src/multimedia/camera/qcameraimagecapture.cpp
index 384d43fbf..31b5d002c 100644
--- a/src/multimedia/camera/qcameraimagecapture.cpp
+++ b/src/multimedia/camera/qcameraimagecapture.cpp
@@ -41,6 +41,7 @@
#include <qmediaencodersettings.h>
#include <qmediametadata.h>
#include <private/qplatformmediacapture_p.h>
+#include <private/qplatformmediaintegration_p.h>
#include <qmediacapturesession.h>
#include "private/qobject_p.h"
@@ -115,6 +116,7 @@ QCameraImageCapture::QCameraImageCapture(QObject *parent)
{
Q_D(QCameraImageCapture);
d->q_ptr = this;
+ d->control = QPlatformMediaIntegration::instance()->createImageCapture(this);
}
void QCameraImageCapture::setCaptureSession(QMediaCaptureSession *session)
@@ -122,15 +124,13 @@ void QCameraImageCapture::setCaptureSession(QMediaCaptureSession *session)
Q_D(QCameraImageCapture);
d->captureSession = session;
- if (!session) {
- d->control = nullptr;
- return;
- }
+ QPlatformMediaCaptureSession *platformSession = session ? session->platformSession() : nullptr;
- d->control = session->platformSession()->imageCapture();
-
- if (!d->control)
+ if (platformSession && d->control) {
+ platformSession->setImageCapture(d->control);
+ } else {
return;
+ }
connect(d->control, SIGNAL(imageExposed(int)),
this, SIGNAL(imageExposed(int)));
@@ -155,7 +155,7 @@ void QCameraImageCapture::setCaptureSession(QMediaCaptureSession *session)
QCameraImageCapture::~QCameraImageCapture()
{
if (d_ptr->captureSession) {
- //d_ptr->captureSession->platformSession()->releaseImageCapture(d_ptr->control);
+ d_ptr->captureSession->platformSession()->setImageCapture(nullptr);
d_ptr->captureSession->setImageCapture(nullptr);
}
delete d_ptr;
@@ -258,9 +258,13 @@ void QCameraImageCapture::addMetaData(const QMediaMetaData &metaData)
bool QCameraImageCapture::isReadyForCapture() const
{
- if (d_func()->control)
- return d_func()->control->isReadyForCapture();
- return false;
+ Q_D(const QCameraImageCapture);
+ if (!d->control || !d->captureSession || !d->control->isReadyForCapture())
+ return false;
+ auto *camera = d->captureSession->camera();
+ if (!camera || !camera->isActive())
+ return false;
+ return true;
}
/*!
@@ -297,15 +301,17 @@ int QCameraImageCapture::captureToFile(const QString &file)
d->unsetError();
- if (d->control)
- return d->control->capture(file);
-
- d->error = NotSupportedFeatureError;
- d->errorString = tr("Device does not support images capture.");
+ if (!d->control) {
+ d->_q_error(-1, NotSupportedFeatureError, tr("Camera is not ready."));
+ return -1;
+ }
- d->_q_error(-1, d->error, d->errorString);
+ if (!isReadyForCapture()) {
+ d->_q_error(-1, NotReadyError, tr("Could not capture in stopped state"));
+ return -1;
+ }
- return -1;
+ return d->control->capture(file);
}
/*!
diff --git a/src/multimedia/platform/darwin/camera/avfcameraimagecapture.mm b/src/multimedia/platform/darwin/camera/avfcameraimagecapture.mm
index 9d04fb3f4..684678471 100644
--- a/src/multimedia/platform/darwin/camera/avfcameraimagecapture.mm
+++ b/src/multimedia/platform/darwin/camera/avfcameraimagecapture.mm
@@ -42,6 +42,8 @@
#include "avfcameraservice_p.h"
#include "avfcamerautility_p.h"
#include "avfcamera_p.h"
+#include "avfcamerasession_p.h"
+#include "avfcamerarenderer_p.h"
#include <private/qmemoryvideobuffer_p.h>
#include <QtCore/qurl.h>
@@ -50,18 +52,16 @@
#include <QtConcurrent/qtconcurrentrun.h>
#include <QtGui/qimagereader.h>
+#import <AVFoundation/AVFoundation.h>
+
QT_USE_NAMESPACE
-AVFCameraImageCapture::AVFCameraImageCapture(AVFCameraService *service, QObject *parent)
+AVFCameraImageCapture::AVFCameraImageCapture(QCameraImageCapture *parent)
: QPlatformCameraImageCapture(parent)
- , m_service(service)
- , m_session(service->session())
- , m_cameraControl(service->avfCameraControl())
, m_ready(false)
, m_lastCaptureId(0)
, m_videoConnection(nil)
{
- Q_UNUSED(service);
m_stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:
@@ -69,13 +69,6 @@ AVFCameraImageCapture::AVFCameraImageCapture(AVFCameraService *service, QObject
[m_stillImageOutput setOutputSettings:outputSettings];
[outputSettings release];
- connect(m_cameraControl, SIGNAL(statusChanged(QCamera::Status)), SLOT(updateReadyStatus()));
-
- connect(m_session, SIGNAL(readyToConfigureConnections()), SLOT(updateCaptureConnection()));
-
- connect(m_session, &AVFCameraSession::newViewfinderFrame,
- this, &AVFCameraImageCapture::onNewViewfinderFrame,
- Qt::DirectConnection);
}
AVFCameraImageCapture::~AVFCameraImageCapture()
@@ -84,7 +77,7 @@ AVFCameraImageCapture::~AVFCameraImageCapture()
bool AVFCameraImageCapture::isReadyForCapture() const
{
- return m_videoConnection && m_cameraControl->status() == QCamera::ActiveStatus;
+ return m_cameraControl && m_videoConnection && m_cameraControl->status() == QCamera::ActiveStatus;
}
void AVFCameraImageCapture::updateReadyStatus()
@@ -98,7 +91,13 @@ void AVFCameraImageCapture::updateReadyStatus()
int AVFCameraImageCapture::doCapture(const QString &actualFileName)
{
-
+ if (!m_session) {
+ QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ Q_ARG(int, m_lastCaptureId),
+ Q_ARG(int, QCameraImageCapture::ResourceError),
+ Q_ARG(QString, tr("Image capture not set to capture session")));
+ return m_lastCaptureId;
+ }
if (!isReadyForCapture()) {
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(int, m_lastCaptureId),
@@ -115,6 +114,8 @@ int AVFCameraImageCapture::doCapture(const QString &actualFileName)
m_captureRequests.enqueue(request);
m_requestsMutex.unlock();
+ QString fileName(actualFileName);
+
[m_stillImageOutput captureStillImageAsynchronouslyFromConnection:m_videoConnection
completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
@@ -159,12 +160,12 @@ int AVFCameraImageCapture::doCapture(const QString &actualFileName)
Q_ARG(int, request.captureId),
Q_ARG(QVideoFrame, frame));
} else {
- QFile f(actualFileName);
+ QFile f(fileName);
if (f.open(QFile::WriteOnly)) {
if (f.write(jpgData) != -1) {
QMetaObject::invokeMethod(this, "imageSaved", Qt::QueuedConnection,
Q_ARG(int, request.captureId),
- Q_ARG(QString, actualFileName));
+ Q_ARG(QString, fileName));
} else {
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(int, request.captureId),
@@ -172,7 +173,7 @@ int AVFCameraImageCapture::doCapture(const QString &actualFileName)
Q_ARG(QString, f.errorString()));
}
} else {
- QString errorMessage = tr("Could not open destination file:\n%1").arg(actualFileName);
+ QString errorMessage = tr("Could not open destination file:\n%1").arg(fileName);
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(int, request.captureId),
Q_ARG(int, QCameraImageCapture::ResourceError),
@@ -226,6 +227,15 @@ void AVFCameraImageCapture::onNewViewfinderFrame(const QVideoFrame &frame)
0 /* rotation */);
}
+void AVFCameraImageCapture::onCameraChanged()
+{
+ Q_ASSERT(m_service);
+ if (m_service->camera()) {
+ m_cameraControl = static_cast<AVFCamera *>(m_service->camera());
+ connect(m_cameraControl, SIGNAL(statusChanged(QCamera::Status)), this, SLOT(updateReadyStatus()));
+ }
+}
+
void AVFCameraImageCapture::makeCapturePreview(CaptureRequest request,
const QVideoFrame &frame,
int rotation)
@@ -240,7 +250,7 @@ void AVFCameraImageCapture::makeCapturePreview(CaptureRequest request,
void AVFCameraImageCapture::updateCaptureConnection()
{
- if (m_session->videoCaptureDevice()) {
+ if (m_session && m_session->videoCaptureDevice()) {
qDebugCamera() << Q_FUNC_INFO;
AVCaptureSession *captureSession = m_session->captureSession();
@@ -361,9 +371,44 @@ bool AVFCameraImageCapture::applySettings()
return activeFormatChanged;
}
+void AVFCameraImageCapture::setCaptureSession(QPlatformMediaCaptureSession *session)
+{
+ AVFCameraService *captureSession = static_cast<AVFCameraService *>(session);
+ if (m_service == captureSession)
+ return;
+
+ m_service = captureSession;
+ if (!m_service) {
+ disconnect(m_session, nullptr, this, nullptr);
+ disconnect(m_session->videoOutput(), nullptr, this, nullptr);
+ disconnect(m_cameraControl, nullptr, this, nullptr);
+ m_session = nullptr;
+ m_cameraControl = nullptr;
+ m_videoConnection = nil;
+ return;
+ }
+
+ m_session = m_service->session();
+ Q_ASSERT(m_session);
+ m_cameraControl = static_cast<AVFCamera *>(m_service->camera());
+
+ connect(m_service, &AVFCameraService::cameraChanged, this, &AVFCameraImageCapture::onCameraChanged);
+ connect(m_session, SIGNAL(readyToConfigureConnections()), SLOT(updateCaptureConnection()));
+ connect(m_session->videoOutput(), &AVFCameraRenderer::newViewfinderFrame,
+ this, &AVFCameraImageCapture::onNewViewfinderFrame,
+ Qt::DirectConnection);
+
+ if (m_session->isActive())
+ updateCaptureConnection();
+ if (m_cameraControl) {
+ updateReadyStatus();
+ connect(m_cameraControl, SIGNAL(statusChanged(QCamera::Status)), this, SLOT(updateReadyStatus()));
+ }
+}
+
bool AVFCameraImageCapture::videoCaptureDeviceIsValid() const
{
- if (!m_service->session() || !m_service->session()->videoCaptureDevice())
+ if (!m_service || !m_service->session() || !m_service->session()->videoCaptureDevice())
return false;
AVCaptureDevice *captureDevice = m_service->session()->videoCaptureDevice();
diff --git a/src/multimedia/platform/darwin/camera/avfcameraimagecapture_p.h b/src/multimedia/platform/darwin/camera/avfcameraimagecapture_p.h
index 5731d13cb..9fceda4f1 100644
--- a/src/multimedia/platform/darwin/camera/avfcameraimagecapture_p.h
+++ b/src/multimedia/platform/darwin/camera/avfcameraimagecapture_p.h
@@ -51,17 +51,24 @@
// We mean it.
//
-#import <AVFoundation/AVFoundation.h>
+// #import <AVFoundation/AVFoundation.h>
#include <QtCore/qqueue.h>
#include <QtCore/qsemaphore.h>
#include <QtCore/qsharedpointer.h>
#include <private/qplatformcameraimagecapture_p.h>
-#include "avfcamerasession_p.h"
#include "avfstoragelocation_p.h"
QT_BEGIN_NAMESPACE
+class AVFCameraService;
+class AVFCameraSession;
+class AVFCamera;
+
+Q_FORWARD_DECLARE_OBJC_CLASS(AVCaptureStillImageOutput);
+Q_FORWARD_DECLARE_OBJC_CLASS(AVCaptureConnection);
+
+
class AVFCameraImageCapture : public QPlatformCameraImageCapture
{
Q_OBJECT
@@ -71,7 +78,7 @@ public:
QSharedPointer<QSemaphore> previewReady;
};
- AVFCameraImageCapture(AVFCameraService *service, QObject *parent = nullptr);
+ AVFCameraImageCapture(QCameraImageCapture *parent = nullptr);
~AVFCameraImageCapture();
bool isReadyForCapture() const override;
@@ -86,10 +93,13 @@ public:
void setImageSettings(const QImageEncoderSettings &settings) override;
bool applySettings();
+ void setCaptureSession(QPlatformMediaCaptureSession *session) override;
+
private Q_SLOTS:
void updateCaptureConnection();
void updateReadyStatus();
void onNewViewfinderFrame(const QVideoFrame &frame);
+ void onCameraChanged();
private:
void makeCapturePreview(CaptureRequest request, const QVideoFrame &frame, int rotation);
diff --git a/src/multimedia/platform/darwin/camera/avfcamerarenderer.mm b/src/multimedia/platform/darwin/camera/avfcamerarenderer.mm
index a3b4cc95a..a5be5e030 100644
--- a/src/multimedia/platform/darwin/camera/avfcamerarenderer.mm
+++ b/src/multimedia/platform/darwin/camera/avfcamerarenderer.mm
@@ -183,6 +183,7 @@ void AVFCameraRenderer::updateCaptureConnection()
//can be called from non main thread
void AVFCameraRenderer::syncHandleViewfinderFrame(const QVideoFrame &frame)
{
+ Q_EMIT newViewfinderFrame(frame);
QMutexLocker lock(&m_vfMutex);
if (m_rendersToWindow)
return;
diff --git a/src/multimedia/platform/darwin/camera/avfcamerarenderer_p.h b/src/multimedia/platform/darwin/camera/avfcamerarenderer_p.h
index 9460c41dd..16ff9a6c7 100644
--- a/src/multimedia/platform/darwin/camera/avfcamerarenderer_p.h
+++ b/src/multimedia/platform/darwin/camera/avfcamerarenderer_p.h
@@ -99,6 +99,9 @@ public:
QRhi *rhi() const { return m_rhi; }
+Q_SIGNALS:
+ void newViewfinderFrame(const QVideoFrame &frame);
+
private Q_SLOTS:
void handleViewfinderFrame();
void updateCaptureConnection();
diff --git a/src/multimedia/platform/darwin/camera/avfcameraservice.mm b/src/multimedia/platform/darwin/camera/avfcameraservice.mm
index 62df42d56..b23c2bc94 100644
--- a/src/multimedia/platform/darwin/camera/avfcameraservice.mm
+++ b/src/multimedia/platform/darwin/camera/avfcameraservice.mm
@@ -67,12 +67,6 @@ AVFCameraService::~AVFCameraService()
#ifdef Q_OS_IOS
delete m_recorderControl;
#endif
-
- //delete controls before session,
- //so they have a chance to do deinitialization
- if (m_imageCaptureControl)
- delete m_imageCaptureControl;
- //delete m_recorderControl;
if (m_session)
delete m_session;
}
@@ -84,7 +78,7 @@ QPlatformCamera *AVFCameraService::camera()
void AVFCameraService::setCamera(QPlatformCamera *camera)
{
- AVFCamera *control = static_cast<AVFCamera*>(camera);
+ AVFCamera *control = static_cast<AVFCamera *>(camera);
if (m_cameraControl == control)
return;
@@ -94,6 +88,7 @@ void AVFCameraService::setCamera(QPlatformCamera *camera)
m_cameraControl = control;
if (m_cameraControl)
m_cameraControl->setCaptureSession(this);
+ emit cameraChanged();
}
QPlatformCameraImageCapture *AVFCameraService::imageCapture()
@@ -101,6 +96,20 @@ QPlatformCameraImageCapture *AVFCameraService::imageCapture()
return m_imageCaptureControl;
}
+void AVFCameraService::setImageCapture(QPlatformCameraImageCapture *imageCapture)
+{
+ AVFCameraImageCapture *control = static_cast<AVFCameraImageCapture *>(imageCapture);
+ if (m_imageCaptureControl == control)
+ return;
+
+ if (m_imageCaptureControl)
+ m_imageCaptureControl->setCaptureSession(nullptr);
+
+ m_imageCaptureControl = control;
+ if (m_imageCaptureControl)
+ m_imageCaptureControl->setCaptureSession(this);
+}
+
QPlatformMediaEncoder *AVFCameraService::mediaEncoder()
{
return m_recorderControl;
@@ -164,8 +173,4 @@ void AVFCameraService::setVideoPreview(QVideoSink *sink)
m_session->setVideoSink(sink);
}
-void AVFCameraService::cameraChanged()
-{
-}
-
#include "moc_avfcameraservice_p.cpp"
diff --git a/src/multimedia/platform/darwin/camera/avfcameraservice_p.h b/src/multimedia/platform/darwin/camera/avfcameraservice_p.h
index ff1cca4ae..eb987e23d 100644
--- a/src/multimedia/platform/darwin/camera/avfcameraservice_p.h
+++ b/src/multimedia/platform/darwin/camera/avfcameraservice_p.h
@@ -74,9 +74,10 @@ public:
~AVFCameraService();
QPlatformCamera *camera() override;
- void setCamera(QPlatformCamera *) override;
+ void setCamera(QPlatformCamera *camera) override;
QPlatformCameraImageCapture *imageCapture() override;
+ void setImageCapture(QPlatformCameraImageCapture *imageCapture) override;
QPlatformMediaEncoder *mediaEncoder() override;
@@ -94,8 +95,6 @@ public:
AVFMediaEncoder *recorderControl() const { return m_recorderControl; }
AVFCameraImageCapture *avfImageCaptureControl() const { return m_imageCaptureControl; }
- void cameraChanged();
-
private:
bool m_muted = false;
qreal m_volume = 1.0;
diff --git a/src/multimedia/platform/darwin/camera/avfcamerasession_p.h b/src/multimedia/platform/darwin/camera/avfcamerasession_p.h
index b5361309a..128a20c5a 100644
--- a/src/multimedia/platform/darwin/camera/avfcamerasession_p.h
+++ b/src/multimedia/platform/darwin/camera/avfcamerasession_p.h
@@ -101,7 +101,6 @@ public Q_SLOTS:
Q_SIGNALS:
void readyToConfigureConnections();
void activeChanged(bool);
- void newViewfinderFrame(const QVideoFrame &frame);
void error(int error, const QString &errorString);
private:
diff --git a/src/multimedia/platform/darwin/qdarwinintegration.cpp b/src/multimedia/platform/darwin/qdarwinintegration.cpp
index caf2dc8fc..fa7244949 100644
--- a/src/multimedia/platform/darwin/qdarwinintegration.cpp
+++ b/src/multimedia/platform/darwin/qdarwinintegration.cpp
@@ -42,6 +42,7 @@
#include <private/avfmediaplayer_p.h>
#include <private/avfcameraservice_p.h>
#include <private/avfcamera_p.h>
+#include <private/avfcameraimagecapture_p.h>
#include <private/qdarwinformatsinfo_p.h>
#include <private/avfvideosink_p.h>
@@ -92,9 +93,9 @@ QPlatformMediaEncoder *QDarwinIntegration::createEncoder(QMediaEncoder*)
return nullptr;
}
-QPlatformImageCapture *QDarwinIntegration::createImageCapture(QCameraImageCapture*)
+QPlatformCameraImageCapture *QDarwinIntegration::createImageCapture(QCameraImageCapture *imageCapture)
{
- return nullptr;
+ return new AVFCameraImageCapture(imageCapture);
}
QPlatformVideoSink *QDarwinIntegration::createVideoSink(QVideoSink *sink)
diff --git a/src/multimedia/platform/darwin/qdarwinintegration_p.h b/src/multimedia/platform/darwin/qdarwinintegration_p.h
index 7dd1b5584..cf7691624 100644
--- a/src/multimedia/platform/darwin/qdarwinintegration_p.h
+++ b/src/multimedia/platform/darwin/qdarwinintegration_p.h
@@ -70,7 +70,7 @@ public:
QPlatformMediaPlayer *createPlayer(QMediaPlayer *player) override;
QPlatformCamera *createCamera(QCamera *camera) override;
QPlatformMediaEncoder *createEncoder(QMediaEncoder *) override;
- QPlatformImageCapture *createImageCapture(QCameraImageCapture *) override;
+ QPlatformCameraImageCapture *createImageCapture(QCameraImageCapture *) override;
QPlatformVideoSink *createVideoSink(QVideoSink *) override;
diff --git a/src/multimedia/platform/gstreamer/mediacapture/qgstreamercameraimagecapture.cpp b/src/multimedia/platform/gstreamer/mediacapture/qgstreamercameraimagecapture.cpp
index 1704ac4a9..cfb66c8b6 100644
--- a/src/multimedia/platform/gstreamer/mediacapture/qgstreamercameraimagecapture.cpp
+++ b/src/multimedia/platform/gstreamer/mediacapture/qgstreamercameraimagecapture.cpp
@@ -53,11 +53,9 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(qLcImageCapture, "qt.multimedia.imageCapture")
-QGstreamerCameraImageCapture::QGstreamerCameraImageCapture(QGstreamerMediaCapture *session, const QGstPipeline &pipeline)
- : QPlatformCameraImageCapture(session),
- QGstreamerBufferProbe(ProbeBuffers),
- m_session(session),
- gstPipeline(pipeline)
+QGstreamerCameraImageCapture::QGstreamerCameraImageCapture(QCameraImageCapture *parent)
+ : QPlatformCameraImageCapture(parent),
+ QGstreamerBufferProbe(ProbeBuffers)
{
bin = QGstBin("imageCaptureBin");
@@ -76,25 +74,22 @@ QGstreamerCameraImageCapture::QGstreamerCameraImageCapture(QGstreamerMediaCaptur
queue.link(videoConvert, encoder, sink);
bin.addGhostPad(queue, "sink");
bin.lockState(true);
- gstPipeline.add(bin);
addProbeToPad(queue.staticPad("src").pad(), false);
sink.set("signal-handoffs", true);
g_signal_connect(sink.object(), "handoff", G_CALLBACK(&QGstreamerCameraImageCapture::saveImageFilter), this);
-
- connect(m_session->camera(), &QPlatformCamera::activeChanged, this, &QGstreamerCameraImageCapture::cameraActiveChanged);
- cameraActive = m_session->camera()->isActive();
}
QGstreamerCameraImageCapture::~QGstreamerCameraImageCapture()
{
- m_session->releaseVideoPad(videoSrcPad);
+ if (m_session)
+ m_session->releaseVideoPad(videoSrcPad);
}
bool QGstreamerCameraImageCapture::isReadyForCapture() const
{
- return !passImage && cameraActive;
+ return m_session && !passImage && cameraActive;
}
@@ -153,6 +148,16 @@ int QGstreamerCameraImageCapture::captureToBuffer()
int QGstreamerCameraImageCapture::doCapture(const QString &fileName)
{
+ if (!m_session) {
+ //emit error in the next event loop,
+ //so application can associate it with returned request id.
+ QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ Q_ARG(int, m_lastId),
+ Q_ARG(int, QCameraImageCapture::ResourceError),
+ Q_ARG(QString,tr("Image capture not set to a session.")));
+
+ return -1;
+ }
if (!m_session->camera()) {
//emit error in the next event loop,
//so application can associate it with returned request id.
@@ -225,6 +230,29 @@ bool QGstreamerCameraImageCapture::probeBuffer(GstBuffer *buffer)
return true;
}
+void QGstreamerCameraImageCapture::setCaptureSession(QPlatformMediaCaptureSession *session)
+{
+ QGstreamerMediaCapture *captureSession = static_cast<QGstreamerMediaCapture *>(session);
+ if (m_session == captureSession)
+ return;
+
+ if (m_session) {
+ disconnect(m_session, nullptr, this, nullptr);
+ m_lastId = 0;
+ pendingImages.clear();
+ passImage = false;
+ cameraActive = false;
+ bin.setStateSync(GST_STATE_NULL);
+ }
+
+ m_session = captureSession;
+ if (!m_session)
+ return;
+
+ connect(m_session, &QPlatformMediaCaptureSession::cameraChanged, this, &QGstreamerCameraImageCapture::onCameraChanged);
+ onCameraChanged();
+}
+
void QGstreamerCameraImageCapture::cameraActiveChanged(bool active)
{
qCDebug(qLcImageCapture) << "cameraActiveChanged" << cameraActive << active;
@@ -235,6 +263,15 @@ void QGstreamerCameraImageCapture::cameraActiveChanged(bool active)
emit readyForCaptureChanged(isReadyForCapture());
}
+void QGstreamerCameraImageCapture::onCameraChanged()
+{
+ if (m_session->camera()) {
+ cameraActiveChanged(m_session->camera()->isActive());
+ connect(m_session->camera(), &QPlatformCamera::activeChanged, this, &QGstreamerCameraImageCapture::cameraActiveChanged);
+ }
+
+}
+
gboolean QGstreamerCameraImageCapture::saveImageFilter(GstElement *element,
GstBuffer *buffer,
GstPad *pad,
@@ -281,7 +318,8 @@ void QGstreamerCameraImageCapture::unlink()
return;
if (passImage)
return;
-
+ if (gstPipeline.isNull())
+ return;
gstPipeline.setStateSync(GST_STATE_PAUSED);
videoSrcPad.unlinkPeer();
m_session->releaseVideoPad(videoSrcPad);
@@ -293,11 +331,10 @@ void QGstreamerCameraImageCapture::unlink()
void QGstreamerCameraImageCapture::link()
{
- Q_ASSERT(m_session->camera());
-
- if (!bin.staticPad("sink").peer().isNull())
+ if (!(m_session && m_session->camera()))
+ return;
+ if (!bin.staticPad("sink").peer().isNull() || gstPipeline.isNull())
return;
-
gstPipeline.setStateSync(GST_STATE_PAUSED);
videoSrcPad = m_session->getVideoPad();
videoSrcPad.link(bin.staticPad("sink"));
diff --git a/src/multimedia/platform/gstreamer/mediacapture/qgstreamercameraimagecapture_p.h b/src/multimedia/platform/gstreamer/mediacapture/qgstreamercameraimagecapture_p.h
index e046eae99..067920518 100644
--- a/src/multimedia/platform/gstreamer/mediacapture/qgstreamercameraimagecapture_p.h
+++ b/src/multimedia/platform/gstreamer/mediacapture/qgstreamercameraimagecapture_p.h
@@ -68,7 +68,7 @@ class QGstreamerCameraImageCapture : public QPlatformCameraImageCapture, private
{
Q_OBJECT
public:
- QGstreamerCameraImageCapture(QGstreamerMediaCapture *session, const QGstPipeline &pipeline);
+ QGstreamerCameraImageCapture(QCameraImageCapture *parent/*, const QGstPipeline &pipeline*/);
virtual ~QGstreamerCameraImageCapture();
bool isReadyForCapture() const override;
@@ -80,8 +80,14 @@ public:
bool probeBuffer(GstBuffer *buffer) override;
+ void setCaptureSession(QPlatformMediaCaptureSession *session);
+
+ QGstElement gstElement() const { return bin.element(); }
+ void setPipeline(const QGstPipeline &pipeline) { gstPipeline = pipeline; }
+
public Q_SLOTS:
void cameraActiveChanged(bool active);
+ void onCameraChanged();
private:
int doCapture(const QString &fileName);
diff --git a/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediacapture.cpp b/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediacapture.cpp
index 770b720a5..6ea518705 100644
--- a/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediacapture.cpp
+++ b/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediacapture.cpp
@@ -88,7 +88,6 @@ QGstreamerMediaCapture::QGstreamerMediaCapture(QMediaRecorder::CaptureMode)
QGstreamerMediaCapture::~QGstreamerMediaCapture()
{
gstPipeline.setStateSync(GST_STATE_NULL);
- delete m_imageCapture;
delete m_mediaEncoder;
}
@@ -130,7 +129,7 @@ void QGstreamerMediaCapture::setCamera(QPlatformCamera *camera)
}
gstPipeline.setStateSync(GST_STATE_PLAYING);
- cameraChanged();
+ emit cameraChanged();
dumpGraph(QLatin1String("camera"));
}
@@ -141,7 +140,29 @@ QPlatformCameraImageCapture *QGstreamerMediaCapture::imageCapture()
void QGstreamerMediaCapture::setImageCapture(QPlatformCameraImageCapture *imageCapture)
{
- Q_UNUSED(imageCapture);
+ QGstreamerCameraImageCapture *control = static_cast<QGstreamerCameraImageCapture *>(imageCapture);
+ if (m_imageCapture == control)
+ return;
+
+ gstPipeline.setStateSync(GST_STATE_PAUSED);
+
+ if (m_imageCapture) {
+ m_imageCapture->setCaptureSession(nullptr);
+ if (m_imageCapture->gstElement().state() != GST_STATE_NULL)
+ m_imageCapture->gstElement().setStateSync(GST_STATE_NULL);
+ gstPipeline.remove(m_imageCapture->gstElement());
+ }
+
+ m_imageCapture = control;
+ if (m_imageCapture) {
+ m_imageCapture->setCaptureSession(this);
+ m_imageCapture->setPipeline(gstPipeline);
+ gstPipeline.add(m_imageCapture->gstElement());
+ // m_imageCapture->gstElement().lockState(false);
+ // m_imageCapture->gstElement().setState(gstPipeline.state());
+ }
+ gstPipeline.setStateSync(GST_STATE_PLAYING);
+ emit imageCaptureChanged();
}
void QGstreamerMediaCapture::setMediaEncoder(QPlatformMediaEncoder *encoder)
@@ -200,9 +221,9 @@ bool QGstreamerMediaCapture::setAudioPreview(const QAudioDeviceInfo &info)
return true;
}
-void QGstreamerMediaCapture::cameraChanged()
-{
-}
+// void QGstreamerMediaCapture::cameraChanged()
+// {
+// }
void QGstreamerMediaCapture::dumpGraph(const QString &fileName)
{
diff --git a/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediacapture_p.h b/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediacapture_p.h
index 5aae7867f..cd097a890 100644
--- a/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediacapture_p.h
+++ b/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediacapture_p.h
@@ -94,7 +94,7 @@ public:
QAudioDeviceInfo audioPreview() const override;
bool setAudioPreview(const QAudioDeviceInfo &info) override;
- void cameraChanged();
+ // void cameraChanged();
void dumpGraph(const QString &fileName);
diff --git a/src/multimedia/platform/gstreamer/qgstreamerintegration.cpp b/src/multimedia/platform/gstreamer/qgstreamerintegration.cpp
index ea75a060d..c4ad5211f 100644
--- a/src/multimedia/platform/gstreamer/qgstreamerintegration.cpp
+++ b/src/multimedia/platform/gstreamer/qgstreamerintegration.cpp
@@ -101,9 +101,9 @@ QPlatformMediaEncoder *QGstreamerIntegration::createEncoder(QMediaEncoder*)
return nullptr;
}
-QPlatformImageCapture *QGstreamerIntegration::createImageCapture(QCameraImageCapture*)
+QPlatformCameraImageCapture *QGstreamerIntegration::createImageCapture(QCameraImageCapture *imageCapture)
{
- return nullptr;
+ return new QGstreamerCameraImageCapture(imageCapture);
}
QPlatformVideoSink *QGstreamerIntegration::createVideoSink(QVideoSink *sink)
diff --git a/src/multimedia/platform/gstreamer/qgstreamerintegration_p.h b/src/multimedia/platform/gstreamer/qgstreamerintegration_p.h
index c00dcc4f0..38fc93f43 100644
--- a/src/multimedia/platform/gstreamer/qgstreamerintegration_p.h
+++ b/src/multimedia/platform/gstreamer/qgstreamerintegration_p.h
@@ -74,7 +74,7 @@ public:
QPlatformMediaPlayer *createPlayer(QMediaPlayer *player) override;
QPlatformCamera *createCamera(QCamera *) override;
QPlatformMediaEncoder *createEncoder(QMediaEncoder *) override;
- QPlatformImageCapture *createImageCapture(QCameraImageCapture *) override;
+ QPlatformCameraImageCapture *createImageCapture(QCameraImageCapture *) override;
QPlatformVideoSink *createVideoSink(QVideoSink *sink) override;
diff --git a/src/multimedia/platform/qplatformcameraimagecapture.cpp b/src/multimedia/platform/qplatformcameraimagecapture.cpp
index bed04b035..907fa3354 100644
--- a/src/multimedia/platform/qplatformcameraimagecapture.cpp
+++ b/src/multimedia/platform/qplatformcameraimagecapture.cpp
@@ -57,8 +57,9 @@ QT_BEGIN_NAMESPACE
/*!
Constructs a new image capture control object with the given \a parent
*/
-QPlatformCameraImageCapture::QPlatformCameraImageCapture(QObject *parent)
- :QObject(parent)
+QPlatformCameraImageCapture::QPlatformCameraImageCapture(QCameraImageCapture *parent)
+ : QObject(parent),
+ m_imageCapture(parent)
{
}
diff --git a/src/multimedia/platform/qplatformcameraimagecapture_p.h b/src/multimedia/platform/qplatformcameraimagecapture_p.h
index f6e4e08f2..8971deb63 100644
--- a/src/multimedia/platform/qplatformcameraimagecapture_p.h
+++ b/src/multimedia/platform/qplatformcameraimagecapture_p.h
@@ -56,6 +56,7 @@
QT_BEGIN_NAMESPACE
class QImage;
+class QPlatformMediaCaptureSession;
class Q_MULTIMEDIA_EXPORT QPlatformCameraImageCapture : public QObject
{
@@ -71,6 +72,9 @@ public:
virtual void setImageSettings(const QImageEncoderSettings &settings) = 0;
virtual void setMetaData(const QMediaMetaData &) {}
+
+ QCameraImageCapture *imageCapture() { return m_imageCapture; }
+
Q_SIGNALS:
void readyForCaptureChanged(bool ready);
@@ -83,7 +87,9 @@ Q_SIGNALS:
void error(int id, int error, const QString &errorString);
protected:
- explicit QPlatformCameraImageCapture(QObject *parent = nullptr);
+ explicit QPlatformCameraImageCapture(QCameraImageCapture *parent = nullptr);
+private:
+ QCameraImageCapture *m_imageCapture = nullptr;
};
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/qplatformmediacapture_p.h b/src/multimedia/platform/qplatformmediacapture_p.h
index c2c211171..087d5e1cb 100644
--- a/src/multimedia/platform/qplatformmediacapture_p.h
+++ b/src/multimedia/platform/qplatformmediacapture_p.h
@@ -92,6 +92,9 @@ public:
Q_SIGNALS:
void mutedChanged(bool muted);
void volumeChanged(qreal volume);
+ void cameraChanged();
+ void imageCaptureChanged();
+ void encoderChanged();
};
diff --git a/src/multimedia/platform/qplatformmediaintegration_p.h b/src/multimedia/platform/qplatformmediaintegration_p.h
index 4fd8aec3f..dd26c2b71 100644
--- a/src/multimedia/platform/qplatformmediaintegration_p.h
+++ b/src/multimedia/platform/qplatformmediaintegration_p.h
@@ -66,7 +66,7 @@ class QPlatformMediaPlayer;
class QPlatformAudioDecoder;
class QPlatformCamera;
class QPlatformMediaEncoder;
-class QPlatformImageCapture;
+class QPlatformCameraImageCapture;
class QPlatformMediaFormatInfo;
class QObject;
class QPlatformVideoSink;
@@ -90,7 +90,7 @@ public:
virtual QPlatformMediaPlayer *createPlayer(QMediaPlayer *) { return nullptr; }
virtual QPlatformCamera *createCamera(QCamera *) { return nullptr; }
virtual QPlatformMediaEncoder *createEncoder(QMediaEncoder *) { return nullptr; }
- virtual QPlatformImageCapture *createImageCapture(QCameraImageCapture *) { return nullptr; }
+ virtual QPlatformCameraImageCapture *createImageCapture(QCameraImageCapture *) { return nullptr; }
virtual QPlatformVideoSink *createVideoSink(QVideoSink *) { return nullptr; }
};
diff --git a/src/multimediaquick/qtmultimediaquicktypes_p.h b/src/multimediaquick/qtmultimediaquicktypes_p.h
index 2539ef86a..8bbbe29eb 100644
--- a/src/multimediaquick/qtmultimediaquicktypes_p.h
+++ b/src/multimediaquick/qtmultimediaquicktypes_p.h
@@ -53,7 +53,7 @@
#include <QtQml/qqml.h>
#include <QtMultimedia/QtMultimedia>
-#include <qtmultimediaquickglobal_p.h>
+#include <private/qtmultimediaquickglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/tests/auto/unit/mockbackend/qmockimagecapture.cpp b/tests/auto/unit/mockbackend/qmockimagecapture.cpp
index 3cab8ce49..23e9fad60 100644
--- a/tests/auto/unit/mockbackend/qmockimagecapture.cpp
+++ b/tests/auto/unit/mockbackend/qmockimagecapture.cpp
@@ -29,16 +29,17 @@
#include <qmockimagecapture.h>
#include <qmockcamera.h>
#include <qmockmediacapturesession.h>
+#include <qcameraimagecapture.h>
+#include <qcamera.h>
-QMockImageCapture::QMockImageCapture(QMockMediaCaptureSession *captureSession)
- : QPlatformCameraImageCapture(captureSession),
- m_captureSession(captureSession)
+QMockImageCapture::QMockImageCapture(QCameraImageCapture *parent)
+ : QPlatformCameraImageCapture(parent)
{
}
bool QMockImageCapture::isReadyForCapture() const
{
- return m_ready && m_captureSession->camera() && m_captureSession->camera()->isActive();
+ return m_ready;
}
int QMockImageCapture::capture(const QString &fileName)
diff --git a/tests/auto/unit/mockbackend/qmockimagecapture.h b/tests/auto/unit/mockbackend/qmockimagecapture.h
index 3107e25fc..7b7a2a5e1 100644
--- a/tests/auto/unit/mockbackend/qmockimagecapture.h
+++ b/tests/auto/unit/mockbackend/qmockimagecapture.h
@@ -42,25 +42,24 @@ class QMockImageCapture : public QPlatformCameraImageCapture
{
Q_OBJECT
public:
- QMockImageCapture(QMockMediaCaptureSession *captureSession);
+ QMockImageCapture(QCameraImageCapture *parent);
~QMockImageCapture()
{
}
- bool isReadyForCapture() const;
+ bool isReadyForCapture() const override;
- int capture(const QString &fileName);
- int captureToBuffer() { return -1; }
+ int capture(const QString &fileName) override;
+ int captureToBuffer() override { return -1; }
- QImageEncoderSettings imageSettings() const { return m_settings; }
- void setImageSettings(const QImageEncoderSettings &settings) { m_settings = settings; }
+ QImageEncoderSettings imageSettings() const override { return m_settings; }
+ void setImageSettings(const QImageEncoderSettings &settings) override { m_settings = settings; }
private Q_SLOTS:
void captured();
private:
- QMockMediaCaptureSession *m_captureSession = nullptr;
QString m_fileName;
int m_captureRequest = 0;
bool m_ready = true;
diff --git a/tests/auto/unit/mockbackend/qmockintegration.cpp b/tests/auto/unit/mockbackend/qmockintegration.cpp
index 383ddc5d3..585cad8ff 100644
--- a/tests/auto/unit/mockbackend/qmockintegration.cpp
+++ b/tests/auto/unit/mockbackend/qmockintegration.cpp
@@ -44,6 +44,7 @@
#include "qmockcamera.h"
#include "qmockmediacapturesession.h"
#include "qmockvideosink.h"
+#include "qmockimagecapture.h"
QT_BEGIN_NAMESPACE
@@ -92,6 +93,11 @@ QPlatformCamera *QMockIntegration::createCamera(QCamera *parent)
return m_lastCamera;
}
+QPlatformCameraImageCapture *QMockIntegration::createImageCapture(QCameraImageCapture *capture)
+{
+ return new QMockImageCapture(capture);
+}
+
QPlatformMediaCaptureSession *QMockIntegration::createCaptureSession(QMediaRecorder::CaptureMode mode)
{
Q_UNUSED(mode);
diff --git a/tests/auto/unit/mockbackend/qmockintegration_p.h b/tests/auto/unit/mockbackend/qmockintegration_p.h
index 3d599d129..af86bf5a8 100644
--- a/tests/auto/unit/mockbackend/qmockintegration_p.h
+++ b/tests/auto/unit/mockbackend/qmockintegration_p.h
@@ -74,7 +74,7 @@ public:
QPlatformMediaPlayer *createPlayer(QMediaPlayer *) override;
QPlatformCamera *createCamera(QCamera *) override;
QPlatformMediaEncoder *createEncoder(QMediaEncoder *) override { return nullptr; }
- QPlatformImageCapture *createImageCapture(QCameraImageCapture *) override { return nullptr; }
+ QPlatformCameraImageCapture *createImageCapture(QCameraImageCapture *) override;
QPlatformMediaCaptureSession *createCaptureSession(QMediaRecorder::CaptureMode mode) override;
QPlatformVideoSink *createVideoSink(QVideoSink *) override;
diff --git a/tests/auto/unit/mockbackend/qmockmediacapturesession.h b/tests/auto/unit/mockbackend/qmockmediacapturesession.h
index 1fb33046c..048698288 100644
--- a/tests/auto/unit/mockbackend/qmockmediacapturesession.h
+++ b/tests/auto/unit/mockbackend/qmockmediacapturesession.h
@@ -43,7 +43,6 @@ public:
: hasControls(true)
{
mockControl = new QMockMediaEncoder(this);
- mockCaptureControl = new QMockImageCapture(this);
}
~QMockMediaCaptureSession()
{
@@ -60,7 +59,11 @@ public:
mockCameraControl = control;
}
- QPlatformCameraImageCapture *imageCapture() override { return hasControls ? mockCaptureControl : nullptr; }
+ void setImageCapture(QPlatformCameraImageCapture *imageCapture) override
+ {
+ mockImageCapture = imageCapture;
+ }
+ QPlatformCameraImageCapture *imageCapture() override { return hasControls ? mockImageCapture : nullptr; }
QPlatformMediaEncoder *mediaEncoder() override { return hasControls ? mockControl : nullptr; }
void setVideoPreview(QVideoSink *) override {}
@@ -98,7 +101,7 @@ public:
}
QMockCamera *mockCameraControl = nullptr;
- QMockImageCapture *mockCaptureControl = nullptr;
+ QPlatformCameraImageCapture *mockImageCapture = nullptr;
QMockMediaEncoder *mockControl = nullptr;
QAudioDeviceInfo m_audioInput;
diff --git a/tests/auto/unit/multimedia/qcameraimagecapture/tst_qcameraimagecapture.cpp b/tests/auto/unit/multimedia/qcameraimagecapture/tst_qcameraimagecapture.cpp
index 533ec5208..b4a05bbde 100644
--- a/tests/auto/unit/multimedia/qcameraimagecapture/tst_qcameraimagecapture.cpp
+++ b/tests/auto/unit/multimedia/qcameraimagecapture/tst_qcameraimagecapture.cpp
@@ -55,7 +55,7 @@ public slots:
private slots:
void constructor();
- void noBackend();
+ void isAvailable();
void deleteMediaSource();
void isReadyForCapture();
void capture();
@@ -100,14 +100,11 @@ void tst_QCameraImageCapture::constructor()
QVERIFY(imageCapture.isAvailable() == true);
}
-void tst_QCameraImageCapture::noBackend()
+void tst_QCameraImageCapture::isAvailable()
{
{
QMediaCaptureSession session;
- QCamera camera;
- mockIntegration->lastCaptureService()->hasControls = false;
QCameraImageCapture imageCapture;
- session.setCamera(&camera);
session.setImageCapture(&imageCapture);
QVERIFY(!imageCapture.isAvailable());
@@ -154,6 +151,7 @@ void tst_QCameraImageCapture::isReadyForCapture()
QVERIFY(imageCapture.isAvailable() == true);
QVERIFY(imageCapture.isReadyForCapture() == false);
camera.start();
+ QVERIFY(imageCapture.isReadyForCapture() == true);
imageCapture.captureToFile();
QTRY_VERIFY(imageCapture.isReadyForCapture());
camera.stop();
@@ -209,7 +207,7 @@ void tst_QCameraImageCapture::errors()
QVERIFY(imageCapture.isAvailable() == true);
imageCapture.captureToFile(QString::fromLatin1("/dev/null"));
- QVERIFY(imageCapture.error() == QCameraImageCapture::NotReadyError);
+ QCOMPARE(imageCapture.error(), QCameraImageCapture::NotReadyError);
QVERIFY(!imageCapture.errorString().isEmpty());
}