1 #include "qtcamdevice.h"
2 #include "qtcamviewfinder.h"
3 #include "qtcamconfig.h"
4 #include "qtcamdevice_p.h"
7 #include "qtcamgstreamermessagelistener.h"
9 #include "qtcamimagemode.h"
10 #include "qtcamvideomode.h"
12 QtCamDevice::QtCamDevice(QtCamConfig *config, const QString& name,
13 const QVariant& id, QObject *parent) :
14 QObject(parent), d_ptr(new QtCamDevicePrivate) {
21 d_ptr->cameraBin = gst_element_factory_make("camerabin2", "QtCameraCameraBin");
22 if (!d_ptr->cameraBin) {
23 qCritical() << "Failed to create camerabin";
27 d_ptr->createAndAddElement(d_ptr->conf->audioSource(), "audio-source", "QtCameraAudioSrc");
28 d_ptr->createAndAddVideoSource();
31 0x00000001 /* no-audio-conversion - Do not use audio conversion elements */
32 | 0x00000002 /* no-video-conversion - Do not use video conversion elements */
33 | 0x00000004 /* no-viewfinder-conversion - Do not use viewfinder conversion elements */
34 | 0x00000008; /* no-image-conversion - Do not use image conversion elements */
36 g_object_set(d_ptr->cameraBin, "flags", flags, NULL);
38 d_ptr->setAudioCaptureCaps();
40 // TODO: audio bitrate
41 // TODO: video bitrate
44 // TODO: custom properties for jifmux, mp4mux, audio encoder, video encoder, sink & video source
45 // color tune, scene modes
46 d_ptr->listener = new QtCamGStreamerMessageListener(gst_element_get_bus(d_ptr->cameraBin),
49 QObject::connect(d_ptr->listener, SIGNAL(error(const QString&, int, const QString&)),
50 this, SLOT(_d_error(const QString&, int, const QString&)));
51 QObject::connect(d_ptr->listener, SIGNAL(started()), this, SLOT(_d_started()));
52 QObject::connect(d_ptr->listener, SIGNAL(stopped()), this, SLOT(_d_stopped()));
53 QObject::connect(d_ptr->listener, SIGNAL(stopping()), this, SLOT(_d_stopping()));
55 g_signal_connect(d_ptr->cameraBin, "notify::idle",
56 G_CALLBACK(QtCamDevicePrivate::on_idle_changed), d_ptr);
58 g_signal_connect(d_ptr->wrapperVideoSource, "notify::ready-for-capture",
59 G_CALLBACK(QtCamDevicePrivate::on_ready_for_capture_changed), d_ptr);
61 d_ptr->image = new QtCamImageMode(d_ptr, this);
62 d_ptr->video = new QtCamVideoMode(d_ptr, this);
65 QtCamDevice::~QtCamDevice() {
68 d_ptr->image->deactivate();
69 d_ptr->video->deactivate();
71 delete d_ptr->image; d_ptr->image = 0;
72 delete d_ptr->video; d_ptr->video = 0;
73 delete d_ptr; d_ptr = 0;
76 bool QtCamDevice::setViewfinder(QtCamViewfinder *viewfinder) {
78 qWarning() << "QtCamDevice: pipeline must be stopped before setting a viewfinder";
82 if (d_ptr->viewfinder == viewfinder) {
87 qWarning() << "QtCamDevice: viewfinder cannot be unset.";
91 if (d_ptr->viewfinder) {
92 qWarning() << "QtCamDevice: viewfinder cannot be replaced.";
96 if (!viewfinder->setDevice(this)) {
100 d_ptr->viewfinder = viewfinder;
105 bool QtCamDevice::start() {
107 qWarning() << "Pipeline must be stopped first because of an error.";
111 if (!d_ptr->cameraBin) {
112 qWarning() << "Missing camerabin";
116 if (!d_ptr->viewfinder) {
117 qWarning() << "Viewfinder not set";
125 if (!d_ptr->active) {
126 d_ptr->image->activate();
129 d_ptr->active->applySettings();
133 if (!d_ptr->setViewfinderSink()) {
137 GstStateChangeReturn err = gst_element_set_state(d_ptr->cameraBin, GST_STATE_PLAYING);
138 if (err == GST_STATE_CHANGE_FAILURE) {
139 qWarning() << "Failed to start camera pipeline";
143 // We need to wait for startup to complet. There's a race condition somewhere in the pipeline.
144 // If we set the scene mode to night and update the resolution while starting up
145 // then subdevsrc2 barfs:
146 // streaming task paused, reason not-negotiated (-4)
148 if (err != GST_STATE_CHANGE_ASYNC) {
152 if (gst_element_get_state(d_ptr->cameraBin, &state, 0, GST_CLOCK_TIME_NONE)
153 != GST_STATE_CHANGE_SUCCESS) {
154 // We are seriously screwed up :(
158 if (state != GST_STATE_PLAYING) {
159 // Huh ? Is this even possible ??
166 bool QtCamDevice::stop() {
167 if (!d_ptr->cameraBin) {
172 gst_element_set_state(d_ptr->cameraBin, GST_STATE_NULL);
173 d_ptr->error = false;
178 gst_element_get_state(d_ptr->cameraBin, &state, 0, GST_CLOCK_TIME_NONE);
180 if (state == GST_STATE_NULL) {
189 // First we go to ready:
190 GstStateChangeReturn st = gst_element_set_state(d_ptr->cameraBin, GST_STATE_READY);
191 if (st != GST_STATE_CHANGE_FAILURE) {
193 d_ptr->listener->flushMessages();
197 gst_element_set_state(d_ptr->cameraBin, GST_STATE_NULL);
202 bool QtCamDevice::isRunning() {
203 if (!d_ptr->cameraBin) {
208 GstStateChangeReturn err = gst_element_get_state(d_ptr->cameraBin,
209 &state, 0, GST_CLOCK_TIME_NONE);
211 if (err == GST_STATE_CHANGE_FAILURE || state != GST_STATE_PLAYING) {
218 bool QtCamDevice::isIdle() {
219 if (!d_ptr->cameraBin) {
223 gboolean idle = FALSE;
224 g_object_get(d_ptr->cameraBin, "idle", &idle, NULL);
229 QtCamImageMode *QtCamDevice::imageMode() const {
233 QtCamVideoMode *QtCamDevice::videoMode() const {
237 QtCamMode *QtCamDevice::activeMode() const {
238 return d_ptr->active;
241 QString QtCamDevice::name() const {
245 QVariant QtCamDevice::id() const {
249 QtCamConfig *QtCamDevice::config() const {
253 QtCamGStreamerMessageListener *QtCamDevice::listener() const {
254 return d_ptr->listener;
257 #include "moc_qtcamdevice.cpp"