static_cast<QtCamGStreamerMessageListenerPrivate *>(data);
if (d_ptr->handleSyncMessage(message)) {
- gst_message_unref(message);
- return GST_BUS_DROP;
+ // We need to pass the message.
+ // Issue is we have 2 video-done handlers, a sync and an async.
+ // If we drop the message then the async handler will never see it :|
+ return GST_BUS_PASS;
}
return GST_BUS_PASS;
gst_message_unref(message);
}
}
-
-GstMessage *QtCamGStreamerMessageListener::waitForMessage(const QLatin1String& name) {
- GstMessage *message = 0;
-
- while (!message) {
- message = gst_bus_timed_pop_filtered(d_ptr->bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ELEMENT);
- if (!message) {
- // Hmmm, what to do here??
- continue;
- }
-
- d_ptr->handleMessage(message);
- const GstStructure *s = gst_message_get_structure(message);
- const gchar *n = s ? gst_structure_get_name(s) : 0;
- if (s && n && n == name) {
- return message;
- }
-
- gst_message_unref(message);
- message = 0;
- }
-
- return 0;
-}
void flushMessages();
- GstMessage *waitForMessage(const QLatin1String& name);
-
signals:
void error(const QString& message, int code, const QString& debug);
void started();
};
QtCamImageMode::QtCamImageMode(QtCamDevicePrivate *dev, QObject *parent) :
- QtCamMode(new QtCamImageModePrivate(dev), "mode-image", "image-done", parent) {
+ QtCamMode(new QtCamImageModePrivate(dev), "mode-image", parent) {
+
+ d_ptr->init(new DoneHandler(d_ptr, "image-done", this));
d = (QtCamImageModePrivate *)d_ptr;
#include "qtcamdevice_p.h"
#include "qtcamdevice.h"
#include <QDebug>
-#include "qtcamgstreamermessagehandler.h"
#include "qtcamgstreamermessagelistener.h"
#include <gst/video/video.h>
#include <QImage>
QtCamMode *mode;
};
-class DoneHandler : public QtCamGStreamerMessageHandler {
-public:
- DoneHandler(QtCamModePrivate *m, const char *done, QObject *parent = 0) :
- QtCamGStreamerMessageHandler(done, parent) {
- mode = m;
- }
-
- virtual void handleMessage(GstMessage *message) {
- // If we have a temp file then we rename it:
- if (!mode->tempFileName.isEmpty() && !mode->fileName.isEmpty()) {
- if (!QFile::rename(mode->tempFileName, mode->fileName)) {
- qCritical() << "Failed to rename" << mode->tempFileName << "to" << mode->fileName;
- }
- }
-
- QString fileName;
- const GstStructure *s = gst_message_get_structure(message);
- if (gst_structure_has_field(s, "filename")) {
- const char *str = gst_structure_get_string(s, "filename");
- if (str) {
- fileName = QString::fromUtf8(str);
- }
- }
-
- if (fileName.isEmpty()) {
- fileName = mode->fileName;
- }
-
- QMetaObject::invokeMethod(mode->q_ptr, "saved", Q_ARG(QString, fileName));
- }
-
- QtCamModePrivate *mode;
-};
-
-QtCamMode::QtCamMode(QtCamModePrivate *d, const char *mode, const char *done, QObject *parent) :
+QtCamMode::QtCamMode(QtCamModePrivate *d, const char *mode, QObject *parent) :
QObject(parent), d_ptr(d) {
d_ptr->q_ptr = this;
d_ptr->id = d_ptr->modeId(mode);
d_ptr->previewImageHandler = new PreviewImageHandler(this, this);
- d_ptr->doneHandler = new DoneHandler(d_ptr, done, this);
+ d_ptr->doneHandler = 0;
}
QtCamMode::~QtCamMode() {
g_object_set(d_ptr->dev->cameraBin, "mode", d_ptr->id, NULL);
d_ptr->dev->listener->addHandler(d_ptr->previewImageHandler);
- d_ptr->dev->listener->addHandler(d_ptr->doneHandler);
+
+ // This has to be sync. VideoDoneHandler will lock a mutex that is already
+ // locked from the main thread.
+ d_ptr->dev->listener->addSyncHandler(d_ptr->doneHandler);
start();
}
d_ptr->dev->listener->removeHandler(d_ptr->previewImageHandler);
- d_ptr->dev->listener->removeHandler(d_ptr->doneHandler);
+ d_ptr->dev->listener->removeSyncHandler(d_ptr->doneHandler);
d_ptr->previewImageHandler->setParent(this);
d_ptr->doneHandler->setParent(this);
Q_PROPERTY(bool active READ isActive NOTIFY activeChanged);
public:
- QtCamMode(QtCamModePrivate *d, const char *mode, const char *done, QObject *parent = 0);
+ QtCamMode(QtCamModePrivate *d, const char *mode, QObject *parent = 0);
virtual ~QtCamMode();
void deactivate();
#include "qtcamanalysisbin.h"
#include <gst/pbutils/encoding-profile.h>
#include <gst/pbutils/encoding-target.h>
+#include "qtcamgstreamermessagehandler.h"
#ifndef GST_USE_UNSTABLE_API
#define GST_USE_UNSTABLE_API
QtCamModePrivate(QtCamDevicePrivate *d) : id(-1), dev(d) {}
virtual ~QtCamModePrivate() {}
+ void init(DoneHandler *handler) {
+ doneHandler = handler;
+ }
+
int modeId(const char *mode) {
if (!dev->cameraBin) {
return -1;
QString tempFileName;
};
+class DoneHandler : public QtCamGStreamerMessageHandler {
+public:
+ DoneHandler(QtCamModePrivate *m, const char *done, QObject *parent = 0) :
+ QtCamGStreamerMessageHandler(done, parent) {
+ mode = m;
+ }
+
+ virtual ~DoneHandler() { }
+
+ virtual void handleMessage(GstMessage *message) {
+ // If we have a temp file then we rename it:
+ if (!mode->tempFileName.isEmpty() && !mode->fileName.isEmpty()) {
+ if (!QFile::rename(mode->tempFileName, mode->fileName)) {
+ qCritical() << "Failed to rename" << mode->tempFileName << "to" << mode->fileName;
+ }
+ }
+
+ QString fileName;
+ const GstStructure *s = gst_message_get_structure(message);
+ if (gst_structure_has_field(s, "filename")) {
+ const char *str = gst_structure_get_string(s, "filename");
+ if (str) {
+ fileName = QString::fromUtf8(str);
+ }
+ }
+
+ if (fileName.isEmpty()) {
+ fileName = mode->fileName;
+ }
+
+ QMetaObject::invokeMethod(mode->q_ptr, "saved", Qt::QueuedConnection,
+ Q_ARG(QString, fileName));
+ }
+
+ QtCamModePrivate *mode;
+};
+
#endif /* QT_CAM_MODE_P_H */
#include "qtcamdevice.h"
#include "qtcamvideosettings.h"
#include "qtcamnotifications.h"
-#include "qtcamgstreamermessagelistener.h"
+#include <QMutex>
+#include <QWaitCondition>
class QtCamVideoModePrivate : public QtCamModePrivate {
public:
QtCamVideoResolution resolution;
};
+class VideoDoneHandler : public DoneHandler {
+public:
+ VideoDoneHandler(QtCamModePrivate *d, QObject *parent = 0) :
+ DoneHandler(d, "video-done", parent) {}
+
+ virtual void handleMessage(GstMessage *message) {
+ DoneHandler::handleMessage(message);
+
+ wake();
+ }
+
+ void wake() {
+ lock();
+ m_cond.wakeOne();
+ unlock();
+ }
+
+ void lock() {
+ m_mutex.lock();
+ }
+
+ void unlock() {
+ m_mutex.unlock();
+ }
+
+ void wait() {
+ m_cond.wait(&m_mutex);
+ }
+
+private:
+ QMutex m_mutex;
+ QWaitCondition m_cond;
+};
+
QtCamVideoMode::QtCamVideoMode(QtCamDevicePrivate *dev, QObject *parent) :
- QtCamMode(new QtCamVideoModePrivate(dev), "mode-video", "video-done", parent) {
+ QtCamMode(new QtCamVideoModePrivate(dev), "mode-video", parent) {
+
+ d_ptr->init(new VideoDoneHandler(d_ptr, this));
d = (QtCamVideoModePrivate *)QtCamMode::d_ptr;
void QtCamVideoMode::stopRecording(bool sync) {
if (isRecording()) {
+ VideoDoneHandler *handler = dynamic_cast<VideoDoneHandler *>(d_ptr->doneHandler);
+ if (sync) {
+ handler->lock();
+ }
+
g_signal_emit_by_name(d_ptr->dev->cameraBin, "stop-capture", NULL);
if (sync) {
- GstMessage *msg = d_ptr->dev->listener->waitForMessage(QLatin1String("video-done"));
- if (msg) {
- gst_message_unref(msg);
- }
+ handler->wait();
+ handler->unlock();
}
}
}