1
/****************************************************************************
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL21$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
17
** GNU Lesser General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU Lesser
19
** General Public License version 2.1 or version 3 as published by the Free
20
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22
** following information to ensure the GNU Lesser General Public License
23
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
26
** In addition, as a special exception, Digia gives you certain additional
27
** rights. These rights are described in the Digia Qt LGPL Exception
28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
32
****************************************************************************/
34
#include "camerabincontrol.h"
35
#include "camerabincontainer.h"
36
#include "camerabinaudioencoder.h"
37
#include "camerabinvideoencoder.h"
38
#include "camerabinimageencoder.h"
39
#include "camerabinresourcepolicy.h"
41
#include <QtCore/qdebug.h>
42
#include <QtCore/qfile.h>
43
#include <QtCore/qmetaobject.h>
47
//#define CAMEABIN_DEBUG 1
48
#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
50
CameraBinControl::CameraBinControl(CameraBinSession *session)
51
:QCameraControl(session),
53
m_state(QCamera::UnloadedState),
54
m_status(QCamera::UnloadedStatus),
55
m_reloadPending(false)
57
connect(m_session, SIGNAL(stateChanged(QCamera::State)),
58
this, SLOT(updateStatus()));
60
connect(m_session, SIGNAL(viewfinderChanged()),
62
connect(m_session, SIGNAL(readyChanged(bool)),
64
connect(m_session, SIGNAL(error(int,QString)),
65
SLOT(handleCameraError(int,QString)));
67
m_resourcePolicy = new CamerabinResourcePolicy(this);
68
connect(m_resourcePolicy, SIGNAL(resourcesGranted()),
69
SLOT(handleResourcesGranted()));
70
connect(m_resourcePolicy, SIGNAL(resourcesDenied()),
71
SLOT(handleResourcesLost()));
72
connect(m_resourcePolicy, SIGNAL(resourcesLost()),
73
SLOT(handleResourcesLost()));
75
connect(m_session, SIGNAL(busyChanged(bool)),
76
SLOT(handleBusyChanged(bool)));
79
CameraBinControl::~CameraBinControl()
83
QCamera::CaptureModes CameraBinControl::captureMode() const
85
return m_session->captureMode();
88
void CameraBinControl::setCaptureMode(QCamera::CaptureModes mode)
90
if (m_session->captureMode() != mode) {
91
m_session->setCaptureMode(mode);
93
if (m_state == QCamera::ActiveState) {
94
m_resourcePolicy->setResourceSet(
95
captureMode() == QCamera::CaptureStillImage ?
96
CamerabinResourcePolicy::ImageCaptureResources :
97
CamerabinResourcePolicy::VideoCaptureResources);
98
#if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 23))
99
//due to bug in v4l2src, it's necessary to reload camera on video caps changes
100
//https://bugzilla.gnome.org/show_bug.cgi?id=649832
104
emit captureModeChanged(mode);
108
bool CameraBinControl::isCaptureModeSupported(QCamera::CaptureModes mode) const
110
return mode == QCamera::CaptureStillImage || mode == QCamera::CaptureVideo;
113
void CameraBinControl::setState(QCamera::State state)
115
#ifdef CAMEABIN_DEBUG
116
qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", state);
118
if (m_state != state) {
121
//special case for stopping the camera while it's busy,
122
//it should be delayed until the camera is idle
123
if (state == QCamera::LoadedState &&
124
m_session->state() == QCamera::ActiveState &&
125
m_session->isBusy()) {
126
#ifdef CAMEABIN_DEBUG
127
qDebug() << Q_FUNC_INFO << "Camera is busy, QCamera::stop() is delayed";
129
emit stateChanged(m_state);
133
CamerabinResourcePolicy::ResourceSet resourceSet = CamerabinResourcePolicy::NoResources;
135
case QCamera::UnloadedState:
136
resourceSet = CamerabinResourcePolicy::NoResources;
138
case QCamera::LoadedState:
139
resourceSet = CamerabinResourcePolicy::LoadedResources;
141
case QCamera::ActiveState:
142
resourceSet = captureMode() == QCamera::CaptureStillImage ?
143
CamerabinResourcePolicy::ImageCaptureResources :
144
CamerabinResourcePolicy::VideoCaptureResources;
148
m_resourcePolicy->setResourceSet(resourceSet);
150
if (m_resourcePolicy->isResourcesGranted()) {
151
//postpone changing to Active if the session is nor ready yet
152
if (state == QCamera::ActiveState) {
153
if (m_session->isReady()) {
154
m_session->setState(state);
156
#ifdef CAMEABIN_DEBUG
157
qDebug() << "Camera session is not ready yet, postpone activating";
161
m_session->setState(state);
164
emit stateChanged(m_state);
168
QCamera::State CameraBinControl::state() const
173
void CameraBinControl::updateStatus()
175
QCamera::State sessionState = m_session->state();
176
QCamera::Status oldStatus = m_status;
179
case QCamera::UnloadedState:
180
m_status = QCamera::UnloadedStatus;
182
case QCamera::LoadedState:
183
switch (sessionState) {
184
case QCamera::UnloadedState:
185
m_status = m_resourcePolicy->isResourcesGranted()
186
? QCamera::LoadingStatus
187
: QCamera::UnavailableStatus;
189
case QCamera::LoadedState:
190
m_status = QCamera::LoadedStatus;
192
case QCamera::ActiveState:
193
m_status = QCamera::ActiveStatus;
197
case QCamera::ActiveState:
198
switch (sessionState) {
199
case QCamera::UnloadedState:
200
m_status = m_resourcePolicy->isResourcesGranted()
201
? QCamera::LoadingStatus
202
: QCamera::UnavailableStatus;
204
case QCamera::LoadedState:
205
m_status = QCamera::StartingStatus;
207
case QCamera::ActiveState:
208
m_status = QCamera::ActiveStatus;
213
if (m_status != oldStatus) {
214
#ifdef CAMEABIN_DEBUG
215
qDebug() << "Camera status changed" << ENUM_NAME(QCamera, "Status", m_status);
217
emit statusChanged(m_status);
221
void CameraBinControl::reloadLater()
223
#ifdef CAMEABIN_DEBUG
224
qDebug() << "CameraBinControl: reload pipeline requested" << ENUM_NAME(QCamera, "State", m_state);
226
if (!m_reloadPending && m_state == QCamera::ActiveState) {
227
m_reloadPending = true;
229
if (!m_session->isBusy()) {
230
m_session->setState(QCamera::LoadedState);
231
QMetaObject::invokeMethod(this, "delayedReload", Qt::QueuedConnection);
236
void CameraBinControl::handleResourcesLost()
238
#ifdef CAMEABIN_DEBUG
239
qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", m_state);
241
m_session->setState(QCamera::UnloadedState);
244
void CameraBinControl::handleResourcesGranted()
246
#ifdef CAMEABIN_DEBUG
247
qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", m_state);
250
//camera will be started soon by delayedReload()
251
if (m_reloadPending && m_state == QCamera::ActiveState)
254
if (m_state == QCamera::ActiveState && m_session->isReady())
255
m_session->setState(QCamera::ActiveState);
256
else if (m_state == QCamera::LoadedState)
257
m_session->setState(QCamera::LoadedState);
260
void CameraBinControl::handleBusyChanged(bool busy)
262
if (!busy && m_session->state() == QCamera::ActiveState) {
263
if (m_state == QCamera::LoadedState) {
264
//handle delayed stop() because of busy camera
265
m_resourcePolicy->setResourceSet(CamerabinResourcePolicy::LoadedResources);
266
m_session->setState(QCamera::LoadedState);
267
} else if (m_state == QCamera::ActiveState && m_reloadPending) {
268
//handle delayed reload because of busy camera
269
m_session->setState(QCamera::LoadedState);
270
QMetaObject::invokeMethod(this, "delayedReload", Qt::QueuedConnection);
275
void CameraBinControl::handleCameraError(int errorCode, const QString &errorString)
277
emit error(errorCode, errorString);
278
setState(QCamera::UnloadedState);
281
void CameraBinControl::delayedReload()
283
#ifdef CAMEABIN_DEBUG
284
qDebug() << "CameraBinControl: reload pipeline";
286
if (m_reloadPending) {
287
m_reloadPending = false;
288
if (m_state == QCamera::ActiveState &&
289
m_session->isReady() &&
290
m_resourcePolicy->isResourcesGranted()) {
291
m_session->setState(QCamera::ActiveState);
296
bool CameraBinControl::canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const
300
switch (changeType) {
301
case QCameraControl::CaptureMode:
302
case QCameraControl::ImageEncodingSettings:
303
case QCameraControl::VideoEncodingSettings:
304
case QCameraControl::Viewfinder:
311
#define VIEWFINDER_COLORSPACE_CONVERSION 0x00000004
313
bool CameraBinControl::viewfinderColorSpaceConversion() const
316
g_object_get(G_OBJECT(m_session->cameraBin()), "flags", &flags, NULL);
318
return flags & VIEWFINDER_COLORSPACE_CONVERSION;
321
void CameraBinControl::setViewfinderColorSpaceConversion(bool enabled)
324
g_object_get(G_OBJECT(m_session->cameraBin()), "flags", &flags, NULL);
327
flags |= VIEWFINDER_COLORSPACE_CONVERSION;
329
flags &= ~VIEWFINDER_COLORSPACE_CONVERSION;
331
g_object_set(G_OBJECT(m_session->cameraBin()), "flags", flags, NULL);