diff options
author | Andrew den Exter <andrew.den.exter@jollamobile.com> | 2014-07-08 15:56:05 +1000 |
---|---|---|
committer | Andrew den Exter <andrew.den.exter@qinetic.com.au> | 2014-07-12 02:46:10 +0200 |
commit | cddbe8736d995b4bfdfbbf1abfc3d6aeae3eb214 (patch) | |
tree | 8d775c9ee17902ae39aebae0d825ee3a93455135 | |
parent | 074bd6ab37bbbb4dbba188921783fd98be872555 (diff) |
Provide face and orientation info from gstreamer camera backend.
Cleans up duplicate device enumeration code so the devices listed by
the QMediaServiceProviderPlugin are the same as those in the
QVideoInputDeviceControl and includes face and orientation information
if available.
Change-Id: Iaa4c303c973bcf3e0f7c8c2fd7a7de629bccec86
Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
15 files changed, 446 insertions, 284 deletions
diff --git a/src/gsttools/qgstreamervideoinputdevicecontrol.cpp b/src/gsttools/qgstreamervideoinputdevicecontrol.cpp index e4e202caf..c26029cbf 100644 --- a/src/gsttools/qgstreamervideoinputdevicecontrol.cpp +++ b/src/gsttools/qgstreamervideoinputdevicecontrol.cpp @@ -44,43 +44,40 @@ #include <QtCore/QDir> #include <QtCore/QDebug> -#include <private/qcore_unix_p.h> -#include <linux/videodev2.h> +#include <private/qgstutils_p.h> QGstreamerVideoInputDeviceControl::QGstreamerVideoInputDeviceControl(QObject *parent) - :QVideoDeviceSelectorControl(parent), m_source(0), m_selectedDevice(0) + :QVideoDeviceSelectorControl(parent), m_factory(0), m_selectedDevice(0) { - update(); } -QGstreamerVideoInputDeviceControl::QGstreamerVideoInputDeviceControl(GstElement *source, QObject *parent) - :QVideoDeviceSelectorControl(parent), m_source(source), m_selectedDevice(0) +QGstreamerVideoInputDeviceControl::QGstreamerVideoInputDeviceControl( + GstElementFactory *factory, QObject *parent) + : QVideoDeviceSelectorControl(parent), m_factory(factory), m_selectedDevice(0) { - if (m_source) - gst_object_ref(GST_OBJECT(m_source)); - - update(); + if (m_factory) + gst_object_ref(GST_OBJECT(m_factory)); } QGstreamerVideoInputDeviceControl::~QGstreamerVideoInputDeviceControl() { - if (m_source) - gst_object_unref(GST_OBJECT(m_source)); + if (m_factory) + gst_object_unref(GST_OBJECT(m_factory)); } int QGstreamerVideoInputDeviceControl::deviceCount() const { - return m_names.size(); + return QGstUtils::enumerateCameras(m_factory).count(); } QString QGstreamerVideoInputDeviceControl::deviceName(int index) const { - return m_names[index]; + return QGstUtils::enumerateCameras(m_factory).value(index).name; } QString QGstreamerVideoInputDeviceControl::deviceDescription(int index) const { - return m_descriptions[index]; + return QGstUtils::enumerateCameras(m_factory).value(index).description; } int QGstreamerVideoInputDeviceControl::defaultDevice() const @@ -93,7 +90,6 @@ int QGstreamerVideoInputDeviceControl::selectedDevice() const return m_selectedDevice; } - void QGstreamerVideoInputDeviceControl::setSelectedDevice(int index) { if (index != m_selectedDevice) { @@ -102,60 +98,3 @@ void QGstreamerVideoInputDeviceControl::setSelectedDevice(int index) emit selectedDeviceChanged(deviceName(index)); } } - - -void QGstreamerVideoInputDeviceControl::update() -{ - m_names.clear(); - m_descriptions.clear(); - - // subdevsrc and the like have a camera-device property that takes an enumeration - // identifying a primary or secondary camera, so return identifiers that map to those - // instead of a list of actual devices. - if (m_source && g_object_class_find_property(G_OBJECT_GET_CLASS(m_source), "camera-device")) { - m_names << QLatin1String("primary") << QLatin1String("secondary"); - m_descriptions << tr("Main camera") << tr("Front camera"); - return; - } - - QDir devDir("/dev"); - devDir.setFilter(QDir::System); - - QFileInfoList entries = devDir.entryInfoList(QStringList() << "video*"); - - foreach( const QFileInfo &entryInfo, entries ) { - //qDebug() << "Try" << entryInfo.filePath(); - - int fd = qt_safe_open(entryInfo.filePath().toLatin1().constData(), O_RDWR ); - if (fd == -1) - continue; - - bool isCamera = false; - - v4l2_input input; - memset(&input, 0, sizeof(input)); - for (; ::ioctl(fd, VIDIOC_ENUMINPUT, &input) >= 0; ++input.index) { - if(input.type == V4L2_INPUT_TYPE_CAMERA || input.type == 0) { - isCamera = ::ioctl(fd, VIDIOC_S_INPUT, input.index) != 0; - break; - } - } - - if (isCamera) { - // find out its driver "name" - QString name; - struct v4l2_capability vcap; - memset(&vcap, 0, sizeof(struct v4l2_capability)); - - if (ioctl(fd, VIDIOC_QUERYCAP, &vcap) != 0) - name = entryInfo.fileName(); - else - name = QString((const char*)vcap.card); - //qDebug() << "found camera: " << name; - - m_names.append(entryInfo.filePath()); - m_descriptions.append(name); - } - qt_safe_close(fd); - } -} diff --git a/src/gsttools/qgstutils.cpp b/src/gsttools/qgstutils.cpp index 41bd005bd..9d94cb6db 100644 --- a/src/gsttools/qgstutils.cpp +++ b/src/gsttools/qgstutils.cpp @@ -42,6 +42,7 @@ #include "qgstutils_p.h" #include <QtCore/qdatetime.h> +#include <QtCore/qdir.h> #include <QtCore/qbytearray.h> #include <QtCore/qvariant.h> #include <QtCore/qsize.h> @@ -49,6 +50,11 @@ #include <QtCore/qstringlist.h> #include <qaudioformat.h> +#include <private/qcore_unix_p.h> +#include <linux/videodev2.h> + +#include "qgstreamervideoinputdevicecontrol_p.h" + QT_BEGIN_NAMESPACE //internal @@ -401,6 +407,165 @@ QMultimedia::SupportEstimate QGstUtils::hasSupport(const QString &mimeType, return QMultimedia::MaybeSupported; } +namespace { + +typedef QHash<GstElementFactory *, QVector<QGstUtils::CameraInfo> > FactoryCameraInfoMap; + +Q_GLOBAL_STATIC(FactoryCameraInfoMap, qt_camera_device_info); + +} + +QVector<QGstUtils::CameraInfo> QGstUtils::enumerateCameras(GstElementFactory *factory) +{ + FactoryCameraInfoMap::const_iterator it = qt_camera_device_info()->constFind(factory); + if (it != qt_camera_device_info()->constEnd()) + return *it; + + QVector<CameraInfo> &devices = (*qt_camera_device_info())[factory]; + + if (factory) { + bool hasVideoSource = false; + + const GType type = gst_element_factory_get_element_type(factory); + GObjectClass * const objectClass = type + ? static_cast<GObjectClass *>(g_type_class_ref(type)) + : 0; + if (objectClass) { + if (g_object_class_find_property(objectClass, "camera-device")) { + const CameraInfo primary = { + QStringLiteral("primary"), + QGstreamerVideoInputDeviceControl::primaryCamera(), + 0, + QCamera::BackFace + }; + const CameraInfo secondary = { + QStringLiteral("secondary"), + QGstreamerVideoInputDeviceControl::secondaryCamera(), + 0, + QCamera::FrontFace + }; + + devices.append(primary); + devices.append(secondary); + + GstElement *camera = g_object_class_find_property(objectClass, "sensor-mount-angle") + ? gst_element_factory_create(factory, 0) + : 0; + if (camera) { + if (gst_element_set_state(camera, GST_STATE_READY) != GST_STATE_CHANGE_SUCCESS) { + // no-op + } else for (int i = 0; i < 2; ++i) { + gint orientation = 0; + g_object_set(G_OBJECT(camera), "camera-device", i, NULL); + g_object_get(G_OBJECT(camera), "sensor-mount-angle", &orientation, NULL); + + devices[i].orientation = (720 - orientation) % 360; + } + gst_element_set_state(camera, GST_STATE_NULL); + gst_object_unref(GST_OBJECT(camera)); + + } + } else if (g_object_class_find_property(objectClass, "video-source")) { + hasVideoSource = true; + } + + g_type_class_unref(objectClass); + } + + if (!devices.isEmpty() || !hasVideoSource) { + return devices; + } + } + + QDir devDir(QStringLiteral("/dev")); + devDir.setFilter(QDir::System); + + QFileInfoList entries = devDir.entryInfoList(QStringList() + << QStringLiteral("video*")); + + foreach (const QFileInfo &entryInfo, entries) { + //qDebug() << "Try" << entryInfo.filePath(); + + int fd = qt_safe_open(entryInfo.filePath().toLatin1().constData(), O_RDWR ); + if (fd == -1) + continue; + + bool isCamera = false; + + v4l2_input input; + memset(&input, 0, sizeof(input)); + for (; ::ioctl(fd, VIDIOC_ENUMINPUT, &input) >= 0; ++input.index) { + if (input.type == V4L2_INPUT_TYPE_CAMERA || input.type == 0) { + isCamera = ::ioctl(fd, VIDIOC_S_INPUT, input.index) != 0; + break; + } + } + + if (isCamera) { + // find out its driver "name" + QString name; + struct v4l2_capability vcap; + memset(&vcap, 0, sizeof(struct v4l2_capability)); + + if (ioctl(fd, VIDIOC_QUERYCAP, &vcap) != 0) + name = entryInfo.fileName(); + else + name = QString::fromUtf8((const char*)vcap.card); + //qDebug() << "found camera: " << name; + + + CameraInfo device = { + entryInfo.absoluteFilePath(), + name, + 0, + QCamera::UnspecifiedPosition + }; + devices.append(device); + } + qt_safe_close(fd); + } + + return devices; +} + +QList<QByteArray> QGstUtils::cameraDevices(GstElementFactory * factory) +{ + QList<QByteArray> devices; + + foreach (const CameraInfo &camera, enumerateCameras(factory)) + devices.append(camera.name.toUtf8()); + + return devices; +} + +QString QGstUtils::cameraDescription(const QString &device, GstElementFactory * factory) +{ + foreach (const CameraInfo &camera, enumerateCameras(factory)) { + if (camera.name == device) + return camera.description; + } + return QString(); +} + +QCamera::Position QGstUtils::cameraPosition(const QString &device, GstElementFactory * factory) +{ + foreach (const CameraInfo &camera, enumerateCameras(factory)) { + if (camera.name == device) + return camera.position; + } + return QCamera::UnspecifiedPosition; +} + +int QGstUtils::cameraOrientation(const QString &device, GstElementFactory * factory) +{ + foreach (const CameraInfo &camera, enumerateCameras(factory)) { + if (camera.name == device) + return camera.orientation; + } + return 0; +} + + void qt_gst_object_ref_sink(gpointer object) { #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 24) diff --git a/src/multimedia/gsttools_headers/qgstreamervideoinputdevicecontrol_p.h b/src/multimedia/gsttools_headers/qgstreamervideoinputdevicecontrol_p.h index eeb576ef5..c4fe83fbc 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideoinputdevicecontrol_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideoinputdevicecontrol_p.h @@ -46,6 +46,7 @@ #include <QtCore/qstringlist.h> #include <gst/gst.h> +#include <qcamera.h> QT_BEGIN_NAMESPACE @@ -54,7 +55,7 @@ class QGstreamerVideoInputDeviceControl : public QVideoDeviceSelectorControl Q_OBJECT public: QGstreamerVideoInputDeviceControl(QObject *parent); - QGstreamerVideoInputDeviceControl(GstElement *source, QObject *parent); + QGstreamerVideoInputDeviceControl(GstElementFactory *factory, QObject *parent); ~QGstreamerVideoInputDeviceControl(); int deviceCount() const; @@ -65,17 +66,16 @@ public: int defaultDevice() const; int selectedDevice() const; + static QString primaryCamera() { return tr("Main camera"); } + static QString secondaryCamera() { return tr("Front camera"); } + public Q_SLOTS: void setSelectedDevice(int index); private: - void update(); - - GstElement *m_source; + GstElementFactory *m_factory; int m_selectedDevice; - QStringList m_names; - QStringList m_descriptions; }; QT_END_NAMESPACE diff --git a/src/multimedia/gsttools_headers/qgstutils_p.h b/src/multimedia/gsttools_headers/qgstutils_p.h index eea1e15d9..701de59da 100644 --- a/src/multimedia/gsttools_headers/qgstutils_p.h +++ b/src/multimedia/gsttools_headers/qgstutils_p.h @@ -55,8 +55,10 @@ #include <QtCore/qmap.h> #include <QtCore/qset.h> +#include <QtCore/qvector.h> #include <gst/gst.h> #include <qaudioformat.h> +#include <qcamera.h> QT_BEGIN_NAMESPACE @@ -65,6 +67,14 @@ class QVariant; class QByteArray; namespace QGstUtils { + struct CameraInfo + { + QString name; + QString description; + int orientation; + QCamera::Position position; + }; + QMap<QByteArray, QVariant> gstTagListToMap(const GstTagList *list); QSize capsResolution(const GstCaps *caps); @@ -76,6 +86,12 @@ namespace QGstUtils { QMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList &codecs, const QSet<QString> &supportedMimeTypeSet); + + QVector<CameraInfo> enumerateCameras(GstElementFactory *factory = 0); + QList<QByteArray> cameraDevices(GstElementFactory * factory = 0); + QString cameraDescription(const QString &device, GstElementFactory * factory = 0); + QCamera::Position cameraPosition(const QString &device, GstElementFactory * factory = 0); + int cameraOrientation(const QString &device, GstElementFactory * factory = 0); } void qt_gst_object_ref_sink(gpointer object); diff --git a/src/plugins/gstreamer/camerabin/camerabin.pro b/src/plugins/gstreamer/camerabin/camerabin.pro index 9efa0812a..bba797f5e 100644 --- a/src/plugins/gstreamer/camerabin/camerabin.pro +++ b/src/plugins/gstreamer/camerabin/camerabin.pro @@ -30,7 +30,8 @@ HEADERS += \ $$PWD/camerabinresourcepolicy.h \ $$PWD/camerabincapturedestination.h \ $$PWD/camerabincapturebufferformat.h \ - $$PWD/camerabinviewfindersettings.h + $$PWD/camerabinviewfindersettings.h \ + $$PWD/camerabininfocontrol.h SOURCES += \ $$PWD/camerabinserviceplugin.cpp \ @@ -48,7 +49,8 @@ SOURCES += \ $$PWD/camerabinresourcepolicy.cpp \ $$PWD/camerabincapturedestination.cpp \ $$PWD/camerabinviewfindersettings.cpp \ - $$PWD/camerabincapturebufferformat.cpp + $$PWD/camerabincapturebufferformat.cpp \ + $$PWD/camerabininfocontrol.cpp maemo6 { HEADERS += \ diff --git a/src/plugins/gstreamer/camerabin/camerabininfocontrol.cpp b/src/plugins/gstreamer/camerabin/camerabininfocontrol.cpp new file mode 100644 index 000000000..a3ee369c1 --- /dev/null +++ b/src/plugins/gstreamer/camerabin/camerabininfocontrol.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "camerabininfocontrol.h" + +#include <private/qgstutils_p.h> + +QT_BEGIN_NAMESPACE + +CameraBinInfoControl::CameraBinInfoControl(GstElementFactory *sourceFactory, QObject *parent) + : QCameraInfoControl(parent) + , m_sourceFactory(sourceFactory) +{ + gst_object_ref(GST_OBJECT(m_sourceFactory)); +} + +CameraBinInfoControl::~CameraBinInfoControl() +{ + gst_object_unref(GST_OBJECT(m_sourceFactory)); +} + +QCamera::Position CameraBinInfoControl::cameraPosition(const QString &device) const +{ + return QGstUtils::cameraPosition(device, m_sourceFactory); +} + +int CameraBinInfoControl::cameraOrientation(const QString &device) const +{ + return QGstUtils::cameraOrientation(device, m_sourceFactory); +} + +QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/camerabin/camerabininfocontrol.h b/src/plugins/gstreamer/camerabin/camerabininfocontrol.h new file mode 100644 index 000000000..577eb3f4a --- /dev/null +++ b/src/plugins/gstreamer/camerabin/camerabininfocontrol.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CAMERABININFOCONTROL_H +#define CAMERABININFOCONTROL_H + +#include <qcamerainfocontrol.h> + +#include <gst/gst.h> + +QT_BEGIN_NAMESPACE + +class CameraBinInfoControl : public QCameraInfoControl +{ + Q_OBJECT +public: + CameraBinInfoControl(GstElementFactory *sourceFactory, QObject *parent); + ~CameraBinInfoControl(); + + QCamera::Position cameraPosition(const QString &deviceName) const; + int cameraOrientation(const QString &deviceName) const; + +private: + GstElementFactory * const m_sourceFactory; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/gstreamer/camerabin/camerabinservice.cpp b/src/plugins/gstreamer/camerabin/camerabinservice.cpp index df02a9ecc..5db723696 100644 --- a/src/plugins/gstreamer/camerabin/camerabinservice.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinservice.cpp @@ -48,6 +48,7 @@ #include "camerabinimageencoder.h" #include "camerabincontrol.h" #include "camerabinmetadata.h" +#include "camerabininfocontrol.h" #ifdef HAVE_GST_PHOTOGRAPHY #include "camerabinexposure.h" @@ -89,8 +90,9 @@ QT_BEGIN_NAMESPACE -CameraBinService::CameraBinService(const QString &service, QObject *parent): - QMediaService(parent) +CameraBinService::CameraBinService(GstElementFactory *sourceFactory, QObject *parent): + QMediaService(parent), + m_cameraInfoControl(0) { m_captureSession = 0; m_metaDataControl = 0; @@ -106,40 +108,32 @@ CameraBinService::CameraBinService(const QString &service, QObject *parent): #endif m_imageCaptureControl = 0; - if (service == Q_MEDIASERVICE_CAMERA) { - m_captureSession = new CameraBinSession(this); - m_videoInputDevice = new QGstreamerVideoInputDeviceControl( - m_captureSession->buildCameraSource(), m_captureSession); - m_imageCaptureControl = new CameraBinImageCapture(m_captureSession); + m_captureSession = new CameraBinSession(sourceFactory, this); + m_videoInputDevice = new QGstreamerVideoInputDeviceControl(sourceFactory, m_captureSession); + m_imageCaptureControl = new CameraBinImageCapture(m_captureSession); - connect(m_videoInputDevice, SIGNAL(selectedDeviceChanged(QString)), - m_captureSession, SLOT(setDevice(QString))); + connect(m_videoInputDevice, SIGNAL(selectedDeviceChanged(QString)), + m_captureSession, SLOT(setDevice(QString))); - if (m_videoInputDevice->deviceCount()) - m_captureSession->setDevice(m_videoInputDevice->deviceName(m_videoInputDevice->selectedDevice())); + if (m_videoInputDevice->deviceCount()) + m_captureSession->setDevice(m_videoInputDevice->deviceName(m_videoInputDevice->selectedDevice())); #if defined(Q_WS_MAEMO_6) && defined(__arm__) && defined(HAVE_WIDGETS) - m_videoRenderer = new QGstreamerGLTextureRenderer(this); + m_videoRenderer = new QGstreamerGLTextureRenderer(this); #else - m_videoRenderer = new QGstreamerVideoRenderer(this); + m_videoRenderer = new QGstreamerVideoRenderer(this); #endif #ifdef Q_WS_MAEMO_6 - m_videoWindow = new QGstreamerVideoWindow(this, "omapxvsink"); + m_videoWindow = new QGstreamerVideoWindow(this, "omapxvsink"); #else - m_videoWindow = new QGstreamerVideoWindow(this); + m_videoWindow = new QGstreamerVideoWindow(this); #endif #if defined(HAVE_WIDGETS) - m_videoWidgetControl = new QGstreamerVideoWidgetControl(this); + m_videoWidgetControl = new QGstreamerVideoWidgetControl(this); #endif - } - if (!m_captureSession) { - qWarning() << Q_FUNC_INFO << "Service type is not supported:" << service; - return; - } - m_audioInputSelector = new QGstreamerAudioInputSelector(this); connect(m_audioInputSelector, SIGNAL(activeInputChanged(QString)), m_captureSession, SLOT(setCaptureDevice(QString))); @@ -244,6 +238,12 @@ QMediaControl *CameraBinService::requestControl(const char *name) if (qstrcmp(name, QCameraViewfinderSettingsControl_iid) == 0) return m_captureSession->viewfinderSettingsControl(); + if (qstrcmp(name, QCameraInfoControl_iid) == 0) { + if (!m_cameraInfoControl) + m_cameraInfoControl = new CameraBinInfoControl(m_captureSession->sourceFactory(), this); + return m_cameraInfoControl; + } + return 0; } diff --git a/src/plugins/gstreamer/camerabin/camerabinservice.h b/src/plugins/gstreamer/camerabin/camerabinservice.h index 7d3b3df09..4dc0f40f0 100644 --- a/src/plugins/gstreamer/camerabin/camerabinservice.h +++ b/src/plugins/gstreamer/camerabin/camerabinservice.h @@ -67,7 +67,7 @@ class CameraBinService : public QMediaService Q_OBJECT public: - CameraBinService(const QString &service, QObject *parent = 0); + CameraBinService(GstElementFactory *sourceFactory, QObject *parent = 0); virtual ~CameraBinService(); QMediaControl *requestControl(const char *name); @@ -92,6 +92,7 @@ private: QGstreamerVideoWidgetControl *m_videoWidgetControl; #endif CameraBinImageCapture *m_imageCaptureControl; + QMediaControl *m_cameraInfoControl; }; QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp b/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp index 3decd6070..bfb0c4935 100644 --- a/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinserviceplugin.cpp @@ -55,12 +55,25 @@ QT_BEGIN_NAMESPACE +template <typename T, int N> static int lengthOf(const T(&)[N]) { return N; } + +CameraBinServicePlugin::CameraBinServicePlugin() + : m_sourceFactory(0) +{ +} + +CameraBinServicePlugin::~CameraBinServicePlugin() +{ + if (m_sourceFactory) + gst_object_unref(GST_OBJECT(m_sourceFactory)); +} + QMediaService* CameraBinServicePlugin::create(const QString &key) { QGstUtils::initializeGst(); if (key == QLatin1String(Q_MEDIASERVICE_CAMERA)) - return new CameraBinService(key); + return new CameraBinService(sourceFactory()); qWarning() << "Gstreamer camerabin service plugin: unsupported key:" << key; return 0; @@ -82,40 +95,24 @@ QMediaServiceProviderHint::Features CameraBinServicePlugin::supportedFeatures( QByteArray CameraBinServicePlugin::defaultDevice(const QByteArray &service) const { - if (service == Q_MEDIASERVICE_CAMERA) { - if (m_cameraDevices.isEmpty()) - updateDevices(); - - return m_defaultCameraDevice; - } - - return QByteArray(); + return service == Q_MEDIASERVICE_CAMERA + ? QGstUtils::enumerateCameras(sourceFactory()).value(0).name.toUtf8() + : QByteArray(); } QList<QByteArray> CameraBinServicePlugin::devices(const QByteArray &service) const { - if (service == Q_MEDIASERVICE_CAMERA) { - if (m_cameraDevices.isEmpty()) - updateDevices(); - return m_cameraDevices; - } - - return QList<QByteArray>(); + return service == Q_MEDIASERVICE_CAMERA + ? QGstUtils::cameraDevices(m_sourceFactory) + : QList<QByteArray>(); } -QString CameraBinServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device) +QString CameraBinServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &deviceName) { - if (service == Q_MEDIASERVICE_CAMERA) { - if (m_cameraDevices.isEmpty()) - updateDevices(); - - for (int i=0; i<m_cameraDevices.count(); i++) - if (m_cameraDevices[i] == device) - return m_cameraDescriptions[i]; - } - - return QString(); + return service == Q_MEDIASERVICE_CAMERA + ? QGstUtils::cameraDescription(deviceName, m_sourceFactory) + : QString(); } QVariant CameraBinServicePlugin::deviceProperty(const QByteArray &service, const QByteArray &device, const QByteArray &property) @@ -126,53 +123,36 @@ QVariant CameraBinServicePlugin::deviceProperty(const QByteArray &service, const return QVariant(); } -void CameraBinServicePlugin::updateDevices() const +QCamera::Position CameraBinServicePlugin::cameraPosition(const QByteArray &deviceName) const { - m_defaultCameraDevice.clear(); - m_cameraDevices.clear(); - m_cameraDescriptions.clear(); - - QDir devDir("/dev"); - devDir.setFilter(QDir::System); - - QFileInfoList entries = devDir.entryInfoList(QStringList() << "video*"); - - foreach (const QFileInfo &entryInfo, entries) { - int fd = qt_safe_open(entryInfo.filePath().toLatin1().constData(), O_RDWR ); - if (fd == -1) - continue; - - bool isCamera = false; - - v4l2_input input; - memset(&input, 0, sizeof(input)); - for (; ::ioctl(fd, VIDIOC_ENUMINPUT, &input) >= 0; ++input.index) { - if (input.type == V4L2_INPUT_TYPE_CAMERA || input.type == 0) { - isCamera = ::ioctl(fd, VIDIOC_S_INPUT, input.index) != 0; - break; - } - } - - if (isCamera) { - // find out its driver "name" - QString name; - struct v4l2_capability vcap; - memset(&vcap, 0, sizeof(struct v4l2_capability)); + return QGstUtils::cameraPosition(deviceName, m_sourceFactory); +} - if (ioctl(fd, VIDIOC_QUERYCAP, &vcap) != 0) - name = entryInfo.fileName(); - else - name = QString((const char*)vcap.card); - //qDebug() << "found camera: " << name; +int CameraBinServicePlugin::cameraOrientation(const QByteArray &deviceName) const +{ + return QGstUtils::cameraOrientation(deviceName, m_sourceFactory); +} - m_cameraDevices.append(entryInfo.filePath().toLocal8Bit()); - m_cameraDescriptions.append(name); +GstElementFactory *CameraBinServicePlugin::sourceFactory() const +{ + if (!m_sourceFactory) { + GstElementFactory *factory = 0; + const QByteArray envCandidate = qgetenv("QT_GSTREAMER_CAMERABIN_SRC"); + if (!envCandidate.isEmpty()) + factory = gst_element_factory_find(envCandidate.constData()); + + static const char *candidates[] = { "subdevsrc", "wrappercamerabinsrc" }; + for (int i = 0; !factory && i < lengthOf(candidates); ++i) + factory = gst_element_factory_find(candidates[i]); + + if (factory) { + m_sourceFactory = GST_ELEMENT_FACTORY(gst_plugin_feature_load( + GST_PLUGIN_FEATURE(factory))); + gst_object_unref((GST_OBJECT(factory))); } - qt_safe_close(fd); } - if (!m_cameraDevices.isEmpty()) - m_defaultCameraDevice = m_cameraDevices.first(); + return m_sourceFactory; } QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/camerabin/camerabinserviceplugin.h b/src/plugins/gstreamer/camerabin/camerabinserviceplugin.h index 50ffc59b2..6b192d8ea 100644 --- a/src/plugins/gstreamer/camerabin/camerabinserviceplugin.h +++ b/src/plugins/gstreamer/camerabin/camerabinserviceplugin.h @@ -44,7 +44,9 @@ #define CAMERABINSERVICEPLUGIN_H #include <qmediaserviceproviderplugin.h> -#include <QtCore/QObject> +#include <private/qgstreamervideoinputdevicecontrol_p.h> + +#include <gst/gst.h> QT_BEGIN_NAMESPACE @@ -53,13 +55,18 @@ class CameraBinServicePlugin , public QMediaServiceSupportedDevicesInterface , public QMediaServiceDefaultDeviceInterface , public QMediaServiceFeaturesInterface + , public QMediaServiceCameraInfoInterface { Q_OBJECT Q_INTERFACES(QMediaServiceSupportedDevicesInterface) Q_INTERFACES(QMediaServiceDefaultDeviceInterface) Q_INTERFACES(QMediaServiceFeaturesInterface) + Q_INTERFACES(QMediaServiceCameraInfoInterface) Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "camerabin.json") public: + CameraBinServicePlugin(); + ~CameraBinServicePlugin(); + QMediaService* create(QString const& key); void release(QMediaService *service); @@ -70,12 +77,13 @@ public: QString deviceDescription(const QByteArray &service, const QByteArray &device); QVariant deviceProperty(const QByteArray &service, const QByteArray &device, const QByteArray &property); + QCamera::Position cameraPosition(const QByteArray &device) const; + int cameraOrientation(const QByteArray &device) const; + private: - void updateDevices() const; + GstElementFactory *sourceFactory() const; - mutable QByteArray m_defaultCameraDevice; - mutable QList<QByteArray> m_cameraDevices; - mutable QStringList m_cameraDescriptions; + mutable GstElementFactory *m_sourceFactory; }; QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp index a835b1ce5..b18e9c93c 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp @@ -119,7 +119,7 @@ QT_BEGIN_NAMESPACE -CameraBinSession::CameraBinSession(QObject *parent) +CameraBinSession::CameraBinSession(GstElementFactory *sourceFactory, QObject *parent) :QObject(parent), m_recordingActive(false), m_state(QCamera::UnloadedState), @@ -133,6 +133,7 @@ CameraBinSession::CameraBinSession(QObject *parent) m_viewfinderInterface(0), m_videoSrc(0), m_viewfinderElement(0), + m_sourceFactory(sourceFactory), m_viewfinderHasChanged(true), m_videoInputHasChanged(true), m_audioSrc(0), @@ -142,6 +143,9 @@ CameraBinSession::CameraBinSession(QObject *parent) m_audioEncoder(0), m_muxer(0) { + if (m_sourceFactory) + gst_object_ref(GST_OBJECT(m_sourceFactory)); + m_camerabin = gst_element_factory_make("camerabin2", "camerabin2"); g_signal_connect(G_OBJECT(m_camerabin), "notify::idle", G_CALLBACK(updateBusyStatus), this); qt_gst_object_ref_sink(m_camerabin); @@ -195,6 +199,9 @@ CameraBinSession::~CameraBinSession() } if (m_viewfinderElement) gst_object_unref(GST_OBJECT(m_viewfinderElement)); + + if (m_sourceFactory) + gst_object_unref(GST_OBJECT(m_sourceFactory)); } #ifdef HAVE_GST_PHOTOGRAPHY @@ -383,32 +390,17 @@ GstElement *CameraBinSession::buildCameraSource() m_videoInputHasChanged = false; GstElement *videoSrc = 0; + + if (!videoSrc) g_object_get(G_OBJECT(m_camerabin), CAMERA_SOURCE_PROPERTY, &videoSrc, NULL); - // If the QT_GSTREAMER_CAMERABIN_SRC environment variable has been set use the source - // it recommends. - const QByteArray envCandidate = qgetenv("QT_GSTREAMER_CAMERABIN_SRC"); - if (!m_videoSrc && !envCandidate.isEmpty()) { - m_videoSrc = gst_element_factory_make(envCandidate.constData(), "camera_source"); - } + if (m_sourceFactory) + m_videoSrc = gst_element_factory_create(m_sourceFactory, "camera_source"); // If gstreamer has set a default source use it. if (!m_videoSrc) m_videoSrc = videoSrc; - // If there's no better guidance try the names of some known camera source elements. - if (!m_videoSrc) { - const QList<QByteArray> candidates = QList<QByteArray>() - << "subdevsrc" - << "wrappercamerabinsrc"; - - foreach (const QByteArray &sourceElementName, candidates) { - m_videoSrc = gst_element_factory_make(sourceElementName.constData(), "camera_source"); - if (m_videoSrc) - break; - } - } - if (m_videoSrc && !m_inputDevice.isEmpty()) { #if CAMERABIN_DEBUG qDebug() << "set camera device" << m_inputDevice; diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.h b/src/plugins/gstreamer/camerabin/camerabinsession.h index 54800e9ed..836c0866a 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.h +++ b/src/plugins/gstreamer/camerabin/camerabinsession.h @@ -96,7 +96,7 @@ public: BackCamera // Main photo camera }; - CameraBinSession(QObject *parent); + CameraBinSession(GstElementFactory *sourceFactory, QObject *parent); ~CameraBinSession(); #ifdef HAVE_GST_PHOTOGRAPHY @@ -121,6 +121,7 @@ public: QString generateFileName(const QString &prefix, const QDir &dir, const QString &ext) const; GstElement *buildCameraSource(); + GstElementFactory *sourceFactory() const { return m_sourceFactory; } CameraBinControl *cameraControl() const { return m_cameraControl; } CameraBinAudioEncoder *audioEncodeControl() const { return m_audioEncodeControl; } @@ -239,6 +240,7 @@ private: GstElement *m_camerabin; GstElement *m_videoSrc; GstElement *m_viewfinderElement; + GstElementFactory *m_sourceFactory; bool m_viewfinderHasChanged; bool m_videoInputHasChanged; diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp index 8b88fbb71..6763c68e2 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp @@ -51,9 +51,6 @@ #include "qgstreamercaptureservice.h" #include <private/qgstutils_p.h> -#include <private/qcore_unix_p.h> -#include <linux/videodev2.h> - QMediaService* QGstreamerCaptureServicePlugin::create(const QString &key) { QGstUtils::initializeGst(); @@ -87,40 +84,19 @@ QMediaServiceProviderHint::Features QGstreamerCaptureServicePlugin::supportedFea QByteArray QGstreamerCaptureServicePlugin::defaultDevice(const QByteArray &service) const { - if (service == Q_MEDIASERVICE_CAMERA) { - if (m_cameraDevices.isEmpty()) - updateDevices(); - - return m_defaultCameraDevice; - } - - return QByteArray(); + return service == Q_MEDIASERVICE_CAMERA + ? QGstUtils::enumerateCameras().value(0).name.toUtf8() + : QByteArray(); } QList<QByteArray> QGstreamerCaptureServicePlugin::devices(const QByteArray &service) const { - if (service == Q_MEDIASERVICE_CAMERA) { - if (m_cameraDevices.isEmpty()) - updateDevices(); - - return m_cameraDevices; - } - - return QList<QByteArray>(); + return service == Q_MEDIASERVICE_CAMERA ? QGstUtils::cameraDevices() : QList<QByteArray>(); } QString QGstreamerCaptureServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device) { - if (service == Q_MEDIASERVICE_CAMERA) { - if (m_cameraDevices.isEmpty()) - updateDevices(); - - for (int i=0; i<m_cameraDevices.count(); i++) - if (m_cameraDevices[i] == device) - return m_cameraDescriptions[i]; - } - - return QString(); + return service == Q_MEDIASERVICE_CAMERA ? QGstUtils::cameraDescription(deviceName) : QString(); } QVariant QGstreamerCaptureServicePlugin::deviceProperty(const QByteArray &service, const QByteArray &device, const QByteArray &property) @@ -131,56 +107,6 @@ QVariant QGstreamerCaptureServicePlugin::deviceProperty(const QByteArray &servic return QVariant(); } -void QGstreamerCaptureServicePlugin::updateDevices() const -{ - m_defaultCameraDevice.clear(); - m_cameraDevices.clear(); - m_cameraDescriptions.clear(); - - QDir devDir("/dev"); - devDir.setFilter(QDir::System); - - QFileInfoList entries = devDir.entryInfoList(QStringList() << "video*"); - - foreach( const QFileInfo &entryInfo, entries ) { - //qDebug() << "Try" << entryInfo.filePath(); - - int fd = qt_safe_open(entryInfo.filePath().toLatin1().constData(), O_RDWR ); - if (fd == -1) - continue; - - bool isCamera = false; - - v4l2_input input; - memset(&input, 0, sizeof(input)); - for (; ::ioctl(fd, VIDIOC_ENUMINPUT, &input) >= 0; ++input.index) { - if(input.type == V4L2_INPUT_TYPE_CAMERA || input.type == 0) { - isCamera = ::ioctl(fd, VIDIOC_S_INPUT, input.index) != 0; - break; - } - } - - if (isCamera) { - // find out its driver "name" - QString name; - struct v4l2_capability vcap; - memset(&vcap, 0, sizeof(struct v4l2_capability)); - - if (ioctl(fd, VIDIOC_QUERYCAP, &vcap) != 0) - name = entryInfo.fileName(); - else - name = QString((const char*)vcap.card); - //qDebug() << "found camera: " << name; - - m_cameraDevices.append(entryInfo.filePath().toLocal8Bit()); - m_cameraDescriptions.append(name); - } - qt_safe_close(fd); - } - - if (!m_cameraDevices.isEmpty()) - m_defaultCameraDevice = m_cameraDevices.first(); -} #endif QMultimedia::SupportEstimate QGstreamerCaptureServicePlugin::hasSupport(const QString &mimeType, diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.h b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.h index a1141d324..a46be9ebd 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.h +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.h @@ -87,13 +87,6 @@ public: QStringList supportedMimeTypes() const; private: -#if defined(USE_GSTREAMER_CAMERA) - void updateDevices() const; - - mutable QByteArray m_defaultCameraDevice; - mutable QList<QByteArray> m_cameraDevices; - mutable QStringList m_cameraDescriptions; -#endif void updateSupportedMimeTypes() const; mutable QSet<QString> m_supportedMimeTypeSet; //for fast access |