diff options
Diffstat (limited to 'src')
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 |