~phablet-team/+junk/qtmultimedia

« back to all changes in this revision

Viewing changes to src/plugins/gstreamer/camerabin/camerabincontrol.cpp

  • Committer: Jim Hodapp
  • Date: 2015-05-15 19:17:49 UTC
  • Revision ID: jim.hodapp@canonical.com-20150515191749-r4xausjaaphme9ok
Initial import.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the Qt Toolkit.
 
7
**
 
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.
 
16
**
 
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.
 
25
**
 
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.
 
29
**
 
30
** $QT_END_LICENSE$
 
31
**
 
32
****************************************************************************/
 
33
 
 
34
#include "camerabincontrol.h"
 
35
#include "camerabincontainer.h"
 
36
#include "camerabinaudioencoder.h"
 
37
#include "camerabinvideoencoder.h"
 
38
#include "camerabinimageencoder.h"
 
39
#include "camerabinresourcepolicy.h"
 
40
 
 
41
#include <QtCore/qdebug.h>
 
42
#include <QtCore/qfile.h>
 
43
#include <QtCore/qmetaobject.h>
 
44
 
 
45
QT_BEGIN_NAMESPACE
 
46
 
 
47
//#define CAMEABIN_DEBUG 1
 
48
#define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v)))
 
49
 
 
50
CameraBinControl::CameraBinControl(CameraBinSession *session)
 
51
    :QCameraControl(session),
 
52
    m_session(session),
 
53
    m_state(QCamera::UnloadedState),
 
54
    m_status(QCamera::UnloadedStatus),
 
55
    m_reloadPending(false)
 
56
{
 
57
    connect(m_session, SIGNAL(stateChanged(QCamera::State)),
 
58
            this, SLOT(updateStatus()));
 
59
 
 
60
    connect(m_session, SIGNAL(viewfinderChanged()),
 
61
            SLOT(reloadLater()));
 
62
    connect(m_session, SIGNAL(readyChanged(bool)),
 
63
            SLOT(reloadLater()));
 
64
    connect(m_session, SIGNAL(error(int,QString)),
 
65
            SLOT(handleCameraError(int,QString)));
 
66
 
 
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()));
 
74
 
 
75
    connect(m_session, SIGNAL(busyChanged(bool)),
 
76
            SLOT(handleBusyChanged(bool)));
 
77
}
 
78
 
 
79
CameraBinControl::~CameraBinControl()
 
80
{
 
81
}
 
82
 
 
83
QCamera::CaptureModes CameraBinControl::captureMode() const
 
84
{
 
85
    return m_session->captureMode();
 
86
}
 
87
 
 
88
void CameraBinControl::setCaptureMode(QCamera::CaptureModes mode)
 
89
{
 
90
    if (m_session->captureMode() != mode) {
 
91
        m_session->setCaptureMode(mode);
 
92
 
 
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
 
101
            reloadLater();
 
102
#endif
 
103
        }
 
104
        emit captureModeChanged(mode);
 
105
    }
 
106
}
 
107
 
 
108
bool CameraBinControl::isCaptureModeSupported(QCamera::CaptureModes mode) const
 
109
{
 
110
    return mode == QCamera::CaptureStillImage || mode == QCamera::CaptureVideo;
 
111
}
 
112
 
 
113
void CameraBinControl::setState(QCamera::State state)
 
114
{
 
115
#ifdef CAMEABIN_DEBUG
 
116
    qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", state);
 
117
#endif
 
118
    if (m_state != state) {
 
119
        m_state = state;
 
120
 
 
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";
 
128
#endif
 
129
            emit stateChanged(m_state);
 
130
            return;
 
131
        }
 
132
 
 
133
        CamerabinResourcePolicy::ResourceSet resourceSet = CamerabinResourcePolicy::NoResources;
 
134
        switch (state) {
 
135
        case QCamera::UnloadedState:
 
136
            resourceSet = CamerabinResourcePolicy::NoResources;
 
137
            break;
 
138
        case QCamera::LoadedState:
 
139
            resourceSet = CamerabinResourcePolicy::LoadedResources;
 
140
            break;
 
141
        case QCamera::ActiveState:
 
142
            resourceSet = captureMode() == QCamera::CaptureStillImage ?
 
143
                            CamerabinResourcePolicy::ImageCaptureResources :
 
144
                            CamerabinResourcePolicy::VideoCaptureResources;
 
145
            break;
 
146
        }
 
147
 
 
148
        m_resourcePolicy->setResourceSet(resourceSet);
 
149
 
 
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);
 
155
                } else {
 
156
#ifdef CAMEABIN_DEBUG
 
157
                    qDebug() << "Camera session is not ready yet, postpone activating";
 
158
#endif
 
159
                }
 
160
            } else
 
161
                m_session->setState(state);
 
162
        }
 
163
 
 
164
        emit stateChanged(m_state);
 
165
    }
 
166
}
 
167
 
 
168
QCamera::State CameraBinControl::state() const
 
169
{
 
170
    return m_state;
 
171
}
 
172
 
 
173
void CameraBinControl::updateStatus()
 
174
{
 
175
    QCamera::State sessionState = m_session->state();
 
176
    QCamera::Status oldStatus = m_status;
 
177
 
 
178
    switch (m_state) {
 
179
    case QCamera::UnloadedState:
 
180
        m_status = QCamera::UnloadedStatus;
 
181
        break;
 
182
    case QCamera::LoadedState:
 
183
        switch (sessionState) {
 
184
        case QCamera::UnloadedState:
 
185
            m_status = m_resourcePolicy->isResourcesGranted()
 
186
                    ? QCamera::LoadingStatus
 
187
                    : QCamera::UnavailableStatus;
 
188
            break;
 
189
        case QCamera::LoadedState:
 
190
            m_status = QCamera::LoadedStatus;
 
191
            break;
 
192
        case QCamera::ActiveState:
 
193
            m_status = QCamera::ActiveStatus;
 
194
            break;
 
195
        }
 
196
        break;
 
197
    case QCamera::ActiveState:
 
198
        switch (sessionState) {
 
199
        case QCamera::UnloadedState:
 
200
            m_status = m_resourcePolicy->isResourcesGranted()
 
201
                    ? QCamera::LoadingStatus
 
202
                    : QCamera::UnavailableStatus;
 
203
            break;
 
204
        case QCamera::LoadedState:
 
205
            m_status = QCamera::StartingStatus;
 
206
            break;
 
207
        case QCamera::ActiveState:
 
208
            m_status = QCamera::ActiveStatus;
 
209
            break;
 
210
        }
 
211
    }
 
212
 
 
213
    if (m_status != oldStatus) {
 
214
#ifdef CAMEABIN_DEBUG
 
215
        qDebug() << "Camera status changed" << ENUM_NAME(QCamera, "Status", m_status);
 
216
#endif
 
217
        emit statusChanged(m_status);
 
218
    }
 
219
}
 
220
 
 
221
void CameraBinControl::reloadLater()
 
222
{
 
223
#ifdef CAMEABIN_DEBUG
 
224
    qDebug() << "CameraBinControl: reload pipeline requested" << ENUM_NAME(QCamera, "State", m_state);
 
225
#endif
 
226
    if (!m_reloadPending && m_state == QCamera::ActiveState) {
 
227
        m_reloadPending = true;
 
228
 
 
229
        if (!m_session->isBusy()) {
 
230
            m_session->setState(QCamera::LoadedState);
 
231
            QMetaObject::invokeMethod(this, "delayedReload", Qt::QueuedConnection);
 
232
        }
 
233
    }
 
234
}
 
235
 
 
236
void CameraBinControl::handleResourcesLost()
 
237
{
 
238
#ifdef CAMEABIN_DEBUG
 
239
    qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", m_state);
 
240
#endif
 
241
    m_session->setState(QCamera::UnloadedState);
 
242
}
 
243
 
 
244
void CameraBinControl::handleResourcesGranted()
 
245
{
 
246
#ifdef CAMEABIN_DEBUG
 
247
    qDebug() << Q_FUNC_INFO << ENUM_NAME(QCamera, "State", m_state);
 
248
#endif
 
249
 
 
250
    //camera will be started soon by delayedReload()
 
251
    if (m_reloadPending && m_state == QCamera::ActiveState)
 
252
        return;
 
253
 
 
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);
 
258
}
 
259
 
 
260
void CameraBinControl::handleBusyChanged(bool busy)
 
261
{
 
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);
 
271
        }
 
272
    }
 
273
}
 
274
 
 
275
void CameraBinControl::handleCameraError(int errorCode, const QString &errorString)
 
276
{
 
277
    emit error(errorCode, errorString);
 
278
    setState(QCamera::UnloadedState);
 
279
}
 
280
 
 
281
void CameraBinControl::delayedReload()
 
282
{
 
283
#ifdef CAMEABIN_DEBUG
 
284
    qDebug() << "CameraBinControl: reload pipeline";
 
285
#endif
 
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);
 
292
        }
 
293
    }
 
294
}
 
295
 
 
296
bool CameraBinControl::canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const
 
297
{
 
298
    Q_UNUSED(status);
 
299
 
 
300
    switch (changeType) {
 
301
    case QCameraControl::CaptureMode:
 
302
    case QCameraControl::ImageEncodingSettings:
 
303
    case QCameraControl::VideoEncodingSettings:
 
304
    case QCameraControl::Viewfinder:
 
305
        return true;
 
306
    default:
 
307
        return false;
 
308
    }
 
309
}
 
310
 
 
311
#define VIEWFINDER_COLORSPACE_CONVERSION 0x00000004
 
312
 
 
313
bool CameraBinControl::viewfinderColorSpaceConversion() const
 
314
{
 
315
    gint flags = 0;
 
316
    g_object_get(G_OBJECT(m_session->cameraBin()), "flags", &flags, NULL);
 
317
 
 
318
    return flags & VIEWFINDER_COLORSPACE_CONVERSION;
 
319
}
 
320
 
 
321
void CameraBinControl::setViewfinderColorSpaceConversion(bool enabled)
 
322
{
 
323
    gint flags = 0;
 
324
    g_object_get(G_OBJECT(m_session->cameraBin()), "flags", &flags, NULL);
 
325
 
 
326
    if (enabled)
 
327
        flags |= VIEWFINDER_COLORSPACE_CONVERSION;
 
328
    else
 
329
        flags &= ~VIEWFINDER_COLORSPACE_CONVERSION;
 
330
 
 
331
    g_object_set(G_OBJECT(m_session->cameraBin()), "flags", flags, NULL);
 
332
}
 
333
 
 
334
QT_END_NAMESPACE