+/*!
+ * 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 "qtcamdevice.h"
#include "qtcamviewfinder.h"
#include "qtcamconfig.h"
#include "qtcammode.h"
#include "qtcamimagemode.h"
#include "qtcamvideomode.h"
+#include "qtcamnotifications.h"
+#include "gst/gstcopy.h"
+#include "qtcampropertysetter.h"
+#include "qtcamanalysisbin.h"
QtCamDevice::QtCamDevice(QtCamConfig *config, const QString& name,
const QVariant& id, QObject *parent) :
QObject(parent), d_ptr(new QtCamDevicePrivate) {
+ static gboolean register_copy = TRUE;
+ if (register_copy) {
+ qt_cam_copy_register();
+ register_copy = FALSE;
+ }
+
d_ptr->q_ptr = this;
d_ptr->name = name;
d_ptr->id = id;
return;
}
+ d_ptr->propertySetter = new QtCamPropertySetter(d_ptr);
+
d_ptr->createAndAddElement(d_ptr->conf->audioSource(), "audio-source", "QtCameraAudioSrc");
- d_ptr->createAndAddVideoSource();
+ if (!d_ptr->conf->wrapperVideoSource().isEmpty() &&
+ !d_ptr->conf->wrapperVideoSourceProperty().isEmpty()) {
+ d_ptr->createAndAddVideoSourceAndWrapper();
+ }
+ else {
+ d_ptr->createAndAddVideoSource();
+ }
+
+ d_ptr->setDevicePoperty();
int flags =
0x00000001 /* no-audio-conversion - Do not use audio conversion elements */
d_ptr->setAudioCaptureCaps();
- // TODO: audio bitrate
- // TODO: video bitrate
- // TODO: filters
- // TODO: capabilities
- // TODO: custom properties for jifmux, mp4mux, audio encoder, video encoder, sink & video source
- // color tune, scene modes
+ QStringList viewfinderFilters = d_ptr->conf->viewfinderFilters();
+ if (!viewfinderFilters.isEmpty()) {
+ d_ptr->viewfinderFilters =
+ QtCamAnalysisBin::create(viewfinderFilters, "QtCamViewfinderFilters");
+
+ if (!d_ptr->viewfinderFilters) {
+ qWarning() << "Failed to create viewfinder filters";
+ }
+ else {
+ g_object_set(d_ptr->cameraBin, "viewfinder-filter", d_ptr->viewfinderFilters->bin(), NULL);
+ }
+ }
+
d_ptr->listener = new QtCamGStreamerMessageListener(gst_element_get_bus(d_ptr->cameraBin),
d_ptr, this);
QObject::connect(d_ptr->listener, SIGNAL(error(const QString&, int, const QString&)),
this, SLOT(_d_error(const QString&, int, const QString&)));
- QObject::connect(d_ptr->listener, SIGNAL(started()), this, SIGNAL(started()));
- QObject::connect(d_ptr->listener, SIGNAL(stopped()), this, SIGNAL(stopped()));
+ QObject::connect(d_ptr->listener, SIGNAL(started()), this, SLOT(_d_started()));
+ QObject::connect(d_ptr->listener, SIGNAL(stopped()), this, SLOT(_d_stopped()));
+ QObject::connect(d_ptr->listener, SIGNAL(stopping()), this, SLOT(_d_stopping()));
+
+ g_signal_connect(d_ptr->cameraBin, "notify::idle",
+ G_CALLBACK(QtCamDevicePrivate::on_idle_changed), d_ptr);
+
+ if (d_ptr->wrapperVideoSource) {
+ g_signal_connect(d_ptr->wrapperVideoSource, "notify::ready-for-capture",
+ G_CALLBACK(QtCamDevicePrivate::on_ready_for_capture_changed), d_ptr);
+ }
+ else {
+ g_signal_connect(d_ptr->videoSource, "notify::ready-for-capture",
+ G_CALLBACK(QtCamDevicePrivate::on_ready_for_capture_changed), d_ptr);
+ }
d_ptr->image = new QtCamImageMode(d_ptr, this);
d_ptr->video = new QtCamVideoMode(d_ptr, this);
+
+ d_ptr->notifications = new QtCamNotifications(this, this);
}
QtCamDevice::~QtCamDevice() {
- stop();
+ stop(true);
d_ptr->image->deactivate();
d_ptr->video->deactivate();
delete d_ptr->image; d_ptr->image = 0;
delete d_ptr->video; d_ptr->video = 0;
+
+ delete d_ptr->propertySetter;
+
+ delete d_ptr->viewfinderFilters;
+
+ if (d_ptr->cameraBin) {
+ gst_object_unref(d_ptr->cameraBin);
+ }
+
delete d_ptr; d_ptr = 0;
}
}
if (!viewfinder) {
- qWarning() << "QtCamDevice: viewfinder cannot be unset.";
- return false;
- }
+ if (d_ptr->cameraBin) {
+ g_object_set(d_ptr->cameraBin, "viewfinder-sink", NULL, NULL);
+ }
- if (d_ptr->viewfinder) {
- qWarning() << "QtCamDevice: viewfinder cannot be replaced.";
- return false;
- }
+ d_ptr->sink = 0;
- if (!viewfinder->setDevice(this)) {
- return false;
+ d_ptr->viewfinder = 0;
+ return true;
}
d_ptr->viewfinder = viewfinder;
+ d_ptr->sink = 0;
return true;
}
+QtCamViewfinder *QtCamDevice::viewfinder() const {
+ return d_ptr->viewfinder;
+}
+
bool QtCamDevice::start() {
if (d_ptr->error) {
qWarning() << "Pipeline must be stopped first because of an error.";
return false;
}
+ // We need to wait for startup to complet. There's a race condition somewhere in the pipeline.
+ // If we set the scene mode to night and update the resolution while starting up
+ // then subdevsrc2 barfs:
+ // streaming task paused, reason not-negotiated (-4)
+ GstState state;
+ if (err != GST_STATE_CHANGE_ASYNC) {
+ return true;
+ }
+
+ if (gst_element_get_state(d_ptr->cameraBin, &state, 0, GST_CLOCK_TIME_NONE)
+ != GST_STATE_CHANGE_SUCCESS) {
+ // We are seriously screwed up :(
+ return false;
+ }
+
+ if (state != GST_STATE_PLAYING) {
+ // Huh ? Is this even possible ??
+ return false;
+ }
+
return true;
}
-bool QtCamDevice::stop() {
+bool QtCamDevice::stop(bool force) {
if (!d_ptr->cameraBin) {
return true;
}
if (d_ptr->error) {
gst_element_set_state(d_ptr->cameraBin, GST_STATE_NULL);
d_ptr->error = false;
+
+ d_ptr->viewfinder->stop();
+
return true;
}
}
if (!isIdle()) {
- return false;
+ if (!force) {
+ return false;
+ }
}
// First we go to ready:
// Now to NULL
gst_element_set_state(d_ptr->cameraBin, GST_STATE_NULL);
+ d_ptr->viewfinder->stop();
+
return true;
}
return d_ptr->listener;
}
+QtCamNotifications *QtCamDevice::notifications() const {
+ return d_ptr->notifications;
+}
+
#include "moc_qtcamdevice.cpp"