+/*!
+ * This file is part of CameraPlus.
+ *
+ * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
#include "qtcammode.h"
#include "qtcammode_p.h"
#include "qtcamdevice_p.h"
#include "qtcamdevice.h"
#include <QDebug>
-#include "qtcamgstreamermessagehandler.h"
#include "qtcamgstreamermessagelistener.h"
#include <gst/video/video.h>
#include <QImage>
-
-#define PREVIEW_CAPS "video/x-raw-rgb, width = (int) %1, height = (int) %2, bpp = (int) 32, depth = (int) 24, red_mask = (int) 65280, green_mask = (int) 16711680, blue_mask = (int) -16777216"
-
-#define CAPS "video/x-raw-yuv, width = (int) %1, height = (int) %2, framerate = (fraction) %3/%4"
+#include <QFile>
class PreviewImageHandler : public QtCamGStreamerMessageHandler {
public:
// We need to copy because GStreamer will free the buffer after we return
// and since QImage doesn't copythe data by default we will end up with garbage.
- // TODO: consider a QImage subclass that takes a GstBuffer reference
+ // There is no way to subclass QImage to prevent copying :|
QImage cp = image.copy();
QString fileName = QString::fromUtf8(file);
QtCamMode *mode;
};
-class DoneHandler : public QtCamGStreamerMessageHandler {
-public:
- DoneHandler(QtCamMode *m, const char *done, QObject *parent = 0) :
- QtCamGStreamerMessageHandler(done, parent) {
- mode = m;
- }
-
- virtual void handleMessage(GstMessage *message) {
- 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);
- }
- }
-
- QMetaObject::invokeMethod(mode, "saved", Q_ARG(QString, fileName));
- }
-
- QString fileName;
- QtCamMode *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(this, done, this);
+ d_ptr->doneHandler = 0;
}
QtCamMode::~QtCamMode() {
d_ptr->dev->active = this;
- // TODO: check that we can actually do it. Perhaps the pipeline is busy.
g_object_set(d_ptr->dev->cameraBin, "mode", d_ptr->id, NULL);
- d_ptr->dev->resetCapabilities();
-
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);
}
bool QtCamMode::canCapture() {
- return d_ptr->dev->cameraBin && isActive() && d_ptr->dev->q_ptr->isRunning();
+ return d_ptr->dev->cameraBin && isActive() && d_ptr->dev->q_ptr->isRunning() &&
+ !d_ptr->dev->error;
}
bool QtCamMode::isActive() {
return d_ptr->dev->active == this;
}
-void QtCamMode::setCaps(const char *property, const QSize& resolution,
- const QPair<int, int> frameRate) {
-
- if (!d_ptr->dev->cameraBin) {
- return;
- }
-
- // TODO: allow proceeding without specifying a frame rate (maybe we can calculate it ?)
- if (frameRate.first <= 0 || frameRate.second <= 0) {
- return;
- }
-
- if (resolution.width() <= 0 || resolution.height() <= 0) {
- return;
- }
-
- QString capsString = QString(CAPS)
- .arg(resolution.width()).arg(resolution.height())
- .arg(frameRate.first).arg(frameRate.second);
-
- GstCaps *caps = gst_caps_from_string(capsString.toAscii());
-
- g_object_set(d_ptr->dev->cameraBin, property, caps, NULL);
-
- gst_caps_unref(caps);
-}
-
-void QtCamMode::setPreviewSize(const QSize& size) {
- if (!d_ptr->dev->cameraBin) {
- return;
- }
-
- if (size.width() <= 0 && size.height() <= 0) {
- g_object_set(d_ptr->dev->cameraBin, "preview-caps", NULL, "post-previews", FALSE, NULL);
- }
- else {
- QString preview = QString(PREVIEW_CAPS).arg(size.width()).arg(size.height());
-
- GstCaps *caps = gst_caps_from_string(preview.toAscii());
-
- g_object_set(d_ptr->dev->cameraBin, "preview-caps", caps, "post-previews", TRUE, NULL);
-
- gst_caps_unref(caps);
- }
-}
-
-void QtCamMode::setFileName(const QString& fileName) {
- d_ptr->doneHandler->fileName = fileName;
+QtCamDevice *QtCamMode::device() const {
+ return d_ptr->dev->q_ptr;
}