2 * This file is part of CameraPlus.
4 * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "qtcammode.h"
22 #include "qtcammode_p.h"
23 #include "qtcamdevice_p.h"
24 #include "qtcamdevice.h"
26 #include "qtcamgstreamermessagelistener.h"
27 #include <gst/video/video.h>
31 class PreviewImageHandler : public QtCamGStreamerMessageHandler {
33 PreviewImageHandler(QtCamMode *m, QObject *parent = 0) :
34 QtCamGStreamerMessageHandler("preview-image", parent) {
38 virtual void handleMessage(GstMessage *message) {
39 const GstStructure *s = gst_message_get_structure(message);
44 const char *file = gst_structure_get_string(s, "location");
49 const GValue *val = gst_structure_get_value(s, "buffer");
54 GstBuffer *buffer = gst_value_get_buffer(val);
61 if (!gst_video_format_parse_caps(buffer->caps, &fmt, &width, &height)) {
65 if (fmt != GST_VIDEO_FORMAT_BGRx || width <= 0 || height <= 0) {
69 QImage image(buffer->data, width, height, QImage::Format_RGB32);
71 // We need to copy because GStreamer will free the buffer after we return
72 // and since QImage doesn't copythe data by default we will end up with garbage.
73 // There is no way to subclass QImage to prevent copying :|
74 QImage cp = image.copy();
76 QString fileName = QString::fromUtf8(file);
78 QMetaObject::invokeMethod(mode, "previewAvailable",
79 Q_ARG(QImage, cp), Q_ARG(QString, fileName));
85 QtCamMode::QtCamMode(QtCamModePrivate *d, const char *mode, QObject *parent) :
86 QObject(parent), d_ptr(d) {
89 d_ptr->id = d_ptr->modeId(mode);
90 d_ptr->previewImageHandler = new PreviewImageHandler(this, this);
91 d_ptr->doneHandler = 0;
94 QtCamMode::~QtCamMode() {
95 delete d_ptr; d_ptr = 0;
98 void QtCamMode::activate() {
99 if (!d_ptr->dev->cameraBin) {
103 if (d_ptr->dev->active == this) {
107 if (d_ptr->dev->active) {
108 d_ptr->dev->active->deactivate();
111 d_ptr->dev->active = this;
113 g_object_set(d_ptr->dev->cameraBin, "mode", d_ptr->id, NULL);
115 d_ptr->dev->listener->addHandler(d_ptr->previewImageHandler);
117 // This has to be sync. VideoDoneHandler will lock a mutex that is already
118 // locked from the main thread.
119 d_ptr->dev->listener->addSyncHandler(d_ptr->doneHandler);
125 QMetaObject::invokeMethod(d_ptr->dev->q_ptr, "modeChanged");
127 emit activeChanged();
130 void QtCamMode::deactivate() {
131 if (d_ptr->dev->active != this) {
135 d_ptr->dev->listener->removeHandler(d_ptr->previewImageHandler);
136 d_ptr->dev->listener->removeSyncHandler(d_ptr->doneHandler);
138 d_ptr->previewImageHandler->setParent(this);
139 d_ptr->doneHandler->setParent(this);
143 d_ptr->dev->active = 0;
145 QMetaObject::invokeMethod(d_ptr->dev->q_ptr, "modeChanged");
147 emit activeChanged();
150 bool QtCamMode::canCapture() {
151 return d_ptr->dev->cameraBin && isActive() && d_ptr->dev->q_ptr->isRunning() &&
155 bool QtCamMode::isActive() {
156 return d_ptr->dev->active == this;
159 QtCamDevice *QtCamMode::device() const {
160 return d_ptr->dev->q_ptr;