Merge remote-tracking branch 'origin/stable' into dev
Change-Id: I42587537cadade4b3f45df18385adb760fb24430
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
OBJECTIVE_SOURCES += main.mm
|
||||
|
||||
LIBS += -framework AVFoundation
|
||||
LIBS += -framework AVFoundation -framework Foundation
|
||||
|
||||
@@ -39,9 +39,11 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
AVPlayer *player = [AVPlayer playerWithURL:[NSURL URLWithString:@"http://doesnotmatter.com"]];
|
||||
return 0;
|
||||
}
|
||||
|
||||
1
config.tests/gpu_vivante/gpu_vivante.pro
Normal file
1
config.tests/gpu_vivante/gpu_vivante.pro
Normal file
@@ -0,0 +1 @@
|
||||
SOURCES += main.cpp
|
||||
50
config.tests/gpu_vivante/main.cpp
Normal file
50
config.tests/gpu_vivante/main.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** 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 <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
const int format = GL_VIV_YV12;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -39,7 +39,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtMultimedia 5.0
|
||||
import QtMultimedia 5.2
|
||||
|
||||
Rectangle {
|
||||
id : cameraUI
|
||||
@@ -129,6 +129,7 @@ Rectangle {
|
||||
height: parent.height
|
||||
|
||||
source: camera
|
||||
autoOrientation: true
|
||||
}
|
||||
|
||||
PhotoCaptureControls {
|
||||
|
||||
@@ -140,8 +140,8 @@ void Camera::setCamera(const QByteArray &cameraDevice)
|
||||
connect(imageCapture, SIGNAL(error(int,QCameraImageCapture::Error,QString)), this,
|
||||
SLOT(displayCaptureError(int,QCameraImageCapture::Error,QString)));
|
||||
|
||||
connect(camera, SIGNAL(lockStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)),
|
||||
this, SLOT(updateLockStatus(QCamera::LockStatus, QCamera::LockChangeReason)));
|
||||
connect(camera, SIGNAL(lockStatusChanged(QCamera::LockStatus,QCamera::LockChangeReason)),
|
||||
this, SLOT(updateLockStatus(QCamera::LockStatus,QCamera::LockChangeReason)));
|
||||
|
||||
ui->captureWidget->setTabEnabled(0, (camera->isCaptureModeSupported(QCamera::CaptureStillImage)));
|
||||
ui->captureWidget->setTabEnabled(1, (camera->isCaptureModeSupported(QCamera::CaptureVideo)));
|
||||
|
||||
@@ -104,7 +104,7 @@ Player::Player(QWidget *parent)
|
||||
histogramLayout->addWidget(histogram, 1);
|
||||
|
||||
probe = new QVideoProbe(this);
|
||||
connect(probe, SIGNAL(videoFrameProbed(const QVideoFrame&)), histogram, SLOT(processFrame(QVideoFrame)));
|
||||
connect(probe, SIGNAL(videoFrameProbed(QVideoFrame)), histogram, SLOT(processFrame(QVideoFrame)));
|
||||
probe->setSource(player);
|
||||
|
||||
QPushButton *openButton = new QPushButton(tr("Open"), this);
|
||||
|
||||
@@ -27,6 +27,7 @@ win32 {
|
||||
qtCompileTest(gstreamer_appsrc)
|
||||
}
|
||||
qtCompileTest(resourcepolicy)
|
||||
qtCompileTest(gpu_vivante)
|
||||
}
|
||||
|
||||
load(qt_parts)
|
||||
|
||||
@@ -440,6 +440,18 @@ void QDeclarativeAudio::seek(int position)
|
||||
This property holds the source URL of the media.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty int QtMultimedia::Audio::loops
|
||||
|
||||
This property holds the number of times the media is played. A value of \c 0 or \c 1 means
|
||||
the media will be played only once; set to \c Audio.Infinite to enable infinite looping.
|
||||
|
||||
The value can be changed while the media is playing, in which case it will update
|
||||
the remaining loops to the new value.
|
||||
|
||||
The default is \c 1.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool QtMultimedia::Audio::autoLoad
|
||||
|
||||
@@ -1232,6 +1244,18 @@ void QDeclarativeAudio::_q_statusChanged()
|
||||
This property holds the source URL of the media.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty int QtMultimedia::MediaPlayer::loops
|
||||
|
||||
This property holds the number of times the media is played. A value of \c 0 or \c 1 means
|
||||
the media will be played only once; set to \c MediaPlayer.Infinite to enable infinite looping.
|
||||
|
||||
The value can be changed while the media is playing, in which case it will update
|
||||
the remaining loops to the new value.
|
||||
|
||||
The default is \c 1.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\qmlproperty bool QtMultimedia::MediaPlayer::autoLoad
|
||||
|
||||
|
||||
@@ -184,16 +184,20 @@ void QSoundEffect::setSource(const QUrl &url)
|
||||
/*!
|
||||
\qmlproperty int QtMultimedia::SoundEffect::loops
|
||||
|
||||
This property provides a way to control the number of times to repeat the sound on each play().
|
||||
This property holds the number of times the sound is played. A value of 0 or 1 means
|
||||
the sound will be played only once; set to SoundEffect.Infinite to enable infinite looping.
|
||||
|
||||
Set to SoundEffect.Infinite to enable infinite looping.
|
||||
The value can be changed while the sound effect is playing, in which case it will update
|
||||
the remaining loops to the new value.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\property QSoundEffect::loops
|
||||
This property provides a way to control the number of times to repeat the sound on each play().
|
||||
This property holds the number of times the sound is played. A value of 0 or 1 means
|
||||
the sound will be played only once; set to SoundEffect.Infinite to enable infinite looping.
|
||||
|
||||
Set to QSoundEffect::Infinite to enable infinite looping.
|
||||
The value can be changed while the sound effect is playing, in which case it will update
|
||||
the remaining loops to the new value.
|
||||
*/
|
||||
|
||||
/*!
|
||||
@@ -213,8 +217,14 @@ int QSoundEffect::loopCount() const
|
||||
*/
|
||||
|
||||
/*!
|
||||
Set the total number of times to repeat playing this sound effect on each play() call to \a loopCount.
|
||||
Pass \c QSoundEffect::Infinite to repeat until stop() is called.
|
||||
Set the total number of times to play this sound effect to \a loopCount.
|
||||
|
||||
Setting the loop count to 0 or 1 means the sound effect will be played only once;
|
||||
pass \c QSoundEffect::Infinite to repeat indefinitely. The loop count can be changed while
|
||||
the sound effect is playing, in which case it will update the remaining loops to
|
||||
the new \a loopCount.
|
||||
|
||||
\sa loopsRemaining()
|
||||
*/
|
||||
void QSoundEffect::setLoopCount(int loopCount)
|
||||
{
|
||||
|
||||
@@ -516,6 +516,8 @@ void QSoundEffectPrivate::setLoopCount(int loopCount)
|
||||
if (loopCount == 0)
|
||||
loopCount = 1;
|
||||
m_loopCount = loopCount;
|
||||
if (m_playing)
|
||||
setLoopsRemaining(loopCount);
|
||||
}
|
||||
|
||||
qreal QSoundEffectPrivate::volume() const
|
||||
@@ -647,7 +649,7 @@ void QSoundEffectPrivate::play()
|
||||
emptyStream();
|
||||
return;
|
||||
}
|
||||
m_runningCount = m_loopCount;
|
||||
setLoopsRemaining(m_loopCount);
|
||||
playSample();
|
||||
}
|
||||
|
||||
|
||||
@@ -172,7 +172,8 @@ void QSoundEffectPrivate::setLoopCount(int loopCount)
|
||||
if (loopCount == 0)
|
||||
loopCount = 1;
|
||||
d->m_loopCount = loopCount;
|
||||
d->m_runningCount = loopCount;
|
||||
if (d->m_playing)
|
||||
setLoopsRemaining(loopCount);
|
||||
}
|
||||
|
||||
qreal QSoundEffectPrivate::volume() const
|
||||
@@ -228,7 +229,7 @@ QSoundEffect::Status QSoundEffectPrivate::status() const
|
||||
void QSoundEffectPrivate::play()
|
||||
{
|
||||
d->m_offset = 0;
|
||||
d->m_runningCount = d->m_loopCount;
|
||||
setLoopsRemaining(d->m_loopCount);
|
||||
#ifdef QT_QAUDIO_DEBUG
|
||||
qDebug() << this << "play";
|
||||
#endif
|
||||
@@ -283,7 +284,7 @@ void QSoundEffectPrivate::setPlaying(bool playing)
|
||||
|
||||
void QSoundEffectPrivate::setLoopsRemaining(int loopsRemaining)
|
||||
{
|
||||
if (!d->m_runningCount && loopsRemaining)
|
||||
if (d->m_runningCount == loopsRemaining)
|
||||
return;
|
||||
#ifdef QT_QAUDIO_DEBUG
|
||||
qDebug() << this << "setLoopsRemaining " << loopsRemaining;
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
INCLUDEPATH += camera
|
||||
|
||||
PRIVATE_HEADERS += \
|
||||
camera/qcamera_p.h
|
||||
|
||||
PUBLIC_HEADERS += \
|
||||
camera/qcamera.h \
|
||||
camera/qcameraimagecapture.h \
|
||||
camera/qcameraexposure.h \
|
||||
camera/qcamerafocus.h \
|
||||
camera/qcameraimageprocessing.h
|
||||
camera/qcameraimageprocessing.h \
|
||||
camera/qcamerainfo.h
|
||||
|
||||
SOURCES += \
|
||||
camera/qcamera.cpp \
|
||||
camera/qcameraexposure.cpp \
|
||||
camera/qcamerafocus.cpp \
|
||||
camera/qcameraimageprocessing.cpp \
|
||||
camera/qcameraimagecapture.cpp
|
||||
camera/qcameraimagecapture.cpp \
|
||||
camera/qcamerainfo.cpp
|
||||
|
||||
|
||||
@@ -39,11 +39,11 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qvideosurfaceoutput_p.h"
|
||||
#include "qmediaobject_p.h"
|
||||
|
||||
#include "qcamera_p.h"
|
||||
#include "qmediaserviceprovider_p.h"
|
||||
|
||||
#include <qcamera.h>
|
||||
#include <qcamerainfo.h>
|
||||
#include <qcameracontrol.h>
|
||||
#include <qcameralockscontrol.h>
|
||||
#include <qcameraexposurecontrol.h>
|
||||
@@ -52,6 +52,7 @@
|
||||
#include <qcameraimageprocessingcontrol.h>
|
||||
#include <qcameraimagecapturecontrol.h>
|
||||
#include <qvideodeviceselectorcontrol.h>
|
||||
#include <qcamerainfocontrol.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
@@ -69,6 +70,7 @@ public:
|
||||
qRegisterMetaType<QCamera::LockType>("QCamera::LockType");
|
||||
qRegisterMetaType<QCamera::LockStatus>("QCamera::LockStatus");
|
||||
qRegisterMetaType<QCamera::LockChangeReason>("QCamera::LockChangeReason");
|
||||
qRegisterMetaType<QCamera::Position>("QCamera::Position");
|
||||
}
|
||||
} _registerCameraMetaTypes;
|
||||
}
|
||||
@@ -85,82 +87,16 @@ QT_BEGIN_NAMESPACE
|
||||
\ingroup multimedia
|
||||
\ingroup multimedia_camera
|
||||
|
||||
QCamera can be used with QVideoWidget for viewfinder display,
|
||||
QCamera can be used with QCameraViewfinder for viewfinder display,
|
||||
QMediaRecorder for video recording and QCameraImageCapture for image taking.
|
||||
|
||||
You can use QCameraInfo to list available cameras and choose which one to use.
|
||||
|
||||
\snippet multimedia-snippets/camera.cpp Camera selection
|
||||
|
||||
See the \l{Camera Overview}{camera overview} for more information.
|
||||
|
||||
\snippet multimedia-snippets/media.cpp Request control
|
||||
|
||||
*/
|
||||
|
||||
|
||||
class QCameraPrivate : public QMediaObjectPrivate
|
||||
{
|
||||
Q_DECLARE_NON_CONST_PUBLIC(QCamera)
|
||||
public:
|
||||
QCameraPrivate():
|
||||
QMediaObjectPrivate(),
|
||||
provider(0),
|
||||
control(0),
|
||||
deviceControl(0),
|
||||
viewfinder(0),
|
||||
capture(0),
|
||||
state(QCamera::UnloadedState),
|
||||
error(QCamera::NoError),
|
||||
supportedLocks(QCamera::NoLock),
|
||||
requestedLocks(QCamera::NoLock),
|
||||
lockStatus(QCamera::Unlocked),
|
||||
lockChangeReason(QCamera::UserRequest),
|
||||
supressLockChangedSignal(false),
|
||||
restartPending(false)
|
||||
{
|
||||
}
|
||||
|
||||
void initControls();
|
||||
|
||||
QMediaServiceProvider *provider;
|
||||
|
||||
QCameraControl *control;
|
||||
QVideoDeviceSelectorControl *deviceControl;
|
||||
QCameraLocksControl *locksControl;
|
||||
|
||||
QCameraExposure *cameraExposure;
|
||||
QCameraFocus *cameraFocus;
|
||||
QCameraImageProcessing *imageProcessing;
|
||||
|
||||
QObject *viewfinder;
|
||||
QObject *capture;
|
||||
|
||||
QCamera::State state;
|
||||
|
||||
QCamera::Error error;
|
||||
QString errorString;
|
||||
|
||||
QCamera::LockTypes supportedLocks;
|
||||
QCamera::LockTypes requestedLocks;
|
||||
|
||||
QCamera::LockStatus lockStatus;
|
||||
QCamera::LockChangeReason lockChangeReason;
|
||||
bool supressLockChangedSignal;
|
||||
|
||||
bool restartPending;
|
||||
|
||||
QVideoSurfaceOutput surfaceViewfinder;
|
||||
|
||||
void _q_error(int error, const QString &errorString);
|
||||
void unsetError() { error = QCamera::NoError; errorString.clear(); }
|
||||
|
||||
void setState(QCamera::State);
|
||||
|
||||
void _q_updateLockStatus(QCamera::LockType, QCamera::LockStatus, QCamera::LockChangeReason);
|
||||
void _q_updateState(QCamera::State newState);
|
||||
void _q_preparePropertyChange(int changeType);
|
||||
void _q_restartCamera();
|
||||
void updateLockStatus();
|
||||
};
|
||||
|
||||
|
||||
void QCameraPrivate::_q_error(int error, const QString &errorString)
|
||||
{
|
||||
Q_Q(QCamera);
|
||||
@@ -168,8 +104,6 @@ void QCameraPrivate::_q_error(int error, const QString &errorString)
|
||||
this->error = QCamera::Error(error);
|
||||
this->errorString = errorString;
|
||||
|
||||
qWarning() << "Camera error:" << errorString;
|
||||
|
||||
emit q->error(this->error);
|
||||
}
|
||||
|
||||
@@ -228,6 +162,16 @@ void QCameraPrivate::_q_restartCamera()
|
||||
}
|
||||
}
|
||||
|
||||
void QCameraPrivate::init()
|
||||
{
|
||||
Q_Q(QCamera);
|
||||
provider = QMediaServiceProvider::defaultServiceProvider();
|
||||
initControls();
|
||||
cameraExposure = new QCameraExposure(q);
|
||||
cameraFocus = new QCameraFocus(q);
|
||||
imageProcessing = new QCameraImageProcessing(q);
|
||||
}
|
||||
|
||||
void QCameraPrivate::initControls()
|
||||
{
|
||||
Q_Q(QCamera);
|
||||
@@ -238,6 +182,7 @@ void QCameraPrivate::initControls()
|
||||
control = qobject_cast<QCameraControl *>(service->requestControl(QCameraControl_iid));
|
||||
locksControl = qobject_cast<QCameraLocksControl *>(service->requestControl(QCameraLocksControl_iid));
|
||||
deviceControl = qobject_cast<QVideoDeviceSelectorControl*>(service->requestControl(QVideoDeviceSelectorControl_iid));
|
||||
infoControl = qobject_cast<QCameraInfoControl*>(service->requestControl(QCameraInfoControl_iid));
|
||||
|
||||
if (control) {
|
||||
q->connect(control, SIGNAL(stateChanged(QCamera::State)), q, SLOT(_q_updateState(QCamera::State)));
|
||||
@@ -259,12 +204,43 @@ void QCameraPrivate::initControls()
|
||||
control = 0;
|
||||
locksControl = 0;
|
||||
deviceControl = 0;
|
||||
infoControl = 0;
|
||||
|
||||
error = QCamera::ServiceMissingError;
|
||||
errorString = QCamera::tr("The camera service is missing");
|
||||
}
|
||||
}
|
||||
|
||||
void QCameraPrivate::clear()
|
||||
{
|
||||
delete cameraExposure;
|
||||
delete cameraFocus;
|
||||
delete imageProcessing;
|
||||
|
||||
if (service) {
|
||||
if (control)
|
||||
service->releaseControl(control);
|
||||
if (locksControl)
|
||||
service->releaseControl(locksControl);
|
||||
if (deviceControl)
|
||||
service->releaseControl(deviceControl);
|
||||
if (infoControl)
|
||||
service->releaseControl(infoControl);
|
||||
|
||||
provider->releaseService(service);
|
||||
}
|
||||
|
||||
cameraExposure = 0;
|
||||
cameraFocus = 0;
|
||||
imageProcessing = 0;
|
||||
control = 0;
|
||||
locksControl = 0;
|
||||
deviceControl = 0;
|
||||
infoControl = 0;
|
||||
service = 0;
|
||||
supportedLocks = 0;
|
||||
}
|
||||
|
||||
void QCameraPrivate::updateLockStatus()
|
||||
{
|
||||
Q_Q(QCamera);
|
||||
@@ -337,42 +313,103 @@ QCamera::QCamera(QObject *parent):
|
||||
QMediaServiceProvider::defaultServiceProvider()->requestService(Q_MEDIASERVICE_CAMERA))
|
||||
{
|
||||
Q_D(QCamera);
|
||||
d->provider = QMediaServiceProvider::defaultServiceProvider();
|
||||
d->initControls();
|
||||
d->cameraExposure = new QCameraExposure(this);
|
||||
d->cameraFocus = new QCameraFocus(this);
|
||||
d->imageProcessing = new QCameraImageProcessing(this);
|
||||
d->init();
|
||||
|
||||
// Select the default camera
|
||||
if (d->service != 0 && d->deviceControl)
|
||||
d->deviceControl->setSelectedDevice(d->deviceControl->defaultDevice());
|
||||
}
|
||||
|
||||
/*!
|
||||
Construct a QCamera from device name \a device and \a parent.
|
||||
Construct a QCamera from \a deviceName and \a parent.
|
||||
|
||||
If no camera with that \a deviceName exists, the camera object will
|
||||
be invalid.
|
||||
*/
|
||||
|
||||
QCamera::QCamera(const QByteArray& device, QObject *parent):
|
||||
QCamera::QCamera(const QByteArray& deviceName, QObject *parent):
|
||||
QMediaObject(*new QCameraPrivate, parent,
|
||||
QMediaServiceProvider::defaultServiceProvider()->requestService(Q_MEDIASERVICE_CAMERA, QMediaServiceProviderHint(device)))
|
||||
QMediaServiceProvider::defaultServiceProvider()->requestService(Q_MEDIASERVICE_CAMERA,
|
||||
QMediaServiceProviderHint(deviceName)))
|
||||
{
|
||||
Q_D(QCamera);
|
||||
d->provider = QMediaServiceProvider::defaultServiceProvider();
|
||||
d->initControls();
|
||||
d->init();
|
||||
|
||||
if (d->service != 0) {
|
||||
//pass device name to service
|
||||
if (d->deviceControl) {
|
||||
QString deviceName = QString::fromLatin1(device);
|
||||
|
||||
for (int i=0; i<d->deviceControl->deviceCount(); i++) {
|
||||
if (d->deviceControl->deviceName(i) == deviceName) {
|
||||
const QString name = QString::fromLatin1(deviceName);
|
||||
for (int i = 0; i < d->deviceControl->deviceCount(); i++) {
|
||||
if (d->deviceControl->deviceName(i) == name) {
|
||||
d->deviceControl->setSelectedDevice(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d->cameraExposure = new QCameraExposure(this);
|
||||
d->cameraFocus = new QCameraFocus(this);
|
||||
d->imageProcessing = new QCameraImageProcessing(this);
|
||||
/*!
|
||||
\since 5.3
|
||||
|
||||
Construct a QCamera from a camera description \a cameraInfo and \a parent.
|
||||
*/
|
||||
|
||||
QCamera::QCamera(const QCameraInfo &cameraInfo, QObject *parent)
|
||||
: QMediaObject(*new QCameraPrivate,
|
||||
parent,
|
||||
QMediaServiceProvider::defaultServiceProvider()->requestService(Q_MEDIASERVICE_CAMERA,
|
||||
QMediaServiceProviderHint(cameraInfo.deviceName().toLatin1())))
|
||||
{
|
||||
Q_D(QCamera);
|
||||
d->init();
|
||||
|
||||
if (d->service != 0 && d->deviceControl) {
|
||||
for (int i = 0; i < d->deviceControl->deviceCount(); i++) {
|
||||
if (d->deviceControl->deviceName(i) == cameraInfo.deviceName()) {
|
||||
d->deviceControl->setSelectedDevice(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.3
|
||||
|
||||
Construct a QCamera which uses a hardware camera located a the specified \a position.
|
||||
|
||||
For example on a mobile phone it can be used to easily choose between front-facing and
|
||||
back-facing cameras.
|
||||
|
||||
If no camera is available at the specified \a position or if \a position is
|
||||
QCamera::UnspecifiedPosition, the default camera is used.
|
||||
*/
|
||||
|
||||
QCamera::QCamera(QCamera::Position position, QObject *parent)
|
||||
: QMediaObject(*new QCameraPrivate,
|
||||
parent,
|
||||
QMediaServiceProvider::defaultServiceProvider()->requestService(Q_MEDIASERVICE_CAMERA, QMediaServiceProviderHint(position)))
|
||||
{
|
||||
Q_D(QCamera);
|
||||
d->init();
|
||||
|
||||
if (d->service != 0 && d->deviceControl) {
|
||||
bool selectDefault = true;
|
||||
|
||||
if (d->infoControl && position != UnspecifiedPosition) {
|
||||
for (int i = 0; i < d->deviceControl->deviceCount(); i++) {
|
||||
if (d->infoControl->cameraPosition(d->deviceControl->deviceName(i)) == position) {
|
||||
d->deviceControl->setSelectedDevice(i);
|
||||
selectDefault = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selectDefault)
|
||||
d->deviceControl->setSelectedDevice(d->deviceControl->defaultDevice());
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -382,23 +419,7 @@ QCamera::QCamera(const QByteArray& device, QObject *parent):
|
||||
QCamera::~QCamera()
|
||||
{
|
||||
Q_D(QCamera);
|
||||
delete d->cameraExposure;
|
||||
d->cameraExposure = 0;
|
||||
delete d->cameraFocus;
|
||||
d->cameraFocus = 0;
|
||||
delete d->imageProcessing;
|
||||
d->imageProcessing = 0;
|
||||
|
||||
if (d->service) {
|
||||
if (d->control)
|
||||
d->service->releaseControl(d->control);
|
||||
if (d->locksControl)
|
||||
d->service->releaseControl(d->locksControl);
|
||||
if (d->deviceControl)
|
||||
d->service->releaseControl(d->deviceControl);
|
||||
|
||||
d->provider->releaseService(d->service);
|
||||
}
|
||||
d->clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -622,9 +643,11 @@ void QCamera::unload()
|
||||
d->setState(QCamera::UnloadedState);
|
||||
}
|
||||
|
||||
|
||||
#if QT_DEPRECATED_SINCE(5, 3)
|
||||
/*!
|
||||
Returns a list of camera device's available from the default service provider.
|
||||
\deprecated
|
||||
\sa QCameraInfo::availableCameras()
|
||||
*/
|
||||
|
||||
QList<QByteArray> QCamera::availableDevices()
|
||||
@@ -634,12 +657,15 @@ QList<QByteArray> QCamera::availableDevices()
|
||||
|
||||
/*!
|
||||
Returns the description of the \a device.
|
||||
\deprecated
|
||||
\sa QCameraInfo::availableCameras(), QCameraInfo::description()
|
||||
*/
|
||||
|
||||
QString QCamera::deviceDescription(const QByteArray &device)
|
||||
{
|
||||
return QMediaServiceProvider::defaultServiceProvider()->deviceDescription(QByteArray(Q_MEDIASERVICE_CAMERA), device);
|
||||
}
|
||||
#endif
|
||||
|
||||
QCamera::State QCamera::state() const
|
||||
{
|
||||
@@ -972,6 +998,25 @@ void QCamera::unlock()
|
||||
Signal emitted when error state changes to \a value.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QCamera::Position
|
||||
\since 5.3
|
||||
|
||||
This enum specifies the physical position of the camera on the system hardware.
|
||||
|
||||
\value UnspecifiedPosition The camera position is unspecified or unknown.
|
||||
|
||||
\value BackFace The camera is on the back face of the system hardware. For example on a
|
||||
mobile device, it means it is on the opposite side to that of the screen.
|
||||
|
||||
\value FrontFace The camera is on the front face of the system hardware. For example on a
|
||||
mobile device, it means it is on the same side as that of the screen. Viewfinder frames of
|
||||
front-facing cameras are mirrored horizontally, so the users can see themselves as looking
|
||||
into a mirror. Captured images or videos are not mirrored.
|
||||
|
||||
\sa QCameraInfo::position()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QCamera::captureModeChanged(QCamera::CaptureModes mode)
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ QT_BEGIN_NAMESPACE
|
||||
class QAbstractVideoSurface;
|
||||
class QVideoWidget;
|
||||
class QGraphicsVideoItem;
|
||||
class QCameraInfo;
|
||||
|
||||
class QCameraPrivate;
|
||||
class Q_MULTIMEDIA_EXPORT QCamera : public QMediaObject
|
||||
@@ -81,6 +82,7 @@ class Q_MULTIMEDIA_EXPORT QCamera : public QMediaObject
|
||||
Q_ENUMS(LockStatus)
|
||||
Q_ENUMS(LockChangeReason)
|
||||
Q_ENUMS(LockType)
|
||||
Q_ENUMS(Position)
|
||||
public:
|
||||
enum Status {
|
||||
UnavailableStatus,
|
||||
@@ -141,12 +143,23 @@ public:
|
||||
};
|
||||
Q_DECLARE_FLAGS(LockTypes, LockType)
|
||||
|
||||
enum Position
|
||||
{
|
||||
UnspecifiedPosition,
|
||||
BackFace,
|
||||
FrontFace
|
||||
};
|
||||
|
||||
QCamera(QObject *parent = 0);
|
||||
QCamera(const QByteArray& device, QObject *parent = 0);
|
||||
QCamera(const QByteArray& deviceName, QObject *parent = 0);
|
||||
QCamera(const QCameraInfo& cameraInfo, QObject *parent = 0);
|
||||
QCamera(QCamera::Position position, QObject *parent = 0);
|
||||
~QCamera();
|
||||
|
||||
static QList<QByteArray> availableDevices();
|
||||
static QString deviceDescription(const QByteArray &device);
|
||||
#if QT_DEPRECATED_SINCE(5, 3)
|
||||
QT_DEPRECATED static QList<QByteArray> availableDevices();
|
||||
QT_DEPRECATED static QString deviceDescription(const QByteArray &device);
|
||||
#endif
|
||||
|
||||
QMultimedia::AvailabilityStatus availability() const;
|
||||
|
||||
@@ -209,6 +222,7 @@ private:
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_error(int, const QString &))
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_updateLockStatus(QCamera::LockType, QCamera::LockStatus, QCamera::LockChangeReason))
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_updateState(QCamera::State))
|
||||
friend class QCameraInfo;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QCamera::LockTypes)
|
||||
@@ -223,6 +237,7 @@ Q_DECLARE_METATYPE(QCamera::CaptureModes)
|
||||
Q_DECLARE_METATYPE(QCamera::LockType)
|
||||
Q_DECLARE_METATYPE(QCamera::LockStatus)
|
||||
Q_DECLARE_METATYPE(QCamera::LockChangeReason)
|
||||
Q_DECLARE_METATYPE(QCamera::Position)
|
||||
|
||||
Q_MEDIA_ENUM_DEBUG(QCamera, State)
|
||||
Q_MEDIA_ENUM_DEBUG(QCamera, Status)
|
||||
@@ -231,5 +246,6 @@ Q_MEDIA_ENUM_DEBUG(QCamera, CaptureMode)
|
||||
Q_MEDIA_ENUM_DEBUG(QCamera, LockType)
|
||||
Q_MEDIA_ENUM_DEBUG(QCamera, LockStatus)
|
||||
Q_MEDIA_ENUM_DEBUG(QCamera, LockChangeReason)
|
||||
Q_MEDIA_ENUM_DEBUG(QCamera, Position)
|
||||
|
||||
#endif // QCAMERA_H
|
||||
|
||||
141
src/multimedia/camera/qcamera_p.h
Normal file
141
src/multimedia/camera/qcamera_p.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** 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 QCAMERA_P_H
|
||||
#define QCAMERA_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qmediaobject_p.h"
|
||||
#include "qvideosurfaceoutput_p.h"
|
||||
#include "qcamera.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QMediaServiceProvider;
|
||||
class QCameraControl;
|
||||
class QVideoDeviceSelectorControl;
|
||||
class QCameraLocksControl;
|
||||
class QCameraInfoControl;
|
||||
|
||||
class QCameraPrivate : public QMediaObjectPrivate
|
||||
{
|
||||
Q_DECLARE_NON_CONST_PUBLIC(QCamera)
|
||||
public:
|
||||
QCameraPrivate():
|
||||
QMediaObjectPrivate(),
|
||||
provider(0),
|
||||
control(0),
|
||||
deviceControl(0),
|
||||
locksControl(0),
|
||||
infoControl(0),
|
||||
viewfinder(0),
|
||||
capture(0),
|
||||
state(QCamera::UnloadedState),
|
||||
error(QCamera::NoError),
|
||||
supportedLocks(QCamera::NoLock),
|
||||
requestedLocks(QCamera::NoLock),
|
||||
lockStatus(QCamera::Unlocked),
|
||||
lockChangeReason(QCamera::UserRequest),
|
||||
supressLockChangedSignal(false),
|
||||
restartPending(false)
|
||||
{
|
||||
}
|
||||
|
||||
void init();
|
||||
void initControls();
|
||||
|
||||
void clear();
|
||||
|
||||
QMediaServiceProvider *provider;
|
||||
|
||||
QCameraControl *control;
|
||||
QVideoDeviceSelectorControl *deviceControl;
|
||||
QCameraLocksControl *locksControl;
|
||||
QCameraInfoControl *infoControl;
|
||||
|
||||
QCameraExposure *cameraExposure;
|
||||
QCameraFocus *cameraFocus;
|
||||
QCameraImageProcessing *imageProcessing;
|
||||
|
||||
QObject *viewfinder;
|
||||
QObject *capture;
|
||||
|
||||
QCamera::State state;
|
||||
|
||||
QCamera::Error error;
|
||||
QString errorString;
|
||||
|
||||
QCamera::LockTypes supportedLocks;
|
||||
QCamera::LockTypes requestedLocks;
|
||||
|
||||
QCamera::LockStatus lockStatus;
|
||||
QCamera::LockChangeReason lockChangeReason;
|
||||
bool supressLockChangedSignal;
|
||||
|
||||
bool restartPending;
|
||||
|
||||
QVideoSurfaceOutput surfaceViewfinder;
|
||||
|
||||
void _q_error(int error, const QString &errorString);
|
||||
void unsetError() { error = QCamera::NoError; errorString.clear(); }
|
||||
|
||||
void setState(QCamera::State);
|
||||
|
||||
void _q_updateLockStatus(QCamera::LockType, QCamera::LockStatus, QCamera::LockChangeReason);
|
||||
void _q_updateState(QCamera::State newState);
|
||||
void _q_preparePropertyChange(int changeType);
|
||||
void _q_restartCamera();
|
||||
void updateLockStatus();
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QCAMERA_P_H
|
||||
@@ -159,6 +159,7 @@ Q_SIGNALS:
|
||||
|
||||
private:
|
||||
friend class QCamera;
|
||||
friend class QCameraPrivate;
|
||||
explicit QCameraExposure(QCamera *parent = 0);
|
||||
virtual ~QCameraExposure();
|
||||
|
||||
|
||||
@@ -156,6 +156,7 @@ Q_SIGNALS:
|
||||
|
||||
private:
|
||||
friend class QCamera;
|
||||
friend class QCameraPrivate;
|
||||
QCameraFocus(QCamera *camera);
|
||||
~QCameraFocus();
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ public:
|
||||
|
||||
private:
|
||||
friend class QCamera;
|
||||
friend class QCameraPrivate;
|
||||
QCameraImageProcessing(QCamera *camera);
|
||||
~QCameraImageProcessing();
|
||||
|
||||
|
||||
289
src/multimedia/camera/qcamerainfo.cpp
Normal file
289
src/multimedia/camera/qcamerainfo.cpp
Normal file
@@ -0,0 +1,289 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** 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 "qcamerainfo.h"
|
||||
|
||||
#include "qcamera_p.h"
|
||||
#include "qmediaserviceprovider_p.h"
|
||||
|
||||
#include <qvideodeviceselectorcontrol.h>
|
||||
#include <qcamerainfocontrol.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QCameraInfo
|
||||
\brief The QCameraInfo class provides general information about camera devices.
|
||||
\since 5.3
|
||||
\inmodule QtMultimedia
|
||||
\ingroup multimedia
|
||||
\ingroup multimedia_camera
|
||||
|
||||
QCameraInfo lets you query for camera devices that are currently available on the system.
|
||||
|
||||
The static functions defaultCamera() and availableCameras() provide you a list of all
|
||||
available cameras.
|
||||
|
||||
This example prints the name of all available cameras:
|
||||
|
||||
\snippet multimedia-snippets/camera.cpp Camera listing
|
||||
|
||||
A QCameraInfo can be used to construct a QCamera. The following example instantiates a QCamera
|
||||
whose camera device is named 'mycamera':
|
||||
|
||||
\snippet multimedia-snippets/camera.cpp Camera selection
|
||||
|
||||
You can also use QCameraInfo to get general information about a camera device such as
|
||||
description, physical position on the system, or camera sensor orientation.
|
||||
|
||||
\snippet multimedia-snippets/camera.cpp Camera info
|
||||
|
||||
\sa QCamera
|
||||
*/
|
||||
|
||||
class QCameraInfoPrivate
|
||||
{
|
||||
public:
|
||||
QCameraInfoPrivate() : isNull(true), position(QCamera::UnspecifiedPosition), orientation(0)
|
||||
{ }
|
||||
|
||||
bool isNull;
|
||||
QString deviceName;
|
||||
QString description;
|
||||
QCamera::Position position;
|
||||
int orientation;
|
||||
};
|
||||
|
||||
/*!
|
||||
Constructs a camera info object for \a camera.
|
||||
|
||||
You can use it to query information about the \a camera object passed as argument.
|
||||
|
||||
If the \a camera is invalid, for example when no camera device is available on the system,
|
||||
the QCameraInfo object will be invalid and isNull() will return true.
|
||||
*/
|
||||
QCameraInfo::QCameraInfo(const QCamera &camera)
|
||||
: d(new QCameraInfoPrivate)
|
||||
{
|
||||
const QVideoDeviceSelectorControl *deviceControl = camera.d_func()->deviceControl;
|
||||
if (deviceControl) {
|
||||
const int selectedDevice = deviceControl->selectedDevice();
|
||||
d->deviceName = deviceControl->deviceName(selectedDevice);
|
||||
d->description = deviceControl->deviceDescription(selectedDevice);
|
||||
d->isNull = false;
|
||||
}
|
||||
|
||||
const QCameraInfoControl *infoControl = camera.d_func()->infoControl;
|
||||
if (infoControl) {
|
||||
d->position = infoControl->cameraPosition(d->deviceName);
|
||||
d->orientation = infoControl->cameraOrientation(d->deviceName);
|
||||
d->isNull = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a camera info object from a camera device \a name.
|
||||
|
||||
If no such device exists, the QCameraInfo object will be invalid and isNull() will return true.
|
||||
*/
|
||||
QCameraInfo::QCameraInfo(const QByteArray &name)
|
||||
: d(new QCameraInfoPrivate)
|
||||
{
|
||||
if (!name.isNull()) {
|
||||
QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider();
|
||||
const QByteArray service(Q_MEDIASERVICE_CAMERA);
|
||||
if (provider->devices(service).contains(name)) {
|
||||
d->deviceName = QString::fromLatin1(name);
|
||||
d->description = provider->deviceDescription(service, name);
|
||||
d->position = provider->cameraPosition(name);
|
||||
d->orientation = provider->cameraOrientation(name);
|
||||
d->isNull = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a copy of \a other.
|
||||
*/
|
||||
QCameraInfo::QCameraInfo(const QCameraInfo &other)
|
||||
: d(other.d)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys the QCameraInfo.
|
||||
*/
|
||||
QCameraInfo::~QCameraInfo()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if this QCameraInfo is equal to \a other.
|
||||
*/
|
||||
bool QCameraInfo::operator==(const QCameraInfo &other) const
|
||||
{
|
||||
if (d == other.d)
|
||||
return true;
|
||||
|
||||
return (d->deviceName == other.d->deviceName
|
||||
&& d->description == other.d->description
|
||||
&& d->position == other.d->position
|
||||
&& d->orientation == other.d->orientation);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if this QCameraInfo is null or invalid.
|
||||
*/
|
||||
bool QCameraInfo::isNull() const
|
||||
{
|
||||
return d->isNull;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the device name of the camera
|
||||
|
||||
This is a unique ID to identify the camera and may not be human-readable.
|
||||
*/
|
||||
QString QCameraInfo::deviceName() const
|
||||
{
|
||||
return d->deviceName;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the human-readable description of the camera.
|
||||
*/
|
||||
QString QCameraInfo::description() const
|
||||
{
|
||||
return d->description;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the physical position of the camera on the hardware system.
|
||||
*/
|
||||
QCamera::Position QCameraInfo::position() const
|
||||
{
|
||||
return d->position;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the physical orientation of the camera sensor.
|
||||
|
||||
The value is the orientation angle (clockwise, in steps of 90 degrees) of the camera sensor
|
||||
in relation to the display in its natural orientation.
|
||||
|
||||
You can show the camera image in the correct orientation by rotating it by this value in the
|
||||
anti-clockwise direction.
|
||||
|
||||
For example, suppose a mobile device which is naturally in portrait orientation. The back-facing
|
||||
camera is mounted in landscape. If the top side of the camera sensor is aligned with the
|
||||
right edge of the screen in natural orientation, the value should be 270. If the top side of a
|
||||
front-facing camera sensor is aligned with the right of the screen, the value should be 90.
|
||||
*/
|
||||
int QCameraInfo::orientation() const
|
||||
{
|
||||
return d->orientation;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the default camera on the system.
|
||||
|
||||
The returned object should be checked using isNull() before being used, in case there is no
|
||||
default camera or no cameras at all.
|
||||
|
||||
\sa availableCameras()
|
||||
*/
|
||||
QCameraInfo QCameraInfo::defaultCamera()
|
||||
{
|
||||
return QCameraInfo(QMediaServiceProvider::defaultServiceProvider()->defaultDevice(Q_MEDIASERVICE_CAMERA));
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a list of available cameras on the system which are located at \a position.
|
||||
|
||||
If \a position is not specified or if the value is QCamera::UnspecifiedPosition, a list of
|
||||
all available cameras will be returned.
|
||||
*/
|
||||
QList<QCameraInfo> QCameraInfo::availableCameras(QCamera::Position position)
|
||||
{
|
||||
QList<QCameraInfo> cameras;
|
||||
|
||||
const QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider();
|
||||
const QByteArray service(Q_MEDIASERVICE_CAMERA);
|
||||
const QList<QByteArray> devices = provider->devices(service);
|
||||
for (int i = 0; i < devices.count(); ++i) {
|
||||
const QByteArray &name = devices.at(i);
|
||||
if (position == QCamera::UnspecifiedPosition
|
||||
|| position == provider->cameraPosition(name)) {
|
||||
cameras.append(QCameraInfo(name));
|
||||
}
|
||||
}
|
||||
|
||||
return cameras;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the QCameraInfo object to be equal to \a other.
|
||||
*/
|
||||
QCameraInfo& QCameraInfo::operator=(const QCameraInfo& other)
|
||||
{
|
||||
d = other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QCameraInfo::operator!=(const QCameraInfo &other) const
|
||||
|
||||
Returns true if this QCameraInfo is different from \a other.
|
||||
*/
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
QDebug operator<<(QDebug d, const QCameraInfo &camera)
|
||||
{
|
||||
d.maybeSpace() << QStringLiteral("QCameraInfo(deviceName=%1, position=%2, orientation=%3)")
|
||||
.arg(camera.deviceName())
|
||||
.arg(QString::fromLatin1(QCamera::staticMetaObject.enumerator(QCamera::staticMetaObject.indexOfEnumerator("Position"))
|
||||
.valueToKey(camera.position())))
|
||||
.arg(camera.orientation());
|
||||
return d.space();
|
||||
}
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE
|
||||
86
src/multimedia/camera/qcamerainfo.h
Normal file
86
src/multimedia/camera/qcamerainfo.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** 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 QCAMERAINFO_H
|
||||
#define QCAMERAINFO_H
|
||||
|
||||
#include <QtMultimedia/qcamera.h>
|
||||
#include <QtCore/qsharedpointer.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QCameraInfoPrivate;
|
||||
|
||||
class Q_MULTIMEDIA_EXPORT QCameraInfo
|
||||
{
|
||||
public:
|
||||
explicit QCameraInfo(const QByteArray &name = QByteArray());
|
||||
explicit QCameraInfo(const QCamera &camera);
|
||||
QCameraInfo(const QCameraInfo& other);
|
||||
~QCameraInfo();
|
||||
|
||||
QCameraInfo& operator=(const QCameraInfo& other);
|
||||
bool operator==(const QCameraInfo &other) const;
|
||||
inline bool operator!=(const QCameraInfo &other) const;
|
||||
|
||||
bool isNull() const;
|
||||
|
||||
QString deviceName() const;
|
||||
QString description() const;
|
||||
QCamera::Position position() const;
|
||||
int orientation() const;
|
||||
|
||||
static QCameraInfo defaultCamera();
|
||||
static QList<QCameraInfo> availableCameras(QCamera::Position position = QCamera::UnspecifiedPosition);
|
||||
|
||||
private:
|
||||
QSharedPointer<QCameraInfoPrivate> d;
|
||||
};
|
||||
|
||||
bool QCameraInfo::operator!=(const QCameraInfo &other) const { return !operator==(other); }
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
Q_MULTIMEDIA_EXPORT QDebug operator<<(QDebug, const QCameraInfo&);
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QCAMERAINFO_H
|
||||
@@ -9,6 +9,7 @@ PUBLIC_HEADERS += \
|
||||
controls/qcameracapturebufferformatcontrol.h \
|
||||
controls/qcameracapturedestinationcontrol.h \
|
||||
controls/qcameracontrol.h \
|
||||
controls/qcamerainfocontrol.h \
|
||||
controls/qcameraexposurecontrol.h \
|
||||
controls/qcamerafeedbackcontrol.h \
|
||||
controls/qcameraflashcontrol.h \
|
||||
@@ -45,6 +46,7 @@ SOURCES += \
|
||||
controls/qcameracapturebufferformatcontrol.cpp \
|
||||
controls/qcameracapturedestinationcontrol.cpp \
|
||||
controls/qcameracontrol.cpp \
|
||||
controls/qcamerainfocontrol.cpp \
|
||||
controls/qcameraexposurecontrol.cpp \
|
||||
controls/qcamerafeedbackcontrol.cpp \
|
||||
controls/qcameraflashcontrol.cpp \
|
||||
@@ -79,4 +81,3 @@ SOURCES += \
|
||||
controls/qaudiooutputselectorcontrol.cpp \
|
||||
controls/qvideodeviceselectorcontrol.cpp
|
||||
|
||||
|
||||
|
||||
104
src/multimedia/controls/qcamerainfocontrol.cpp
Normal file
104
src/multimedia/controls/qcamerainfocontrol.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** 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 "qcamerainfocontrol.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QCameraInfoControl
|
||||
\since 5.3
|
||||
|
||||
\brief The QCameraInfoControl class provides a camera info media control.
|
||||
\inmodule QtMultimedia
|
||||
|
||||
\ingroup multimedia_control
|
||||
|
||||
The QCameraInfoControl class provides information about the camera devices
|
||||
available on the system.
|
||||
|
||||
The interface name of QCameraInfoControl is \c org.qt-project.qt.camerainfocontrol/5.3 as
|
||||
defined in QCameraInfoControl_iid.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\macro QCameraInfoControl_iid
|
||||
|
||||
\c org.qt-project.qt.camerainfocontrol/5.3
|
||||
|
||||
Defines the interface name of the QCameraInfoControl class.
|
||||
|
||||
\relates QVideoDeviceSelectorControl
|
||||
*/
|
||||
|
||||
/*!
|
||||
Constructs a camera info control with the given \a parent.
|
||||
*/
|
||||
QCameraInfoControl::QCameraInfoControl(QObject *parent)
|
||||
: QMediaControl(parent)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys a camera info control.
|
||||
*/
|
||||
QCameraInfoControl::~QCameraInfoControl()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QCameraInfoControl::cameraPosition(const QString &deviceName) const
|
||||
|
||||
Returns the physical position of the camera named \a deviceName on the hardware system.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QCameraInfoControl::cameraOrientation(const QString &deviceName) const
|
||||
|
||||
Returns the physical orientation of the sensor for the camera named \a deviceName.
|
||||
|
||||
The value is the orientation angle (clockwise, in steps of 90 degrees) of the camera sensor
|
||||
in relation to the display in its natural orientation.
|
||||
*/
|
||||
|
||||
#include "moc_qcamerainfocontrol.cpp"
|
||||
|
||||
QT_END_NAMESPACE
|
||||
71
src/multimedia/controls/qcamerainfocontrol.h
Normal file
71
src/multimedia/controls/qcamerainfocontrol.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** 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 QCAMERAINFOCONTROL_H
|
||||
#define QCAMERAINFOCONTROL_H
|
||||
|
||||
#include <QtMultimedia/qcamera.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// Required for QDoc workaround
|
||||
class QString;
|
||||
|
||||
class Q_MULTIMEDIA_EXPORT QCameraInfoControl : public QMediaControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
virtual ~QCameraInfoControl();
|
||||
|
||||
virtual QCamera::Position cameraPosition(const QString &deviceName) const = 0;
|
||||
virtual int cameraOrientation(const QString &deviceName) const = 0;
|
||||
|
||||
protected:
|
||||
QCameraInfoControl(QObject *parent = 0);
|
||||
};
|
||||
|
||||
#define QCameraInfoControl_iid "org.qt-project.qt.camerainfocontrol/5.3"
|
||||
Q_MEDIA_DECLARE_CONTROL(QCameraInfoControl, QCameraInfoControl_iid)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QCAMERAINFOCONTROL_H
|
||||
@@ -42,11 +42,15 @@
|
||||
/* Camera snippets */
|
||||
|
||||
#include "qcamera.h"
|
||||
#include "qcamerainfo.h"
|
||||
#include "qcameraviewfinder.h"
|
||||
#include "qmediarecorder.h"
|
||||
#include "qcameraimagecapture.h"
|
||||
#include "qcameraimageprocessing.h"
|
||||
#include "qabstractvideosurface.h"
|
||||
#include <QtGui/qscreen.h>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <QtGui/qimage.h>
|
||||
|
||||
/* Globals so that everything is consistent. */
|
||||
QCamera *camera = 0;
|
||||
@@ -94,6 +98,32 @@ void overview_surface()
|
||||
//! [Camera overview surface]
|
||||
}
|
||||
|
||||
void overview_viewfinder_orientation()
|
||||
{
|
||||
QCamera camera;
|
||||
|
||||
//! [Camera overview viewfinder orientation]
|
||||
// Assuming a QImage has been created from the QVideoFrame that needs to be presented
|
||||
QImage videoFrame;
|
||||
QCameraInfo cameraInfo(camera); // needed to get the camera sensor position and orientation
|
||||
|
||||
// Get the current display orientation
|
||||
const QScreen *screen = QGuiApplication::primaryScreen();
|
||||
const int screenAngle = screen->angleBetween(screen->nativeOrientation(), screen->orientation());
|
||||
|
||||
int rotation;
|
||||
if (cameraInfo.position() == QCamera::BackFace) {
|
||||
rotation = (cameraInfo.orientation() - screenAngle) % 360;
|
||||
} else {
|
||||
// Front position, compensate the mirror
|
||||
rotation = (360 - cameraInfo.orientation() + screenAngle) % 360;
|
||||
}
|
||||
|
||||
// Rotate the frame so it always shows in the correct orientation
|
||||
videoFrame = videoFrame.transformed(QTransform().rotate(rotation));
|
||||
//! [Camera overview viewfinder orientation]
|
||||
}
|
||||
|
||||
void overview_still()
|
||||
{
|
||||
//! [Camera overview capture]
|
||||
@@ -130,6 +160,41 @@ void overview_movie()
|
||||
//! [Camera overview movie]
|
||||
}
|
||||
|
||||
void camera_listing()
|
||||
{
|
||||
//! [Camera listing]
|
||||
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
|
||||
foreach (const QCameraInfo &cameraInfo, cameras)
|
||||
qDebug() << cameraInfo.deviceName();
|
||||
//! [Camera listing]
|
||||
}
|
||||
|
||||
void camera_selection()
|
||||
{
|
||||
//! [Camera selection]
|
||||
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
|
||||
foreach (const QCameraInfo &cameraInfo, cameras) {
|
||||
if (cameraInfo.deviceName() == "mycamera")
|
||||
camera = new QCamera(cameraInfo);
|
||||
}
|
||||
//! [Camera selection]
|
||||
}
|
||||
|
||||
void camera_info()
|
||||
{
|
||||
//! [Camera info]
|
||||
QCamera myCamera;
|
||||
QCameraInfo cameraInfo(myCamera);
|
||||
|
||||
if (cameraInfo.position() == QCamera::FrontFace)
|
||||
qDebug() << "The camera is on the front face of the hardware system.";
|
||||
else if (cameraInfo.position() == QCamera::BackFace)
|
||||
qDebug() << "The camera is on the back face of the hardware system.";
|
||||
|
||||
qDebug() << "The camera sensor orientation is " << cameraInfo.orientation() << " degrees.";
|
||||
//! [Camera info]
|
||||
}
|
||||
|
||||
void camera_blah()
|
||||
{
|
||||
//! [Camera]
|
||||
|
||||
@@ -118,7 +118,7 @@ VideoOutput {
|
||||
\endqml
|
||||
|
||||
In C++, your choice depends on whether you are using widgets, or QGraphicsView.
|
||||
The \l QVideoWidget class is used in the widgets case, and \l QGraphicsVideoItem
|
||||
The \l QCameraViewfinder class is used in the widgets case, and \l QGraphicsVideoItem
|
||||
is useful for QGraphicsView.
|
||||
|
||||
\snippet multimedia-snippets/camera.cpp Camera overview viewfinder
|
||||
@@ -130,6 +130,15 @@ need to render the viewfinder image yourself.
|
||||
|
||||
\snippet multimedia-snippets/camera.cpp Camera overview surface
|
||||
|
||||
On mobile devices, the viewfinder image might not always be in the orientation you would expect.
|
||||
The camera sensors on these devices are often mounted in landscape while the natural
|
||||
orientation of the screen is portrait. This results in the image appearing sideways or inverted
|
||||
depending on the device orientation. In order to reflect on screen what the user actually sees, you
|
||||
should make sure the viewfinder frames are always rotated to the correct orientation, taking into
|
||||
account the camera sensor orientation and the current display orientation.
|
||||
|
||||
\snippet multimedia-snippets/camera.cpp Camera overview viewfinder orientation
|
||||
|
||||
\section2 Still Images
|
||||
|
||||
After setting up a viewfinder and finding something photogenic,
|
||||
|
||||
@@ -58,7 +58,7 @@ class QMediaServiceProviderHintPrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
QMediaServiceProviderHintPrivate(QMediaServiceProviderHint::Type type)
|
||||
:type(type), features(0)
|
||||
:type(type), cameraPosition(QCamera::UnspecifiedPosition), features(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ public:
|
||||
:QSharedData(other),
|
||||
type(other.type),
|
||||
device(other.device),
|
||||
cameraPosition(other.cameraPosition),
|
||||
mimeType(other.mimeType),
|
||||
codecs(other.codecs),
|
||||
features(other.features)
|
||||
@@ -78,6 +79,7 @@ public:
|
||||
|
||||
QMediaServiceProviderHint::Type type;
|
||||
QByteArray device;
|
||||
QCamera::Position cameraPosition;
|
||||
QString mimeType;
|
||||
QStringList codecs;
|
||||
QMediaServiceProviderHint::Features features;
|
||||
@@ -129,6 +131,7 @@ public:
|
||||
\value ContentType Select media service most suitable for certain content type.
|
||||
\value Device Select media service which supports certain device.
|
||||
\value SupportedFeatures Select media service supporting the set of optional features.
|
||||
\value CameraPosition Select media service having a camera at a specified position.
|
||||
*/
|
||||
|
||||
|
||||
@@ -164,6 +167,19 @@ QMediaServiceProviderHint::QMediaServiceProviderHint(const QByteArray &device)
|
||||
d->device = device;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.3
|
||||
|
||||
Constructs a CameraPosition media service provider hint.
|
||||
|
||||
This type of hint describes a media service that has a camera in the specific \a position.
|
||||
*/
|
||||
QMediaServiceProviderHint::QMediaServiceProviderHint(QCamera::Position position)
|
||||
:d(new QMediaServiceProviderHintPrivate(CameraPosition))
|
||||
{
|
||||
d->cameraPosition = position;
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a SupportedFeatures media service provider hint.
|
||||
|
||||
@@ -209,6 +225,7 @@ bool QMediaServiceProviderHint::operator == (const QMediaServiceProviderHint &ot
|
||||
return (d == other.d) ||
|
||||
(d->type == other.d->type &&
|
||||
d->device == other.d->device &&
|
||||
d->cameraPosition == other.d->cameraPosition &&
|
||||
d->mimeType == other.d->mimeType &&
|
||||
d->codecs == other.d->codecs &&
|
||||
d->features == other.d->features);
|
||||
@@ -264,6 +281,17 @@ QByteArray QMediaServiceProviderHint::device() const
|
||||
return d->device;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.3
|
||||
|
||||
Returns the camera's position a media service is expected to utilize.
|
||||
*/
|
||||
QCamera::Position QMediaServiceProviderHint::cameraPosition() const
|
||||
{
|
||||
return d->cameraPosition;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Returns a set of features a media service is expected to provide.
|
||||
*/
|
||||
@@ -349,6 +377,29 @@ public:
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QMediaServiceProviderHint::CameraPosition: {
|
||||
plugin = plugins[0];
|
||||
if (type == QByteArray(Q_MEDIASERVICE_CAMERA)
|
||||
&& hint.cameraPosition() != QCamera::UnspecifiedPosition) {
|
||||
foreach (QMediaServiceProviderPlugin *currentPlugin, plugins) {
|
||||
const QMediaServiceSupportedDevicesInterface *deviceIface =
|
||||
qobject_cast<QMediaServiceSupportedDevicesInterface*>(currentPlugin);
|
||||
const QMediaServiceCameraInfoInterface *cameraIface =
|
||||
qobject_cast<QMediaServiceCameraInfoInterface*>(currentPlugin);
|
||||
|
||||
if (deviceIface && cameraIface) {
|
||||
const QList<QByteArray> cameras = deviceIface->devices(type);
|
||||
foreach (const QByteArray &camera, cameras) {
|
||||
if (cameraIface->cameraPosition(camera) == hint.cameraPosition()) {
|
||||
plugin = currentPlugin;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QMediaServiceProviderHint::ContentType: {
|
||||
QMultimedia::SupportEstimate estimate = QMultimedia::NotSupported;
|
||||
foreach (QMediaServiceProviderPlugin *currentPlugin, plugins) {
|
||||
@@ -496,6 +547,25 @@ public:
|
||||
return supportedTypes;
|
||||
}
|
||||
|
||||
QByteArray defaultDevice(const QByteArray &serviceType) const
|
||||
{
|
||||
foreach (QObject *obj, loader()->instances(QLatin1String(serviceType))) {
|
||||
const QMediaServiceDefaultDeviceInterface *iface =
|
||||
qobject_cast<QMediaServiceDefaultDeviceInterface*>(obj);
|
||||
|
||||
if (iface)
|
||||
return iface->defaultDevice(serviceType);
|
||||
}
|
||||
|
||||
// if QMediaServiceDefaultDeviceInterface is not implemented, return the
|
||||
// first available device.
|
||||
QList<QByteArray> devs = devices(serviceType);
|
||||
if (!devs.isEmpty())
|
||||
return devs.first();
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QList<QByteArray> devices(const QByteArray &serviceType) const
|
||||
{
|
||||
QList<QByteArray> res;
|
||||
@@ -526,6 +596,44 @@ public:
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QCamera::Position cameraPosition(const QByteArray &device) const
|
||||
{
|
||||
const QByteArray serviceType(Q_MEDIASERVICE_CAMERA);
|
||||
foreach (QObject *obj, loader()->instances(QString::fromLatin1(serviceType))) {
|
||||
const QMediaServiceSupportedDevicesInterface *deviceIface =
|
||||
qobject_cast<QMediaServiceSupportedDevicesInterface*>(obj);
|
||||
const QMediaServiceCameraInfoInterface *cameraIface =
|
||||
qobject_cast<QMediaServiceCameraInfoInterface*>(obj);
|
||||
|
||||
if (cameraIface) {
|
||||
if (deviceIface && !deviceIface->devices(serviceType).contains(device))
|
||||
continue;
|
||||
return cameraIface->cameraPosition(device);
|
||||
}
|
||||
}
|
||||
|
||||
return QCamera::UnspecifiedPosition;
|
||||
}
|
||||
|
||||
int cameraOrientation(const QByteArray &device) const
|
||||
{
|
||||
const QByteArray serviceType(Q_MEDIASERVICE_CAMERA);
|
||||
foreach (QObject *obj, loader()->instances(QString::fromLatin1(serviceType))) {
|
||||
const QMediaServiceSupportedDevicesInterface *deviceIface =
|
||||
qobject_cast<QMediaServiceSupportedDevicesInterface*>(obj);
|
||||
const QMediaServiceCameraInfoInterface *cameraIface =
|
||||
qobject_cast<QMediaServiceCameraInfoInterface*>(obj);
|
||||
|
||||
if (cameraIface) {
|
||||
if (deviceIface && !deviceIface->devices(serviceType).contains(device))
|
||||
continue;
|
||||
return cameraIface->cameraOrientation(device);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(QPluginServiceProvider, pluginProvider);
|
||||
@@ -598,6 +706,17 @@ QStringList QMediaServiceProvider::supportedMimeTypes(const QByteArray &serviceT
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.3
|
||||
|
||||
Returns the default device for a \a service type.
|
||||
*/
|
||||
QByteArray QMediaServiceProvider::defaultDevice(const QByteArray &serviceType) const
|
||||
{
|
||||
Q_UNUSED(serviceType);
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the list of devices related to \a service type.
|
||||
*/
|
||||
@@ -618,6 +737,30 @@ QString QMediaServiceProvider::deviceDescription(const QByteArray &serviceType,
|
||||
return QString();
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.3
|
||||
|
||||
Returns the physical position of a camera \a device on the system hardware.
|
||||
*/
|
||||
QCamera::Position QMediaServiceProvider::cameraPosition(const QByteArray &device) const
|
||||
{
|
||||
Q_UNUSED(device);
|
||||
return QCamera::UnspecifiedPosition;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.3
|
||||
|
||||
Returns the physical orientation of the camera \a device. The value is the angle by which the
|
||||
camera image should be rotated anti-clockwise (in steps of 90 degrees) so it shows correctly on
|
||||
the display in its natural orientation.
|
||||
*/
|
||||
int QMediaServiceProvider::cameraOrientation(const QByteArray &device) const
|
||||
{
|
||||
Q_UNUSED(device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QMediaServiceProvider *qt_defaultMediaServiceProvider = 0;
|
||||
|
||||
/*!
|
||||
@@ -712,16 +855,47 @@ QMediaServiceProvider *QMediaServiceProvider::defaultServiceProvider()
|
||||
Destroys a media service supported devices interface.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\since 5.3
|
||||
|
||||
\fn QMediaServiceSupportedDevicesInterface::defaultDevice(const QByteArray &service) const
|
||||
|
||||
Returns the default device for a \a service type.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QMediaServiceSupportedDevicesInterface::devices(const QByteArray &service) const
|
||||
|
||||
Returns a list of devices supported by a plug-in \a service.
|
||||
Returns a list of devices available for a \a service type.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QMediaServiceSupportedDevicesInterface::deviceDescription(const QByteArray &service, const QByteArray &device)
|
||||
|
||||
Returns a description of a \a device supported by a plug-in \a service.
|
||||
Returns the description of a \a device available for a \a service type.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QMediaServiceCameraInfoInterface
|
||||
\inmodule QtMultimedia
|
||||
\since 5.3
|
||||
\brief The QMediaServiceCameraInfoInterface class interface
|
||||
provides camera-specific information about devices supported by a camera service plug-in.
|
||||
|
||||
A QMediaServiceProviderPlugin may implement this interface, in that case it also needs to
|
||||
implement the QMediaServiceSupportedDevicesInterface.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QMediaServiceCameraInfoInterface::cameraPosition(const QByteArray &device) const
|
||||
|
||||
Returns the physical position of a camera \a device supported by a camera service plug-in.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QMediaServiceCameraInfoInterface::cameraOrientation(const QByteArray &device) const
|
||||
|
||||
Returns the physical orientation of a camera \a device supported by a camera service plug-in.
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
||||
@@ -67,9 +67,13 @@ public:
|
||||
int flags = 0) const;
|
||||
virtual QStringList supportedMimeTypes(const QByteArray &serviceType, int flags = 0) const;
|
||||
|
||||
virtual QByteArray defaultDevice(const QByteArray &serviceType) const;
|
||||
virtual QList<QByteArray> devices(const QByteArray &serviceType) const;
|
||||
virtual QString deviceDescription(const QByteArray &serviceType, const QByteArray &device);
|
||||
|
||||
virtual QCamera::Position cameraPosition(const QByteArray &device) const;
|
||||
virtual int cameraOrientation(const QByteArray &device) const;
|
||||
|
||||
static QMediaServiceProvider* defaultServiceProvider();
|
||||
static void setDefaultServiceProvider(QMediaServiceProvider *provider);
|
||||
};
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <QtCore/qplugin.h>
|
||||
#include <QtMultimedia/qmultimedia.h>
|
||||
#include <QtMultimedia/qtmultimediadefs.h>
|
||||
#include <QtMultimedia/qcamera.h>
|
||||
|
||||
#ifdef Q_MOC_RUN
|
||||
# pragma Q_MOC_EXPAND_MACROS
|
||||
@@ -62,7 +63,7 @@ class QMediaServiceProviderHintPrivate;
|
||||
class Q_MULTIMEDIA_EXPORT QMediaServiceProviderHint
|
||||
{
|
||||
public:
|
||||
enum Type { Null, ContentType, Device, SupportedFeatures };
|
||||
enum Type { Null, ContentType, Device, SupportedFeatures, CameraPosition };
|
||||
|
||||
enum Feature {
|
||||
LowLatencyPlayback = 0x01,
|
||||
@@ -75,6 +76,7 @@ public:
|
||||
QMediaServiceProviderHint();
|
||||
QMediaServiceProviderHint(const QString &mimeType, const QStringList& codecs);
|
||||
QMediaServiceProviderHint(const QByteArray &device);
|
||||
QMediaServiceProviderHint(QCamera::Position position);
|
||||
QMediaServiceProviderHint(Features features);
|
||||
QMediaServiceProviderHint(const QMediaServiceProviderHint &other);
|
||||
~QMediaServiceProviderHint();
|
||||
@@ -92,6 +94,7 @@ public:
|
||||
QStringList codecs() const;
|
||||
|
||||
QByteArray device() const;
|
||||
QCamera::Position cameraPosition() const;
|
||||
|
||||
Features features() const;
|
||||
|
||||
@@ -145,6 +148,32 @@ struct Q_MULTIMEDIA_EXPORT QMediaServiceSupportedDevicesInterface
|
||||
"org.qt-project.qt.mediaservicesupporteddevices/5.0"
|
||||
Q_DECLARE_INTERFACE(QMediaServiceSupportedDevicesInterface, QMediaServiceSupportedDevicesInterface_iid)
|
||||
|
||||
// This should be part of QMediaServiceSupportedDevicesInterface but it can't in order
|
||||
// to preserve binary compatibility with 5.2 and earlier.
|
||||
// The whole media service plugin API shouldn't even be public in the first place. It should
|
||||
// be made private in Qt 6.0 and QMediaServiceDefaultDeviceInterface should be merged with
|
||||
// QMediaServiceSupportedDevicesInterface
|
||||
struct Q_MULTIMEDIA_EXPORT QMediaServiceDefaultDeviceInterface
|
||||
{
|
||||
virtual ~QMediaServiceDefaultDeviceInterface() {}
|
||||
virtual QByteArray defaultDevice(const QByteArray &service) const = 0;
|
||||
};
|
||||
|
||||
#define QMediaServiceDefaultDeviceInterface_iid \
|
||||
"org.qt-project.qt.mediaservicedefaultdevice/5.3"
|
||||
Q_DECLARE_INTERFACE(QMediaServiceDefaultDeviceInterface, QMediaServiceDefaultDeviceInterface_iid)
|
||||
|
||||
struct Q_MULTIMEDIA_EXPORT QMediaServiceCameraInfoInterface
|
||||
{
|
||||
virtual ~QMediaServiceCameraInfoInterface() {}
|
||||
virtual QCamera::Position cameraPosition(const QByteArray &device) const = 0;
|
||||
virtual int cameraOrientation(const QByteArray &device) const = 0;
|
||||
};
|
||||
|
||||
#define QMediaServiceCameraInfoInterface_iid \
|
||||
"org.qt-project.qt.mediaservicecamerainfo/5.3"
|
||||
Q_DECLARE_INTERFACE(QMediaServiceCameraInfoInterface, QMediaServiceCameraInfoInterface_iid)
|
||||
|
||||
// Required for QDoc workaround
|
||||
class QString;
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include <QtCore/qsharedpointer.h>
|
||||
#include <QtQuick/qquickitem.h>
|
||||
#include <QtCore/qpointer.h>
|
||||
#include <QtMultimedia/qcamerainfo.h>
|
||||
|
||||
#include <private/qtmultimediaquickdefs_p.h>
|
||||
|
||||
@@ -138,6 +139,7 @@ private:
|
||||
QPointer<QObject> m_source;
|
||||
QPointer<QMediaObject> m_mediaObject;
|
||||
QPointer<QMediaService> m_service;
|
||||
QCameraInfo m_cameraInfo;
|
||||
|
||||
FillMode m_fillMode;
|
||||
QSize m_nativeSize;
|
||||
|
||||
@@ -73,7 +73,7 @@ void QVideoOutputOrientationHandler::screenOrientationChanged(Qt::ScreenOrientat
|
||||
const QScreen *screen = QGuiApplication::primaryScreen();
|
||||
const QPlatformScreen *platformScreen = screen->handle();
|
||||
|
||||
const int angle = (360 - screen->angleBetween(platformScreen->nativeOrientation(), orientation));
|
||||
const int angle = (360 - screen->angleBetween(platformScreen->nativeOrientation(), orientation)) % 360;
|
||||
|
||||
if (angle == m_currentOrientation)
|
||||
return;
|
||||
|
||||
@@ -247,6 +247,8 @@ public:
|
||||
|
||||
bool isFormatSupported(const QVideoSurfaceFormat &format) const;
|
||||
|
||||
void stop();
|
||||
|
||||
QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame);
|
||||
|
||||
QAbstractVideoSurface::Error paint(
|
||||
@@ -351,6 +353,12 @@ bool QVideoSurfaceGLPainter::isFormatSupported(const QVideoSurfaceFormat &format
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void QVideoSurfaceGLPainter::stop()
|
||||
{
|
||||
m_frame = QVideoFrame();
|
||||
}
|
||||
|
||||
QAbstractVideoSurface::Error QVideoSurfaceGLPainter::setCurrentFrame(const QVideoFrame &frame)
|
||||
{
|
||||
m_frame = frame;
|
||||
@@ -832,6 +840,8 @@ void QVideoSurfaceArbFpPainter::stop()
|
||||
m_textureCount = 0;
|
||||
m_programId = 0;
|
||||
m_handleType = QAbstractVideoBuffer::NoHandle;
|
||||
|
||||
QVideoSurfaceGLPainter::stop();
|
||||
}
|
||||
|
||||
QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::paint(
|
||||
@@ -1176,6 +1186,8 @@ void QVideoSurfaceGlslPainter::stop()
|
||||
|
||||
m_textureCount = 0;
|
||||
m_handleType = QAbstractVideoBuffer::NoHandle;
|
||||
|
||||
QVideoSurfaceGLPainter::stop();
|
||||
}
|
||||
|
||||
QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::paint(
|
||||
|
||||
@@ -22,7 +22,8 @@ SOURCES += \
|
||||
$$PWD/qandroidmediacontainercontrol.cpp \
|
||||
$$PWD/qandroidvideoencodersettingscontrol.cpp \
|
||||
$$PWD/qandroidaudioinputselectorcontrol.cpp \
|
||||
$$PWD/qandroidmediavideoprobecontrol.cpp
|
||||
$$PWD/qandroidmediavideoprobecontrol.cpp \
|
||||
$$PWD/qandroidcamerainfocontrol.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/qandroidcaptureservice.h \
|
||||
@@ -46,4 +47,5 @@ HEADERS += \
|
||||
$$PWD/qandroidmediacontainercontrol.h \
|
||||
$$PWD/qandroidvideoencodersettingscontrol.h \
|
||||
$$PWD/qandroidaudioinputselectorcontrol.h \
|
||||
$$PWD/qandroidmediavideoprobecontrol.h
|
||||
$$PWD/qandroidmediavideoprobecontrol.h \
|
||||
$$PWD/qandroidcamerainfocontrol.h
|
||||
|
||||
@@ -46,36 +46,15 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static QPointF rotateNormalizedPoint(const QPointF &point, int rotation)
|
||||
{
|
||||
const qreal one(1.0f);
|
||||
|
||||
switch (rotation) {
|
||||
case 0:
|
||||
default:
|
||||
return point;
|
||||
case 90:
|
||||
return QPointF(point.y(), one - point.x());
|
||||
case 180:
|
||||
return QPointF(one - point.x(), one - point.y());
|
||||
case 270:
|
||||
return QPointF(one - point.y(), point.x());
|
||||
}
|
||||
}
|
||||
|
||||
static QRect adjustedArea(const QRectF &area, int rotation)
|
||||
static QRect adjustedArea(const QRectF &area)
|
||||
{
|
||||
// Qt maps focus points in the range (0.0, 0.0) -> (1.0, 1.0)
|
||||
// Android maps focus points in the range (-1000, -1000) -> (1000, 1000)
|
||||
// Converts an area in Qt coordinates to Android coordinates
|
||||
// Applies 'rotation' in the counter-clockwise direction
|
||||
QRectF rotated(rotateNormalizedPoint(area.topLeft(), rotation),
|
||||
rotateNormalizedPoint(area.bottomRight(), rotation));
|
||||
|
||||
return QRect(-1000 + qRound(rotated.x() * 2000),
|
||||
-1000 + qRound(rotated.y() * 2000),
|
||||
qRound(rotated.width() * 2000),
|
||||
qRound(rotated.height() * 2000))
|
||||
return QRect(-1000 + qRound(area.x() * 2000),
|
||||
-1000 + qRound(area.y() * 2000),
|
||||
qRound(area.width() * 2000),
|
||||
qRound(area.height() * 2000))
|
||||
.intersected(QRect(-1000, -1000, 2000, 2000));
|
||||
}
|
||||
|
||||
@@ -263,9 +242,6 @@ void QAndroidCameraFocusControl::updateFocusZones(QCameraFocusZone::FocusZoneSta
|
||||
if (!viewportSize.isValid())
|
||||
return;
|
||||
|
||||
if (m_session->camera()->getDisplayOrientation() % 180)
|
||||
viewportSize.transpose();
|
||||
|
||||
QSizeF focusSize(50.f / viewportSize.width(), 50.f / viewportSize.height());
|
||||
float x = qBound(qreal(0),
|
||||
m_actualFocusPoint.x() - (focusSize.width() / 2),
|
||||
@@ -288,13 +264,8 @@ void QAndroidCameraFocusControl::setCameraFocusArea()
|
||||
// in FocusPointAuto mode, leave the area list empty
|
||||
// to let the driver choose the focus point.
|
||||
|
||||
for (int i = 0; i < m_focusZones.size(); ++i) {
|
||||
// The area passed to Android should be in sensor orientation.
|
||||
// What we have in m_focusZones is in viewport orientation, so revert the rotation set
|
||||
// on the viewport to get sensor coordinates.
|
||||
areas.append(adjustedArea(m_focusZones.at(i).area(),
|
||||
m_session->camera()->getDisplayOrientation()));
|
||||
}
|
||||
for (int i = 0; i < m_focusZones.size(); ++i)
|
||||
areas.append(adjustedArea(m_focusZones.at(i).area()));
|
||||
|
||||
}
|
||||
m_session->camera()->setFocusAreas(areas);
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** 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 "qandroidcamerainfocontrol.h"
|
||||
|
||||
#include "qandroidcamerasession.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QCamera::Position QAndroidCameraInfoControl::position(const QString &deviceName)
|
||||
{
|
||||
const QList<AndroidCameraInfo> &cameras = QAndroidCameraSession::availableCameras();
|
||||
for (int i = 0; i < cameras.count(); ++i) {
|
||||
const AndroidCameraInfo &info = cameras.at(i);
|
||||
if (QString::fromLatin1(info.name) == deviceName)
|
||||
return info.position;
|
||||
}
|
||||
|
||||
return QCamera::UnspecifiedPosition;
|
||||
}
|
||||
|
||||
int QAndroidCameraInfoControl::orientation(const QString &deviceName)
|
||||
{
|
||||
const QList<AndroidCameraInfo> &cameras = QAndroidCameraSession::availableCameras();
|
||||
for (int i = 0; i < cameras.count(); ++i) {
|
||||
const AndroidCameraInfo &info = cameras.at(i);
|
||||
if (QString::fromLatin1(info.name) == deviceName)
|
||||
return info.orientation;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QCamera::Position QAndroidCameraInfoControl::cameraPosition(const QString &deviceName) const
|
||||
{
|
||||
return position(deviceName);
|
||||
}
|
||||
|
||||
int QAndroidCameraInfoControl::cameraOrientation(const QString &deviceName) const
|
||||
{
|
||||
return orientation(deviceName);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** 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 QANDROIDCAMERAINFOCONTROL_H
|
||||
#define QANDROIDCAMERAINFOCONTROL_H
|
||||
|
||||
#include <qcamerainfocontrol.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QAndroidCameraInfoControl : public QCameraInfoControl
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QCamera::Position cameraPosition(const QString &deviceName) const;
|
||||
int cameraOrientation(const QString &deviceName) const;
|
||||
|
||||
static QCamera::Position position(const QString &deviceName);
|
||||
static int orientation(const QString &deviceName);
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QANDROIDCAMERAINFOCONTROL_H
|
||||
@@ -90,13 +90,13 @@ private:
|
||||
int bytesPerLine;
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(QList<AndroidCameraInfo>, g_availableCameras)
|
||||
|
||||
QAndroidCameraSession::QAndroidCameraSession(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_selectedCamera(0)
|
||||
, m_camera(0)
|
||||
, m_nativeOrientation(0)
|
||||
, m_previewOrientation(0)
|
||||
, m_videoOutput(0)
|
||||
, m_captureMode(QCamera::CaptureViewfinder)
|
||||
, m_state(QCamera::UnloadedState)
|
||||
@@ -175,6 +175,54 @@ void QAndroidCameraSession::setState(QCamera::State state)
|
||||
emit stateChanged(m_state);
|
||||
}
|
||||
|
||||
void QAndroidCameraSession::updateAvailableCameras()
|
||||
{
|
||||
g_availableCameras->clear();
|
||||
|
||||
const QJNIObjectPrivate cameraInfo("android/hardware/Camera$CameraInfo");
|
||||
const int numCameras = QJNIObjectPrivate::callStaticMethod<jint>("android/hardware/Camera",
|
||||
"getNumberOfCameras");
|
||||
|
||||
for (int i = 0; i < numCameras; ++i) {
|
||||
AndroidCameraInfo info;
|
||||
|
||||
QJNIObjectPrivate::callStaticMethod<void>("android/hardware/Camera",
|
||||
"getCameraInfo",
|
||||
"(ILandroid/hardware/Camera$CameraInfo;)V",
|
||||
i, cameraInfo.object());
|
||||
|
||||
JCamera::CameraFacing facing = JCamera::CameraFacing(cameraInfo.getField<jint>("facing"));
|
||||
// The orientation provided by Android is counter-clockwise, we need it clockwise
|
||||
info.orientation = (360 - cameraInfo.getField<jint>("orientation")) % 360;
|
||||
|
||||
switch (facing) {
|
||||
case JCamera::CameraFacingBack:
|
||||
info.name = QByteArray("back");
|
||||
info.description = QStringLiteral("Rear-facing camera");
|
||||
info.position = QCamera::BackFace;
|
||||
break;
|
||||
case JCamera::CameraFacingFront:
|
||||
info.name = QByteArray("front");
|
||||
info.description = QStringLiteral("Front-facing camera");
|
||||
info.position = QCamera::FrontFace;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!info.name.isNull())
|
||||
g_availableCameras->append(info);
|
||||
}
|
||||
}
|
||||
|
||||
const QList<AndroidCameraInfo> &QAndroidCameraSession::availableCameras()
|
||||
{
|
||||
if (g_availableCameras->isEmpty())
|
||||
updateAvailableCameras();
|
||||
|
||||
return *g_availableCameras;
|
||||
}
|
||||
|
||||
bool QAndroidCameraSession::open()
|
||||
{
|
||||
close();
|
||||
@@ -196,12 +244,6 @@ bool QAndroidCameraSession::open()
|
||||
|
||||
m_nativeOrientation = m_camera->getNativeOrientation();
|
||||
|
||||
// Preview orientation will always match the device natural orientation
|
||||
if (m_camera->getFacing() == JCamera::CameraFacingFront)
|
||||
m_previewOrientation = 360 - m_nativeOrientation;
|
||||
else
|
||||
m_previewOrientation = m_nativeOrientation;
|
||||
|
||||
m_status = QCamera::LoadedStatus;
|
||||
|
||||
if (m_camera->getPreviewFormat() != JCamera::NV21)
|
||||
@@ -279,16 +321,8 @@ void QAndroidCameraSession::adjustViewfinderSize(const QSize &captureSize, bool
|
||||
}
|
||||
|
||||
if (m_camera->previewSize() != viewfinderResolution) {
|
||||
if (m_videoOutput) {
|
||||
QSize size = viewfinderResolution;
|
||||
|
||||
// If the preview orientation is not the defaut one (0 or 180 degrees),
|
||||
// we have to invert the output aspect ratio.
|
||||
if (m_previewOrientation % 180)
|
||||
size.transpose();
|
||||
|
||||
m_videoOutput->setVideoSize(size);
|
||||
}
|
||||
if (m_videoOutput)
|
||||
m_videoOutput->setVideoSize(viewfinderResolution);
|
||||
|
||||
// if preview is started, we have to stop it first before changing its size
|
||||
if (m_previewStarted && restartPreview)
|
||||
@@ -312,7 +346,6 @@ void QAndroidCameraSession::startPreview()
|
||||
|
||||
applyImageSettings();
|
||||
adjustViewfinderSize(m_imageSettings.resolution());
|
||||
m_camera->setDisplayOrientation(m_previewOrientation);
|
||||
|
||||
if (m_videoOutput && m_videoOutput->isReady())
|
||||
onVideoOutputReady(true);
|
||||
|
||||
@@ -55,6 +55,14 @@ class JCamera;
|
||||
class QAndroidVideoOutput;
|
||||
class QAndroidMediaVideoProbeControl;
|
||||
|
||||
struct AndroidCameraInfo
|
||||
{
|
||||
QByteArray name;
|
||||
QString description;
|
||||
QCamera::Position position;
|
||||
int orientation;
|
||||
};
|
||||
|
||||
class QAndroidCameraSession : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -62,6 +70,8 @@ public:
|
||||
explicit QAndroidCameraSession(QObject *parent = 0);
|
||||
~QAndroidCameraSession();
|
||||
|
||||
static const QList<AndroidCameraInfo> &availableCameras();
|
||||
|
||||
void setSelectedCamera(int cameraId) { m_selectedCamera = cameraId; }
|
||||
JCamera *camera() const { return m_camera; }
|
||||
|
||||
@@ -126,6 +136,8 @@ private Q_SLOTS:
|
||||
void onCameraPreviewStopped();
|
||||
|
||||
private:
|
||||
static void updateAvailableCameras();
|
||||
|
||||
bool open();
|
||||
void close();
|
||||
|
||||
@@ -144,7 +156,6 @@ private:
|
||||
int m_selectedCamera;
|
||||
JCamera *m_camera;
|
||||
int m_nativeOrientation;
|
||||
int m_previewOrientation;
|
||||
QAndroidVideoOutput *m_videoOutput;
|
||||
|
||||
QCamera::CaptureModes m_captureMode;
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "qandroidmediarecordercontrol.h"
|
||||
#include "qandroidcapturesession.h"
|
||||
#include "qandroidcameracontrol.h"
|
||||
#include "qandroidcamerainfocontrol.h"
|
||||
#include "qandroidvideodeviceselectorcontrol.h"
|
||||
#include "qandroidaudioinputselectorcontrol.h"
|
||||
#include "qandroidcamerasession.h"
|
||||
@@ -75,6 +76,7 @@ QAndroidCaptureService::QAndroidCaptureService(const QString &service, QObject *
|
||||
if (m_service == QLatin1String(Q_MEDIASERVICE_CAMERA)) {
|
||||
m_cameraSession = new QAndroidCameraSession;
|
||||
m_cameraControl = new QAndroidCameraControl(m_cameraSession);
|
||||
m_cameraInfoControl = new QAndroidCameraInfoControl;
|
||||
m_videoInputControl = new QAndroidVideoDeviceSelectorControl(m_cameraSession);
|
||||
m_cameraZoomControl = new QAndroidCameraZoomControl(m_cameraSession);
|
||||
m_cameraExposureControl = new QAndroidCameraExposureControl(m_cameraSession);
|
||||
@@ -90,6 +92,7 @@ QAndroidCaptureService::QAndroidCaptureService(const QString &service, QObject *
|
||||
} else {
|
||||
m_cameraSession = 0;
|
||||
m_cameraControl = 0;
|
||||
m_cameraInfoControl = 0;
|
||||
m_videoInputControl = 0;
|
||||
m_cameraZoomControl = 0;
|
||||
m_cameraExposureControl = 0;
|
||||
@@ -125,6 +128,7 @@ QAndroidCaptureService::~QAndroidCaptureService()
|
||||
delete m_recorderControl;
|
||||
delete m_captureSession;
|
||||
delete m_cameraControl;
|
||||
delete m_cameraInfoControl;
|
||||
delete m_audioInputControl;
|
||||
delete m_videoInputControl;
|
||||
delete m_videoRendererControl;
|
||||
@@ -158,6 +162,9 @@ QMediaControl *QAndroidCaptureService::requestControl(const char *name)
|
||||
if (qstrcmp(name, QCameraControl_iid) == 0)
|
||||
return m_cameraControl;
|
||||
|
||||
if (qstrcmp(name, QCameraInfoControl_iid) == 0)
|
||||
return m_cameraInfoControl;
|
||||
|
||||
if (qstrcmp(name, QAudioInputSelectorControl_iid) == 0)
|
||||
return m_audioInputControl;
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE
|
||||
class QAndroidMediaRecorderControl;
|
||||
class QAndroidCaptureSession;
|
||||
class QAndroidCameraControl;
|
||||
class QAndroidCameraInfoControl;
|
||||
class QAndroidVideoDeviceSelectorControl;
|
||||
class QAndroidAudioInputSelectorControl;
|
||||
class QAndroidCameraSession;
|
||||
@@ -85,6 +86,7 @@ private:
|
||||
QAndroidMediaRecorderControl *m_recorderControl;
|
||||
QAndroidCaptureSession *m_captureSession;
|
||||
QAndroidCameraControl *m_cameraControl;
|
||||
QAndroidCameraInfoControl *m_cameraInfoControl;
|
||||
QAndroidVideoDeviceSelectorControl *m_videoInputControl;
|
||||
QAndroidAudioInputSelectorControl *m_audioInputControl;
|
||||
QAndroidCameraSession *m_cameraSession;
|
||||
|
||||
@@ -46,16 +46,11 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QList<QByteArray> QAndroidVideoDeviceSelectorControl::m_names;
|
||||
QStringList QAndroidVideoDeviceSelectorControl::m_descriptions;
|
||||
|
||||
QAndroidVideoDeviceSelectorControl::QAndroidVideoDeviceSelectorControl(QAndroidCameraSession *session)
|
||||
: QVideoDeviceSelectorControl(0)
|
||||
, m_selectedDevice(0)
|
||||
, m_cameraSession(session)
|
||||
{
|
||||
if (m_names.isEmpty())
|
||||
update();
|
||||
}
|
||||
|
||||
QAndroidVideoDeviceSelectorControl::~QAndroidVideoDeviceSelectorControl()
|
||||
@@ -64,17 +59,23 @@ QAndroidVideoDeviceSelectorControl::~QAndroidVideoDeviceSelectorControl()
|
||||
|
||||
int QAndroidVideoDeviceSelectorControl::deviceCount() const
|
||||
{
|
||||
return m_names.size();
|
||||
return QAndroidCameraSession::availableCameras().count();
|
||||
}
|
||||
|
||||
QString QAndroidVideoDeviceSelectorControl::deviceName(int index) const
|
||||
{
|
||||
return m_names.at(index);
|
||||
if (index < 0 || index >= QAndroidCameraSession::availableCameras().count())
|
||||
return QString();
|
||||
|
||||
return QString::fromLatin1(QAndroidCameraSession::availableCameras().at(index).name);
|
||||
}
|
||||
|
||||
QString QAndroidVideoDeviceSelectorControl::deviceDescription(int index) const
|
||||
{
|
||||
return m_descriptions.at(index);
|
||||
if (index < 0 || index >= QAndroidCameraSession::availableCameras().count())
|
||||
return QString();
|
||||
|
||||
return QAndroidCameraSession::availableCameras().at(index).description;
|
||||
}
|
||||
|
||||
int QAndroidVideoDeviceSelectorControl::defaultDevice() const
|
||||
@@ -97,53 +98,4 @@ void QAndroidVideoDeviceSelectorControl::setSelectedDevice(int index)
|
||||
}
|
||||
}
|
||||
|
||||
void QAndroidVideoDeviceSelectorControl::update()
|
||||
{
|
||||
m_names.clear();
|
||||
m_descriptions.clear();
|
||||
|
||||
QJNIObjectPrivate cameraInfo("android/hardware/Camera$CameraInfo");
|
||||
int numCameras = QJNIObjectPrivate::callStaticMethod<jint>("android/hardware/Camera",
|
||||
"getNumberOfCameras");
|
||||
|
||||
for (int i = 0; i < numCameras; ++i) {
|
||||
QJNIObjectPrivate::callStaticMethod<void>("android/hardware/Camera",
|
||||
"getCameraInfo",
|
||||
"(ILandroid/hardware/Camera$CameraInfo;)V",
|
||||
i, cameraInfo.object());
|
||||
|
||||
JCamera::CameraFacing facing = JCamera::CameraFacing(cameraInfo.getField<jint>("facing"));
|
||||
|
||||
switch (facing) {
|
||||
case JCamera::CameraFacingBack:
|
||||
m_names.append("back");
|
||||
m_descriptions.append(QStringLiteral("Rear-facing camera"));
|
||||
break;
|
||||
case JCamera::CameraFacingFront:
|
||||
m_names.append("front");
|
||||
m_descriptions.append(QStringLiteral("Front-facing camera"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<QByteArray> QAndroidVideoDeviceSelectorControl::availableDevices()
|
||||
{
|
||||
if (m_names.isEmpty())
|
||||
update();
|
||||
|
||||
return m_names;
|
||||
}
|
||||
|
||||
QString QAndroidVideoDeviceSelectorControl::availableDeviceDescription(const QByteArray &device)
|
||||
{
|
||||
int i = m_names.indexOf(device);
|
||||
if (i != -1)
|
||||
return m_descriptions.at(i);
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -63,18 +63,10 @@ public:
|
||||
|
||||
int defaultDevice() const;
|
||||
int selectedDevice() const;
|
||||
|
||||
void setSelectedDevice(int index);
|
||||
|
||||
static QList<QByteArray> availableDevices();
|
||||
static QString availableDeviceDescription(const QByteArray &device);
|
||||
|
||||
private:
|
||||
static void update();
|
||||
|
||||
int m_selectedDevice;
|
||||
static QList<QByteArray> m_names;
|
||||
static QStringList m_descriptions;
|
||||
|
||||
QAndroidCameraSession *m_cameraSession;
|
||||
};
|
||||
|
||||
@@ -43,8 +43,9 @@
|
||||
|
||||
#include "qandroidmediaservice.h"
|
||||
#include "qandroidcaptureservice.h"
|
||||
#include "qandroidvideodeviceselectorcontrol.h"
|
||||
#include "qandroidaudioinputselectorcontrol.h"
|
||||
#include "qandroidcamerainfocontrol.h"
|
||||
#include "qandroidcamerasession.h"
|
||||
#include "jmediaplayer.h"
|
||||
#include "jsurfacetexture.h"
|
||||
#include "jsurfacetextureholder.h"
|
||||
@@ -96,10 +97,23 @@ QMediaServiceProviderHint::Features QAndroidMediaServicePlugin::supportedFeature
|
||||
return QMediaServiceProviderHint::Features();
|
||||
}
|
||||
|
||||
QByteArray QAndroidMediaServicePlugin::defaultDevice(const QByteArray &service) const
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA && !QAndroidCameraSession::availableCameras().isEmpty())
|
||||
return QAndroidCameraSession::availableCameras().first().name;
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QList<QByteArray> QAndroidMediaServicePlugin::devices(const QByteArray &service) const
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA)
|
||||
return QAndroidVideoDeviceSelectorControl::availableDevices();
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
QList<QByteArray> devices;
|
||||
const QList<AndroidCameraInfo> &cameras = QAndroidCameraSession::availableCameras();
|
||||
for (int i = 0; i < cameras.count(); ++i)
|
||||
devices.append(cameras.at(i).name);
|
||||
return devices;
|
||||
}
|
||||
|
||||
if (service == Q_MEDIASERVICE_AUDIOSOURCE)
|
||||
return QAndroidAudioInputSelectorControl::availableDevices();
|
||||
@@ -109,8 +123,14 @@ QList<QByteArray> QAndroidMediaServicePlugin::devices(const QByteArray &service)
|
||||
|
||||
QString QAndroidMediaServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA)
|
||||
return QAndroidVideoDeviceSelectorControl::availableDeviceDescription(device);
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
const QList<AndroidCameraInfo> &cameras = QAndroidCameraSession::availableCameras();
|
||||
for (int i = 0; i < cameras.count(); ++i) {
|
||||
const AndroidCameraInfo &info = cameras.at(i);
|
||||
if (info.name == device)
|
||||
return info.description;
|
||||
}
|
||||
}
|
||||
|
||||
if (service == Q_MEDIASERVICE_AUDIOSOURCE)
|
||||
return QAndroidAudioInputSelectorControl::availableDeviceDescription(device);
|
||||
@@ -118,6 +138,16 @@ QString QAndroidMediaServicePlugin::deviceDescription(const QByteArray &service,
|
||||
return QString();
|
||||
}
|
||||
|
||||
QCamera::Position QAndroidMediaServicePlugin::cameraPosition(const QByteArray &device) const
|
||||
{
|
||||
return QAndroidCameraInfoControl::position(device);
|
||||
}
|
||||
|
||||
int QAndroidMediaServicePlugin::cameraOrientation(const QByteArray &device) const
|
||||
{
|
||||
return QAndroidCameraInfoControl::orientation(device);
|
||||
}
|
||||
|
||||
|
||||
Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/)
|
||||
{
|
||||
|
||||
@@ -49,10 +49,14 @@ QT_BEGIN_NAMESPACE
|
||||
class QAndroidMediaServicePlugin
|
||||
: public QMediaServiceProviderPlugin
|
||||
, public QMediaServiceSupportedDevicesInterface
|
||||
, public QMediaServiceDefaultDeviceInterface
|
||||
, public QMediaServiceCameraInfoInterface
|
||||
, public QMediaServiceFeaturesInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
|
||||
Q_INTERFACES(QMediaServiceDefaultDeviceInterface)
|
||||
Q_INTERFACES(QMediaServiceCameraInfoInterface)
|
||||
Q_INTERFACES(QMediaServiceFeaturesInterface)
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0"
|
||||
FILE "android_mediaservice.json")
|
||||
@@ -66,8 +70,12 @@ public:
|
||||
|
||||
QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const Q_DECL_OVERRIDE;
|
||||
|
||||
QList<QByteArray> devices(const QByteArray &service) const;
|
||||
QString deviceDescription(const QByteArray &service, const QByteArray &device);
|
||||
QByteArray defaultDevice(const QByteArray &service) const Q_DECL_OVERRIDE;
|
||||
QList<QByteArray> devices(const QByteArray &service) const Q_DECL_OVERRIDE;
|
||||
QString deviceDescription(const QByteArray &service, const QByteArray &device) Q_DECL_OVERRIDE;
|
||||
|
||||
QCamera::Position cameraPosition(const QByteArray &device) const Q_DECL_OVERRIDE;
|
||||
int cameraOrientation(const QByteArray &device) const Q_DECL_OVERRIDE;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -158,8 +158,6 @@ class JCameraWorker : public QObject, public QJNIObjectPrivate
|
||||
Q_INVOKABLE JCamera::CameraFacing getFacing();
|
||||
Q_INVOKABLE int getNativeOrientation();
|
||||
|
||||
Q_INVOKABLE void setDisplayOrientation(int degrees);
|
||||
|
||||
Q_INVOKABLE QSize getPreferredPreviewSizeForVideo();
|
||||
Q_INVOKABLE QList<QSize> getSupportedPreviewSizes();
|
||||
|
||||
@@ -231,7 +229,6 @@ class JCameraWorker : public QObject, public QJNIObjectPrivate
|
||||
|
||||
QSize m_previewSize;
|
||||
int m_rotation;
|
||||
int m_displayOrientation;
|
||||
|
||||
bool m_hasAPI14;
|
||||
|
||||
@@ -337,17 +334,6 @@ int JCamera::getNativeOrientation()
|
||||
return d->getNativeOrientation();
|
||||
}
|
||||
|
||||
int JCamera::getDisplayOrientation() const
|
||||
{
|
||||
return d->m_displayOrientation;
|
||||
}
|
||||
|
||||
void JCamera::setDisplayOrientation(int degrees)
|
||||
{
|
||||
d->m_displayOrientation = degrees;
|
||||
QMetaObject::invokeMethod(d, "setDisplayOrientation", Q_ARG(int, degrees));
|
||||
}
|
||||
|
||||
QSize JCamera::getPreferredPreviewSizeForVideo()
|
||||
{
|
||||
return d->getPreferredPreviewSizeForVideo();
|
||||
@@ -626,7 +612,6 @@ JCameraWorker::JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread
|
||||
, QJNIObjectPrivate(cam)
|
||||
, m_cameraId(cameraId)
|
||||
, m_rotation(0)
|
||||
, m_displayOrientation(0)
|
||||
, m_hasAPI14(false)
|
||||
, m_parametersMutex(QMutex::Recursive)
|
||||
{
|
||||
@@ -692,11 +677,6 @@ int JCameraWorker::getNativeOrientation()
|
||||
return m_info.getField<jint>("orientation");
|
||||
}
|
||||
|
||||
void JCameraWorker::setDisplayOrientation(int degrees)
|
||||
{
|
||||
callMethod<void>("setDisplayOrientation", "(I)V", degrees);
|
||||
}
|
||||
|
||||
QSize JCameraWorker::getPreferredPreviewSizeForVideo()
|
||||
{
|
||||
QMutexLocker parametersLocker(&m_parametersMutex);
|
||||
|
||||
@@ -88,9 +88,6 @@ public:
|
||||
CameraFacing getFacing();
|
||||
int getNativeOrientation();
|
||||
|
||||
int getDisplayOrientation() const;
|
||||
void setDisplayOrientation(int degrees);
|
||||
|
||||
QSize getPreferredPreviewSizeForVideo();
|
||||
QList<QSize> getSupportedPreviewSizes();
|
||||
|
||||
|
||||
61
src/plugins/avfoundation/camera/avfcamerainfocontrol.h
Normal file
61
src/plugins/avfoundation/camera/avfcamerainfocontrol.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** 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 AVFCAMERAINFOCONTROL_H
|
||||
#define AVFCAMERAINFOCONTROL_H
|
||||
|
||||
#include <qcamerainfocontrol.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class AVFCameraInfoControl : public QCameraInfoControl
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AVFCameraInfoControl(QObject *parent = 0);
|
||||
|
||||
QCamera::Position cameraPosition(const QString &deviceName) const;
|
||||
int cameraOrientation(const QString &deviceName) const;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // AVFCAMERAINFOCONTROL_H
|
||||
62
src/plugins/avfoundation/camera/avfcamerainfocontrol.mm
Normal file
62
src/plugins/avfoundation/camera/avfcamerainfocontrol.mm
Normal file
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** 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 "avfcamerainfocontrol.h"
|
||||
#include "avfcamerasession.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
AVFCameraInfoControl::AVFCameraInfoControl(QObject *parent)
|
||||
: QCameraInfoControl(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QCamera::Position AVFCameraInfoControl::cameraPosition(const QString &deviceName) const
|
||||
{
|
||||
return AVFCameraSession::cameraDeviceInfo(deviceName.toUtf8()).position;
|
||||
}
|
||||
|
||||
int AVFCameraInfoControl::cameraOrientation(const QString &deviceName) const
|
||||
{
|
||||
return AVFCameraSession::cameraDeviceInfo(deviceName.toUtf8()).orientation;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
@@ -50,6 +50,7 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QCameraControl;
|
||||
class AVFCameraControl;
|
||||
class AVFCameraInfoControl;
|
||||
class AVFCameraMetaDataControl;
|
||||
class AVFVideoWindowControl;
|
||||
class AVFVideoWidgetControl;
|
||||
@@ -82,6 +83,7 @@ public:
|
||||
private:
|
||||
AVFCameraSession *m_session;
|
||||
AVFCameraControl *m_cameraControl;
|
||||
AVFCameraInfoControl *m_cameraInfoControl;
|
||||
AVFVideoDeviceControl *m_videoDeviceControl;
|
||||
AVFAudioInputSelectorControl *m_audioInputSelectorControl;
|
||||
AVFVideoRendererControl *m_videoOutput;
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
|
||||
#include "avfcameraservice.h"
|
||||
#include "avfcameracontrol.h"
|
||||
#include "avfcamerainfocontrol.h"
|
||||
#include "avfcamerasession.h"
|
||||
#include "avfvideodevicecontrol.h"
|
||||
#include "avfaudioinputselectorcontrol.h"
|
||||
@@ -65,6 +66,7 @@ AVFCameraService::AVFCameraService(QObject *parent):
|
||||
{
|
||||
m_session = new AVFCameraSession(this);
|
||||
m_cameraControl = new AVFCameraControl(this);
|
||||
m_cameraInfoControl = new AVFCameraInfoControl(this);
|
||||
m_videoDeviceControl = new AVFVideoDeviceControl(this);
|
||||
m_audioInputSelectorControl = new AVFAudioInputSelectorControl(this);
|
||||
|
||||
@@ -98,6 +100,9 @@ QMediaControl *AVFCameraService::requestControl(const char *name)
|
||||
if (qstrcmp(name, QCameraControl_iid) == 0)
|
||||
return m_cameraControl;
|
||||
|
||||
if (qstrcmp(name, QCameraInfoControl_iid) == 0)
|
||||
return m_cameraInfoControl;
|
||||
|
||||
if (qstrcmp(name, QVideoDeviceSelectorControl_iid) == 0)
|
||||
return m_videoDeviceControl;
|
||||
|
||||
|
||||
@@ -49,10 +49,14 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class AVFServicePlugin : public QMediaServiceProviderPlugin,
|
||||
public QMediaServiceSupportedDevicesInterface
|
||||
public QMediaServiceSupportedDevicesInterface,
|
||||
public QMediaServiceDefaultDeviceInterface,
|
||||
public QMediaServiceCameraInfoInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
|
||||
Q_INTERFACES(QMediaServiceDefaultDeviceInterface)
|
||||
Q_INTERFACES(QMediaServiceCameraInfoInterface)
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "avfcamera.json")
|
||||
|
||||
public:
|
||||
@@ -61,14 +65,12 @@ public:
|
||||
QMediaService* create(QString const& key);
|
||||
void release(QMediaService *service);
|
||||
|
||||
QByteArray defaultDevice(const QByteArray &service) const;
|
||||
QList<QByteArray> devices(const QByteArray &service) const;
|
||||
QString deviceDescription(const QByteArray &service, const QByteArray &device);
|
||||
|
||||
private:
|
||||
void updateDevices() const;
|
||||
|
||||
mutable QList<QByteArray> m_cameraDevices;
|
||||
mutable QMap<QByteArray, QString> m_cameraDescriptions;
|
||||
QCamera::Position cameraPosition(const QByteArray &device) const;
|
||||
int cameraOrientation(const QByteArray &device) const;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -44,15 +44,12 @@
|
||||
|
||||
#include "avfcameraserviceplugin.h"
|
||||
#include "avfcameraservice.h"
|
||||
#include "avfcamerasession.h"
|
||||
|
||||
#include <qmediaserviceproviderplugin.h>
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
AVFServicePlugin::AVFServicePlugin()
|
||||
{
|
||||
}
|
||||
@@ -72,41 +69,38 @@ void AVFServicePlugin::release(QMediaService *service)
|
||||
delete service;
|
||||
}
|
||||
|
||||
QByteArray AVFServicePlugin::defaultDevice(const QByteArray &service) const
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA)
|
||||
return AVFCameraSession::defaultCameraDevice();
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QList<QByteArray> AVFServicePlugin::devices(const QByteArray &service) const
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
if (m_cameraDevices.isEmpty())
|
||||
updateDevices();
|
||||
|
||||
return m_cameraDevices;
|
||||
}
|
||||
if (service == Q_MEDIASERVICE_CAMERA)
|
||||
return AVFCameraSession::availableCameraDevices();
|
||||
|
||||
return QList<QByteArray>();
|
||||
}
|
||||
|
||||
QString AVFServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
if (m_cameraDevices.isEmpty())
|
||||
updateDevices();
|
||||
|
||||
return m_cameraDescriptions.value(device);
|
||||
}
|
||||
if (service == Q_MEDIASERVICE_CAMERA)
|
||||
return AVFCameraSession::cameraDeviceInfo(device).description;
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
void AVFServicePlugin::updateDevices() const
|
||||
QCamera::Position AVFServicePlugin::cameraPosition(const QByteArray &device) const
|
||||
{
|
||||
m_cameraDevices.clear();
|
||||
m_cameraDescriptions.clear();
|
||||
return AVFCameraSession::cameraDeviceInfo(device).position;
|
||||
}
|
||||
|
||||
NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
|
||||
for (AVCaptureDevice *device in videoDevices) {
|
||||
QByteArray deviceId([[device uniqueID] UTF8String]);
|
||||
m_cameraDevices << deviceId;
|
||||
m_cameraDescriptions.insert(deviceId, QString::fromUtf8([[device localizedName] UTF8String]));
|
||||
}
|
||||
int AVFServicePlugin::cameraOrientation(const QByteArray &device) const
|
||||
{
|
||||
return AVFCameraSession::cameraDeviceInfo(device).orientation;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -55,6 +55,16 @@ class AVFCameraControl;
|
||||
class AVFCameraService;
|
||||
class AVFVideoRendererControl;
|
||||
|
||||
struct AVFCameraInfo
|
||||
{
|
||||
AVFCameraInfo() : position(QCamera::UnspecifiedPosition), orientation(0)
|
||||
{ }
|
||||
|
||||
QString description;
|
||||
QCamera::Position position;
|
||||
int orientation;
|
||||
};
|
||||
|
||||
class AVFCameraSession : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -62,6 +72,10 @@ public:
|
||||
AVFCameraSession(AVFCameraService *service, QObject *parent = 0);
|
||||
~AVFCameraSession();
|
||||
|
||||
static const QByteArray &defaultCameraDevice();
|
||||
static const QList<QByteArray> &availableCameraDevices();
|
||||
static AVFCameraInfo cameraDeviceInfo(const QByteArray &device);
|
||||
|
||||
void setVideoOutput(AVFVideoRendererControl *output);
|
||||
AVCaptureSession *captureSession() const { return m_captureSession; }
|
||||
AVCaptureDevice *videoCaptureDevice() const;
|
||||
@@ -84,8 +98,13 @@ Q_SIGNALS:
|
||||
void error(int error, const QString &errorString);
|
||||
|
||||
private:
|
||||
static void updateCameraDevices();
|
||||
void attachInputDevices();
|
||||
|
||||
static QByteArray m_defaultCameraDevice;
|
||||
static QList<QByteArray> m_cameraDevices;
|
||||
static QMap<QByteArray, AVFCameraInfo> m_cameraInfo;
|
||||
|
||||
AVFCameraService *m_service;
|
||||
AVFVideoRendererControl *m_videoOutput;
|
||||
|
||||
|
||||
@@ -57,6 +57,10 @@
|
||||
|
||||
QT_USE_NAMESPACE
|
||||
|
||||
QByteArray AVFCameraSession::m_defaultCameraDevice;
|
||||
QList<QByteArray> AVFCameraSession::m_cameraDevices;
|
||||
QMap<QByteArray, AVFCameraInfo> AVFCameraSession::m_cameraInfo;
|
||||
|
||||
@interface AVFCameraSessionObserver : NSObject
|
||||
{
|
||||
@private
|
||||
@@ -81,6 +85,7 @@ QT_USE_NAMESPACE
|
||||
self->m_session = session;
|
||||
self->m_captureSession = session->captureSession();
|
||||
|
||||
[m_captureSession retain];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(processRuntimeError:)
|
||||
name:AVCaptureSessionRuntimeErrorNotification
|
||||
@@ -99,6 +104,22 @@ QT_USE_NAMESPACE
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:AVCaptureSessionRuntimeErrorNotification
|
||||
object:m_captureSession];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:AVCaptureSessionDidStartRunningNotification
|
||||
object:m_captureSession];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:AVCaptureSessionDidStopRunningNotification
|
||||
object:m_captureSession];
|
||||
[m_captureSession release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) processRuntimeError:(NSNotification *)notification
|
||||
{
|
||||
@@ -151,6 +172,74 @@ AVFCameraSession::~AVFCameraSession()
|
||||
[m_captureSession release];
|
||||
}
|
||||
|
||||
const QByteArray &AVFCameraSession::defaultCameraDevice()
|
||||
{
|
||||
if (m_cameraDevices.isEmpty())
|
||||
updateCameraDevices();
|
||||
|
||||
return m_defaultCameraDevice;
|
||||
}
|
||||
|
||||
const QList<QByteArray> &AVFCameraSession::availableCameraDevices()
|
||||
{
|
||||
if (m_cameraDevices.isEmpty())
|
||||
updateCameraDevices();
|
||||
|
||||
return m_cameraDevices;
|
||||
}
|
||||
|
||||
AVFCameraInfo AVFCameraSession::cameraDeviceInfo(const QByteArray &device)
|
||||
{
|
||||
if (m_cameraDevices.isEmpty())
|
||||
updateCameraDevices();
|
||||
|
||||
return m_cameraInfo.value(device);
|
||||
}
|
||||
|
||||
void AVFCameraSession::updateCameraDevices()
|
||||
{
|
||||
m_defaultCameraDevice.clear();
|
||||
m_cameraDevices.clear();
|
||||
m_cameraInfo.clear();
|
||||
|
||||
AVCaptureDevice *defaultDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
||||
if (defaultDevice)
|
||||
m_defaultCameraDevice = QByteArray([[defaultDevice uniqueID] UTF8String]);
|
||||
|
||||
NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
|
||||
for (AVCaptureDevice *device in videoDevices) {
|
||||
QByteArray deviceId([[device uniqueID] UTF8String]);
|
||||
|
||||
AVFCameraInfo info;
|
||||
info.description = QString::fromNSString([device localizedName]);
|
||||
|
||||
// There is no API to get the camera sensor orientation, however, cameras are always
|
||||
// mounted in landscape on iDevices.
|
||||
// - Back-facing cameras have the top side of the sensor aligned with the right side of
|
||||
// the screen when held in portrait ==> 270 degrees clockwise angle
|
||||
// - Front-facing cameras have the top side of the sensor aligned with the left side of
|
||||
// the screen when held in portrait ==> 270 degrees clockwise angle
|
||||
// On Mac OS, the position will always be unspecified and the sensor orientation unknown.
|
||||
switch (device.position) {
|
||||
case AVCaptureDevicePositionBack:
|
||||
info.position = QCamera::BackFace;
|
||||
info.orientation = 270;
|
||||
break;
|
||||
case AVCaptureDevicePositionFront:
|
||||
info.position = QCamera::FrontFace;
|
||||
info.orientation = 270;
|
||||
break;
|
||||
default:
|
||||
info.position = QCamera::UnspecifiedPosition;
|
||||
info.orientation = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
m_cameraDevices << deviceId;
|
||||
m_cameraInfo.insert(deviceId, info);
|
||||
}
|
||||
}
|
||||
|
||||
void AVFCameraSession::setVideoOutput(AVFVideoRendererControl *output)
|
||||
{
|
||||
m_videoOutput = output;
|
||||
|
||||
@@ -80,8 +80,6 @@ private:
|
||||
|
||||
int m_selectedDevice;
|
||||
bool m_dirty;
|
||||
QStringList m_devices;
|
||||
QStringList m_deviceDescriptions;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "avfcameradebug.h"
|
||||
#include "avfvideodevicecontrol.h"
|
||||
#include "avfcameraservice.h"
|
||||
#include "avfcamerasession.h"
|
||||
|
||||
QT_USE_NAMESPACE
|
||||
|
||||
@@ -51,11 +52,6 @@ AVFVideoDeviceControl::AVFVideoDeviceControl(AVFCameraService *service, QObject
|
||||
, m_selectedDevice(0)
|
||||
, m_dirty(true)
|
||||
{
|
||||
NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
|
||||
for (AVCaptureDevice *device in videoDevices) {
|
||||
m_devices << QString::fromUtf8([[device uniqueID] UTF8String]);
|
||||
m_deviceDescriptions << QString::fromUtf8([[device localizedName] UTF8String]);
|
||||
}
|
||||
}
|
||||
|
||||
AVFVideoDeviceControl::~AVFVideoDeviceControl()
|
||||
@@ -64,22 +60,30 @@ AVFVideoDeviceControl::~AVFVideoDeviceControl()
|
||||
|
||||
int AVFVideoDeviceControl::deviceCount() const
|
||||
{
|
||||
return m_devices.size();
|
||||
return AVFCameraSession::availableCameraDevices().count();
|
||||
}
|
||||
|
||||
QString AVFVideoDeviceControl::deviceName(int index) const
|
||||
{
|
||||
return m_devices[index];
|
||||
const QList<QByteArray> &devices = AVFCameraSession::availableCameraDevices();
|
||||
if (index < 0 || index >= devices.count())
|
||||
return QString();
|
||||
|
||||
return QString::fromUtf8(devices.at(index));
|
||||
}
|
||||
|
||||
QString AVFVideoDeviceControl::deviceDescription(int index) const
|
||||
{
|
||||
return m_deviceDescriptions[index];
|
||||
const QList<QByteArray> &devices = AVFCameraSession::availableCameraDevices();
|
||||
if (index < 0 || index >= devices.count())
|
||||
return QString();
|
||||
|
||||
return AVFCameraSession::cameraDeviceInfo(devices.at(index)).description;
|
||||
}
|
||||
|
||||
int AVFVideoDeviceControl::defaultDevice() const
|
||||
{
|
||||
return 0;
|
||||
return AVFCameraSession::availableCameraDevices().indexOf(AVFCameraSession::defaultCameraDevice());
|
||||
}
|
||||
|
||||
int AVFVideoDeviceControl::selectedDevice() const
|
||||
@@ -89,11 +93,13 @@ int AVFVideoDeviceControl::selectedDevice() const
|
||||
|
||||
void AVFVideoDeviceControl::setSelectedDevice(int index)
|
||||
{
|
||||
if (index != m_selectedDevice) {
|
||||
if (index >= 0 &&
|
||||
index < deviceCount() &&
|
||||
index != m_selectedDevice) {
|
||||
m_dirty = true;
|
||||
m_selectedDevice = index;
|
||||
Q_EMIT selectedDeviceChanged(index);
|
||||
Q_EMIT selectedDeviceChanged(m_devices[index]);
|
||||
Q_EMIT selectedDeviceChanged(deviceName(index));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,9 +108,8 @@ AVCaptureDevice *AVFVideoDeviceControl::createCaptureDevice()
|
||||
m_dirty = false;
|
||||
AVCaptureDevice *device = 0;
|
||||
|
||||
if (!m_devices.isEmpty()) {
|
||||
QString deviceId = m_devices.at(m_selectedDevice);
|
||||
|
||||
QString deviceId = deviceName(m_selectedDevice);
|
||||
if (!deviceId.isEmpty()) {
|
||||
device = [AVCaptureDevice deviceWithUniqueID:
|
||||
[NSString stringWithUTF8String:
|
||||
deviceId.toUtf8().constData()]];
|
||||
|
||||
@@ -34,6 +34,7 @@ HEADERS += \
|
||||
avfstoragelocation.h \
|
||||
avfvideodevicecontrol.h \
|
||||
avfaudioinputselectorcontrol.h \
|
||||
avfcamerainfocontrol.h
|
||||
|
||||
OBJECTIVE_SOURCES += \
|
||||
avfcameraserviceplugin.mm \
|
||||
@@ -47,4 +48,5 @@ OBJECTIVE_SOURCES += \
|
||||
avfstoragelocation.mm \
|
||||
avfvideodevicecontrol.mm \
|
||||
avfaudioinputselectorcontrol.mm \
|
||||
avfcamerainfocontrol.mm
|
||||
|
||||
|
||||
@@ -133,7 +133,8 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
|
||||
|
||||
- (void) unloadMedia
|
||||
{
|
||||
[m_player setRate:0.0];
|
||||
if (m_player)
|
||||
[m_player setRate:0.0];
|
||||
if (m_playerItem) {
|
||||
[m_playerItem removeObserver:self forKeyPath:AVF_STATUS_KEY];
|
||||
|
||||
@@ -407,10 +408,12 @@ static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMe
|
||||
[m_player removeObserver:self forKeyPath:AVF_CURRENT_ITEM_KEY];
|
||||
[m_player removeObserver:self forKeyPath:AVF_RATE_KEY];
|
||||
[m_player release];
|
||||
m_player = 0;
|
||||
}
|
||||
|
||||
if (m_playerLayer) {
|
||||
[m_playerLayer release];
|
||||
m_playerLayer = 0;
|
||||
}
|
||||
|
||||
[self unloadMedia];
|
||||
|
||||
@@ -120,7 +120,7 @@ QImage AVFVideoFrameRenderer::renderLayerToImage(AVPlayerLayer *layer)
|
||||
return QImage();
|
||||
|
||||
renderLayerToFBO(layer, fbo);
|
||||
QImage fboImage = fbo->toImage().mirrored();
|
||||
QImage fboImage = fbo->toImage();
|
||||
m_glContext->doneCurrent();
|
||||
|
||||
return fboImage;
|
||||
@@ -204,7 +204,8 @@ void AVFVideoFrameRenderer::renderLayerToFBO(AVPlayerLayer *layer, QOpenGLFrameb
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glOrtho(0.0f, m_targetSize.width(), m_targetSize.height(), 0.0f, 0.0f, 1.0f);
|
||||
//Render to FBO with inverted Y
|
||||
glOrtho(0.0, m_targetSize.width(), 0.0, m_targetSize.height(), 0.0, 1.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
||||
@@ -182,6 +182,11 @@ void AVFVideoRendererControl::setLayer(void *playerLayer)
|
||||
|
||||
m_playerLayer = playerLayer;
|
||||
|
||||
//If there is an active surface, make sure it has been stopped so that
|
||||
//we can update it's state with the new content.
|
||||
if (m_surface && m_surface->isActive())
|
||||
m_surface->stop();
|
||||
|
||||
//If there is no layer to render, stop scheduling updates
|
||||
if (m_playerLayer == 0) {
|
||||
m_displayLink->stop();
|
||||
|
||||
@@ -121,7 +121,7 @@ void AVFVideoWidget::setPlayerLayer(AVPlayerLayer *layer)
|
||||
[nativeLayer addSublayer:m_playerLayer];
|
||||
updatePlayerLayerBounds(this->size());
|
||||
}
|
||||
|
||||
#ifdef QT_DEBUG_AVF
|
||||
NSArray *sublayers = [nativeLayer sublayers];
|
||||
qDebug() << "playerlayer: " << "at z:" << [m_playerLayer zPosition]
|
||||
<< " frame: " << m_playerLayer.frame.size.width << "x" << m_playerLayer.frame.size.height;
|
||||
@@ -133,7 +133,7 @@ void AVFVideoWidget::setPlayerLayer(AVPlayerLayer *layer)
|
||||
<< " frame: " << layer.frame.size.width << "x" << layer.frame.size.height;
|
||||
i++;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,11 @@ CoreAudioDeviceInfo::CoreAudioDeviceInfo(const QByteArray &device, QAudio::Mode
|
||||
m_deviceId = AudioDeviceID(deviceID);
|
||||
#else //iOS
|
||||
m_device = device;
|
||||
if (mode == QAudio::AudioInput) {
|
||||
if (CoreAudioSessionManager::instance().category() != CoreAudioSessionManager::PlayAndRecord) {
|
||||
CoreAudioSessionManager::instance().setCategory(CoreAudioSessionManager::PlayAndRecord);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -130,9 +135,11 @@ bool CoreAudioDeviceInfo::isFormatSupported(const QAudioFormat &format) const
|
||||
{
|
||||
CoreAudioDeviceInfo *self = const_cast<CoreAudioDeviceInfo*>(this);
|
||||
|
||||
//Sample rates are more of a suggestion with CoreAudio so as long as we get a
|
||||
//sane value then we can likely use it.
|
||||
return format.isValid()
|
||||
&& format.codec() == QString::fromLatin1("audio/pcm")
|
||||
&& self->supportedSampleRates().contains(format.sampleRate())
|
||||
&& format.sampleRate() > 0
|
||||
&& self->supportedChannelCounts().contains(format.channelCount())
|
||||
&& self->supportedSampleSizes().contains(format.sampleSize());
|
||||
}
|
||||
@@ -168,8 +175,9 @@ QList<int> CoreAudioDeviceInfo::supportedSampleRates()
|
||||
AudioValueRange* vr = new AudioValueRange[pc];
|
||||
|
||||
if (AudioObjectGetPropertyData(m_deviceId, &availableNominalSampleRatesAddress, 0, NULL, &propSize, vr) == noErr) {
|
||||
for (int i = 0; i < pc; ++i)
|
||||
sampleRates << vr[i].mMaximum;
|
||||
for (int i = 0; i < pc; ++i) {
|
||||
sampleRates << vr[i].mMinimum << vr[i].mMaximum;
|
||||
}
|
||||
}
|
||||
|
||||
delete vr;
|
||||
@@ -324,7 +332,7 @@ QByteArray CoreAudioDeviceInfo::defaultOutputDevice()
|
||||
#if defined(Q_OS_OSX)
|
||||
AudioDeviceID audioDevice;
|
||||
UInt32 size = sizeof(audioDevice);
|
||||
AudioObjectPropertyAddress defaultOutputDevicePropertyAddress = { kAudioHardwarePropertyDefaultInputDevice,
|
||||
AudioObjectPropertyAddress defaultOutputDevicePropertyAddress = { kAudioHardwarePropertyDefaultOutputDevice,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster };
|
||||
|
||||
@@ -360,10 +368,15 @@ QList<QByteArray> CoreAudioDeviceInfo::availableDevices(QAudio::Mode mode)
|
||||
AudioDeviceID* audioDevices = new AudioDeviceID[dc];
|
||||
|
||||
if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &audioDevicesPropertyAddress, 0, NULL, &propSize, audioDevices) == noErr) {
|
||||
QByteArray defaultDevice = (mode == QAudio::AudioOutput) ? defaultOutputDevice() : defaultInputDevice();
|
||||
for (int i = 0; i < dc; ++i) {
|
||||
QByteArray info = get_device_info(audioDevices[i], mode);
|
||||
if (!info.isNull())
|
||||
devices << info;
|
||||
if (!info.isNull()) {
|
||||
if (info == defaultDevice)
|
||||
devices.prepend(info);
|
||||
else
|
||||
devices << info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,6 +384,12 @@ QList<QByteArray> CoreAudioDeviceInfo::availableDevices(QAudio::Mode mode)
|
||||
}
|
||||
}
|
||||
#else //iOS
|
||||
if (mode == QAudio::AudioInput) {
|
||||
if (CoreAudioSessionManager::instance().category() != CoreAudioSessionManager::PlayAndRecord) {
|
||||
CoreAudioSessionManager::instance().setCategory(CoreAudioSessionManager::PlayAndRecord);
|
||||
}
|
||||
}
|
||||
|
||||
CoreAudioSessionManager::instance().setActive(true);
|
||||
|
||||
if (mode == QAudio::AudioOutput)
|
||||
|
||||
@@ -47,6 +47,10 @@
|
||||
# include <CoreServices/CoreServices.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_IOS)
|
||||
# include "coreaudiosessionmanager.h"
|
||||
#endif
|
||||
|
||||
#include <QtMultimedia/private/qaudiohelpers_p.h>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
|
||||
@@ -52,6 +52,10 @@
|
||||
# include <CoreServices/CoreServices.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_IOS)
|
||||
# include <QtMultimedia/private/qaudiohelpers_p.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static const int DEFAULT_BUFFER_SIZE = 8 * 1024;
|
||||
@@ -430,13 +434,23 @@ QAudioFormat CoreAudioOutput::format() const
|
||||
void CoreAudioOutput::setVolume(qreal volume)
|
||||
{
|
||||
const qreal normalizedVolume = qBound(qreal(0.0), volume, qreal(1.0));
|
||||
m_cachedVolume = normalizedVolume;
|
||||
if (!m_isOpen) {
|
||||
m_cachedVolume = normalizedVolume;
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: actually set the output volume here
|
||||
//To set the output volume you need a handle to the mixer unit
|
||||
#if defined(Q_OS_OSX)
|
||||
//on OS X the volume can be set directly on the AudioUnit
|
||||
if (AudioUnitSetParameter(m_audioUnit,
|
||||
kHALOutputParam_Volume,
|
||||
kAudioUnitScope_Global,
|
||||
0 /* bus */,
|
||||
(float)normalizedVolume,
|
||||
0) == noErr)
|
||||
m_cachedVolume = normalizedVolume;
|
||||
#else
|
||||
m_cachedVolume = normalizedVolume;
|
||||
#endif
|
||||
}
|
||||
|
||||
qreal CoreAudioOutput::volume() const
|
||||
@@ -497,6 +511,17 @@ OSStatus CoreAudioOutput::renderCallback(void *inRefCon, AudioUnitRenderActionFl
|
||||
if (framesRead > 0) {
|
||||
ioData->mBuffers[0].mDataByteSize = framesRead * bytesPerFrame;
|
||||
d->m_totalFrames += framesRead;
|
||||
#ifdef Q_OS_IOS
|
||||
// on iOS we have to adjust the sound volume ourselves
|
||||
if (!qFuzzyCompare(d->m_cachedVolume, qreal(1.0f))) {
|
||||
QAudioHelperInternal::qMultiplySamples(d->m_cachedVolume,
|
||||
d->m_audioFormat,
|
||||
ioData->mBuffers[0].mData, /* input */
|
||||
ioData->mBuffers[0].mData, /* output */
|
||||
ioData->mBuffers[0].mDataByteSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
else {
|
||||
ioData->mBuffers[0].mDataByteSize = 0;
|
||||
|
||||
@@ -216,7 +216,8 @@ CoreAudioSessionManager::CoreAudioSessionManager() :
|
||||
{
|
||||
m_sessionObserver = [[CoreAudioSessionObserver alloc] initWithAudioSessionManager:this];
|
||||
setActive(true);
|
||||
setCategory(CoreAudioSessionManager::PlayAndRecord, CoreAudioSessionManager::MixWithOthers);
|
||||
//set default category to just Playback and only switch if we need more permissions
|
||||
setCategory(CoreAudioSessionManager::Playback, CoreAudioSessionManager::MixWithOthers);
|
||||
}
|
||||
|
||||
CoreAudioSessionManager::~CoreAudioSessionManager()
|
||||
|
||||
@@ -153,7 +153,7 @@ void DSVideoDeviceControl::enumerateDevices(QList<QByteArray> *devices, QStringL
|
||||
|
||||
void DSVideoDeviceControl::setSelectedDevice(int index)
|
||||
{
|
||||
if (index >= 0 && index <= m_devices.count()) {
|
||||
if (index >= 0 && index < m_devices.count()) {
|
||||
if (m_session) {
|
||||
QString device = m_devices.at(index);
|
||||
if (device.startsWith("ds:"))
|
||||
|
||||
@@ -107,6 +107,20 @@ QMediaServiceProviderHint::Features DSServicePlugin::supportedFeatures(
|
||||
return QMediaServiceProviderHint::Features();
|
||||
}
|
||||
|
||||
QByteArray DSServicePlugin::defaultDevice(const QByteArray &service) const
|
||||
{
|
||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
if (m_cameraDevices.isEmpty())
|
||||
updateDevices();
|
||||
|
||||
return m_defaultCameraDevice;
|
||||
}
|
||||
#endif
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QList<QByteArray> DSServicePlugin::devices(const QByteArray &service) const
|
||||
{
|
||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
||||
@@ -140,10 +154,13 @@ QString DSServicePlugin::deviceDescription(const QByteArray &service, const QByt
|
||||
|
||||
void DSServicePlugin::updateDevices() const
|
||||
{
|
||||
m_defaultCameraDevice.clear();
|
||||
DSVideoDeviceControl::enumerateDevices(&m_cameraDevices, &m_cameraDescriptions);
|
||||
|
||||
if (m_cameraDevices.isEmpty()) {
|
||||
qWarning() << "No camera devices found";
|
||||
} else {
|
||||
m_defaultCameraDevice = m_cameraDevices.first();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -49,10 +49,12 @@ QT_USE_NAMESPACE
|
||||
class DSServicePlugin
|
||||
: public QMediaServiceProviderPlugin
|
||||
, public QMediaServiceSupportedDevicesInterface
|
||||
, public QMediaServiceDefaultDeviceInterface
|
||||
, public QMediaServiceFeaturesInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
|
||||
Q_INTERFACES(QMediaServiceDefaultDeviceInterface)
|
||||
Q_INTERFACES(QMediaServiceFeaturesInterface)
|
||||
// The player service provided by the WMF-plugin should preferably be used.
|
||||
// DirectShow should then only provide the camera (see QTBUG-29172, QTBUG-29175).
|
||||
@@ -68,6 +70,7 @@ public:
|
||||
|
||||
QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const;
|
||||
|
||||
QByteArray defaultDevice(const QByteArray &service) const;
|
||||
QList<QByteArray> devices(const QByteArray &service) const;
|
||||
QString deviceDescription(const QByteArray &service, const QByteArray &device);
|
||||
|
||||
@@ -75,6 +78,7 @@ private:
|
||||
#ifdef QMEDIA_DIRECTSHOW_CAMERA
|
||||
void updateDevices() const;
|
||||
|
||||
mutable QByteArray m_defaultCameraDevice;
|
||||
mutable QList<QByteArray> m_cameraDevices;
|
||||
mutable QStringList m_cameraDescriptions;
|
||||
#endif
|
||||
|
||||
@@ -198,11 +198,13 @@ QVariant CameraBinMetaData::metaData(const QString &key) const
|
||||
void CameraBinMetaData::setMetaData(const QString &key, const QVariant &value)
|
||||
{
|
||||
QVariant correctedValue = value;
|
||||
if (key == QMediaMetaData::Orientation) {
|
||||
correctedValue = toGStreamerOrientation(value);
|
||||
} else if (key == QMediaMetaData::GPSSpeed) {
|
||||
// kilometers per hour to meters per second.
|
||||
correctedValue = (value.toDouble() * 1000) / 3600;
|
||||
if (value.isValid()) {
|
||||
if (key == QMediaMetaData::Orientation) {
|
||||
correctedValue = toGStreamerOrientation(value);
|
||||
} else if (key == QMediaMetaData::GPSSpeed) {
|
||||
// kilometers per hour to meters per second.
|
||||
correctedValue = (value.toDouble() * 1000) / 3600;
|
||||
}
|
||||
}
|
||||
|
||||
static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup);
|
||||
@@ -211,9 +213,12 @@ void CameraBinMetaData::setMetaData(const QString &key, const QVariant &value)
|
||||
if (qt_gstreamerMetaDataKeys[i].key == key) {
|
||||
const char *name = qt_gstreamerMetaDataKeys[i].token;
|
||||
|
||||
correctedValue.convert(qt_gstreamerMetaDataKeys[i].type);
|
||||
|
||||
m_values.insert(QByteArray::fromRawData(name, qstrlen(name)), correctedValue);
|
||||
if (correctedValue.isValid()) {
|
||||
correctedValue.convert(qt_gstreamerMetaDataKeys[i].type);
|
||||
m_values.insert(QByteArray::fromRawData(name, qstrlen(name)), correctedValue);
|
||||
} else {
|
||||
m_values.remove(QByteArray::fromRawData(name, qstrlen(name)));
|
||||
}
|
||||
|
||||
emit QMetaDataWriterControl::metaDataChanged();
|
||||
emit metaDataChanged(m_values);
|
||||
|
||||
@@ -90,6 +90,18 @@ QMediaServiceProviderHint::Features CameraBinServicePlugin::supportedFeatures(
|
||||
return QMediaServiceProviderHint::Features();
|
||||
}
|
||||
|
||||
QByteArray CameraBinServicePlugin::defaultDevice(const QByteArray &service) const
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
if (m_cameraDevices.isEmpty())
|
||||
updateDevices();
|
||||
|
||||
return m_defaultCameraDevice;
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QList<QByteArray> CameraBinServicePlugin::devices(const QByteArray &service) const
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
@@ -126,6 +138,7 @@ QVariant CameraBinServicePlugin::deviceProperty(const QByteArray &service, const
|
||||
|
||||
void CameraBinServicePlugin::updateDevices() const
|
||||
{
|
||||
m_defaultCameraDevice.clear();
|
||||
m_cameraDevices.clear();
|
||||
m_cameraDescriptions.clear();
|
||||
|
||||
@@ -167,6 +180,9 @@ void CameraBinServicePlugin::updateDevices() const
|
||||
}
|
||||
::close(fd);
|
||||
}
|
||||
|
||||
if (!m_cameraDevices.isEmpty())
|
||||
m_defaultCameraDevice = m_cameraDevices.first();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -51,10 +51,12 @@ QT_BEGIN_NAMESPACE
|
||||
class CameraBinServicePlugin
|
||||
: public QMediaServiceProviderPlugin
|
||||
, public QMediaServiceSupportedDevicesInterface
|
||||
, public QMediaServiceDefaultDeviceInterface
|
||||
, public QMediaServiceFeaturesInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
|
||||
Q_INTERFACES(QMediaServiceDefaultDeviceInterface)
|
||||
Q_INTERFACES(QMediaServiceFeaturesInterface)
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "camerabin.json")
|
||||
public:
|
||||
@@ -63,6 +65,7 @@ public:
|
||||
|
||||
QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const;
|
||||
|
||||
QByteArray defaultDevice(const QByteArray &service) const;
|
||||
QList<QByteArray> devices(const QByteArray &service) const;
|
||||
QString deviceDescription(const QByteArray &service, const QByteArray &device);
|
||||
QVariant deviceProperty(const QByteArray &service, const QByteArray &device, const QByteArray &property);
|
||||
@@ -70,6 +73,7 @@ public:
|
||||
private:
|
||||
void updateDevices() const;
|
||||
|
||||
mutable QByteArray m_defaultCameraDevice;
|
||||
mutable QList<QByteArray> m_cameraDevices;
|
||||
mutable QStringList m_cameraDescriptions;
|
||||
};
|
||||
|
||||
@@ -756,6 +756,8 @@ void CameraBinSession::setMetaData(const QMap<QByteArray, QVariant> &data)
|
||||
GstIterator *elements = gst_bin_iterate_all_by_interface(GST_BIN(m_camerabin), GST_TYPE_TAG_SETTER);
|
||||
GstElement *element = 0;
|
||||
while (gst_iterator_next(elements, (void**)&element) == GST_ITERATOR_OK) {
|
||||
gst_tag_setter_reset_tags(GST_TAG_SETTER(element));
|
||||
|
||||
QMapIterator<QByteArray, QVariant> it(data);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
|
||||
@@ -95,6 +95,18 @@ QMediaServiceProviderHint::Features QGstreamerCaptureServicePlugin::supportedFea
|
||||
return QMediaServiceProviderHint::Features();
|
||||
}
|
||||
|
||||
QByteArray QGstreamerCaptureServicePlugin::defaultDevice(const QByteArray &service) const
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
if (m_cameraDevices.isEmpty())
|
||||
updateDevices();
|
||||
|
||||
return m_defaultCameraDevice;
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QList<QByteArray> QGstreamerCaptureServicePlugin::devices(const QByteArray &service) const
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
@@ -131,6 +143,7 @@ QVariant QGstreamerCaptureServicePlugin::deviceProperty(const QByteArray &servic
|
||||
|
||||
void QGstreamerCaptureServicePlugin::updateDevices() const
|
||||
{
|
||||
m_defaultCameraDevice.clear();
|
||||
m_cameraDevices.clear();
|
||||
m_cameraDescriptions.clear();
|
||||
|
||||
@@ -174,6 +187,9 @@ void QGstreamerCaptureServicePlugin::updateDevices() const
|
||||
}
|
||||
::close(fd);
|
||||
}
|
||||
|
||||
if (!m_cameraDevices.isEmpty())
|
||||
m_defaultCameraDevice = m_cameraDevices.first();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ class QGstreamerCaptureServicePlugin
|
||||
: public QMediaServiceProviderPlugin
|
||||
#if defined(USE_GSTREAMER_CAMERA)
|
||||
, public QMediaServiceSupportedDevicesInterface
|
||||
, public QMediaServiceDefaultDeviceInterface
|
||||
, public QMediaServiceFeaturesInterface
|
||||
#endif
|
||||
, public QMediaServiceSupportedFormatsInterface
|
||||
@@ -60,6 +61,7 @@ class QGstreamerCaptureServicePlugin
|
||||
Q_OBJECT
|
||||
#if defined(USE_GSTREAMER_CAMERA)
|
||||
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
|
||||
Q_INTERFACES(QMediaServiceDefaultDeviceInterface)
|
||||
Q_INTERFACES(QMediaServiceFeaturesInterface)
|
||||
#endif
|
||||
Q_INTERFACES(QMediaServiceSupportedFormatsInterface)
|
||||
@@ -75,6 +77,7 @@ public:
|
||||
#if defined(USE_GSTREAMER_CAMERA)
|
||||
QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const;
|
||||
|
||||
QByteArray defaultDevice(const QByteArray &service) const;
|
||||
QList<QByteArray> devices(const QByteArray &service) const;
|
||||
QString deviceDescription(const QByteArray &service, const QByteArray &device);
|
||||
QVariant deviceProperty(const QByteArray &service, const QByteArray &device, const QByteArray &property);
|
||||
@@ -87,6 +90,7 @@ private:
|
||||
#if defined(USE_GSTREAMER_CAMERA)
|
||||
void updateDevices() const;
|
||||
|
||||
mutable QByteArray m_defaultCameraDevice;
|
||||
mutable QList<QByteArray> m_cameraDevices;
|
||||
mutable QStringList m_cameraDescriptions;
|
||||
#endif
|
||||
|
||||
@@ -74,6 +74,18 @@ QMediaServiceProviderHint::Features BbServicePlugin::supportedFeatures(const QBy
|
||||
return QMediaServiceProviderHint::Features();
|
||||
}
|
||||
|
||||
QByteArray BbServicePlugin::defaultDevice(const QByteArray &service) const
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
if (m_cameraDevices.isEmpty())
|
||||
updateDevices();
|
||||
|
||||
return m_defaultCameraDevice;
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QList<QByteArray> BbServicePlugin::devices(const QByteArray &service) const
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA) {
|
||||
@@ -102,10 +114,13 @@ QString BbServicePlugin::deviceDescription(const QByteArray &service, const QByt
|
||||
|
||||
void BbServicePlugin::updateDevices() const
|
||||
{
|
||||
m_defaultCameraDevice.clear();
|
||||
BbVideoDeviceSelectorControl::enumerateDevices(&m_cameraDevices, &m_cameraDescriptions);
|
||||
|
||||
if (m_cameraDevices.isEmpty()) {
|
||||
qWarning() << "No camera devices found";
|
||||
} else {
|
||||
m_defaultCameraDevice = m_cameraDevices.first();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,10 +48,12 @@ QT_BEGIN_NAMESPACE
|
||||
class BbServicePlugin
|
||||
: public QMediaServiceProviderPlugin,
|
||||
public QMediaServiceSupportedDevicesInterface,
|
||||
public QMediaServiceDefaultDeviceInterface,
|
||||
public QMediaServiceFeaturesInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
|
||||
Q_INTERFACES(QMediaServiceDefaultDeviceInterface)
|
||||
Q_INTERFACES(QMediaServiceFeaturesInterface)
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "blackberry_mediaservice.json")
|
||||
public:
|
||||
@@ -61,6 +63,7 @@ public:
|
||||
void release(QMediaService *service) Q_DECL_OVERRIDE;
|
||||
QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const Q_DECL_OVERRIDE;
|
||||
|
||||
QByteArray defaultDevice(const QByteArray &service) const Q_DECL_OVERRIDE;
|
||||
QList<QByteArray> devices(const QByteArray &service) const Q_DECL_OVERRIDE;
|
||||
QString deviceDescription(const QByteArray &service, const QByteArray &device) Q_DECL_OVERRIDE;
|
||||
QVariant deviceProperty(const QByteArray &service, const QByteArray &device, const QByteArray &property) Q_DECL_OVERRIDE;
|
||||
@@ -68,6 +71,7 @@ public:
|
||||
private:
|
||||
void updateDevices() const;
|
||||
|
||||
mutable QByteArray m_defaultCameraDevice;
|
||||
mutable QList<QByteArray> m_cameraDevices;
|
||||
mutable QStringList m_cameraDescriptions;
|
||||
};
|
||||
|
||||
@@ -64,7 +64,7 @@ static QString errorToString(camera_error_t error)
|
||||
case CAMERA_EAGAIN:
|
||||
return QLatin1String("Camera unavailable");
|
||||
case CAMERA_EINVAL:
|
||||
return QLatin1String("Inavlid argument");
|
||||
return QLatin1String("Invalid argument");
|
||||
case CAMERA_ENODEV:
|
||||
return QLatin1String("Camera not found");
|
||||
case CAMERA_EMFILE:
|
||||
|
||||
@@ -56,6 +56,9 @@
|
||||
|
||||
QSGVivanteVideoMaterial::QSGVivanteVideoMaterial() :
|
||||
mOpacity(1.0),
|
||||
mWidth(0),
|
||||
mHeight(0),
|
||||
mFormat(QVideoFrame::Format_Invalid),
|
||||
mCurrentTexture(0)
|
||||
{
|
||||
#ifdef QT_VIVANTE_VIDEO_DEBUG
|
||||
@@ -147,6 +150,18 @@ GLuint QSGVivanteVideoMaterial::vivanteMapping(QVideoFrame vF)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mWidth != vF.width() || mHeight != vF.height() || mFormat != vF.pixelFormat()) {
|
||||
mWidth = vF.width();
|
||||
mHeight = vF.height();
|
||||
mFormat = vF.pixelFormat();
|
||||
for (GLuint id : mBitsToTextureMap.values()) {
|
||||
#ifdef QT_VIVANTE_VIDEO_DEBUG
|
||||
qDebug() << "delete texture: " << id;
|
||||
#endif
|
||||
glDeleteTextures(1, &id);
|
||||
}
|
||||
mBitsToTextureMap.clear();
|
||||
}
|
||||
|
||||
if (vF.map(QAbstractVideoBuffer::ReadOnly)) {
|
||||
|
||||
|
||||
@@ -70,6 +70,10 @@ public:
|
||||
private:
|
||||
qreal mOpacity;
|
||||
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
QVideoFrame::PixelFormat mFormat;
|
||||
|
||||
QMap<const uchar*, GLuint> mBitsToTextureMap;
|
||||
QVideoFrame mCurrentFrame, mNextFrame;
|
||||
GLuint mCurrentTexture;
|
||||
|
||||
@@ -91,7 +91,7 @@ const char *QSGVivanteVideoMaterialShader::fragmentShader() const {
|
||||
""
|
||||
"void main()"
|
||||
"{"
|
||||
" gl_FragColor = texture2D( texture, qt_TexCoord ) * opacity;\n"
|
||||
" gl_FragColor = vec4(texture2D( texture, qt_TexCoord ).rgb, 1.0) * opacity;\n"
|
||||
"}";
|
||||
return shader;
|
||||
}
|
||||
|
||||
@@ -71,16 +71,14 @@ const QMap<QVideoFrame::PixelFormat, GLenum>& QSGVivanteVideoNode::getVideoForma
|
||||
if (static_VideoFormat2GLFormatMap.isEmpty()) {
|
||||
static_VideoFormat2GLFormatMap.insert(QVideoFrame::Format_YV12, GL_VIV_YV12);
|
||||
static_VideoFormat2GLFormatMap.insert(QVideoFrame::Format_NV12, GL_VIV_NV12);
|
||||
|
||||
|
||||
// The following formats should work but are untested!
|
||||
static_VideoFormat2GLFormatMap.insert(QVideoFrame::Format_NV21, GL_VIV_NV21);
|
||||
static_VideoFormat2GLFormatMap.insert(QVideoFrame::Format_UYVY, GL_VIV_UYVY);
|
||||
static_VideoFormat2GLFormatMap.insert(QVideoFrame::Format_YUYV, GL_VIV_YUY2);
|
||||
static_VideoFormat2GLFormatMap.insert(QVideoFrame::Format_RGB32, GL_RGBA);
|
||||
static_VideoFormat2GLFormatMap.insert(QVideoFrame::Format_RGB24, GL_RGB);
|
||||
static_VideoFormat2GLFormatMap.insert(QVideoFrame::Format_RGB32, GL_BGRA_EXT);
|
||||
static_VideoFormat2GLFormatMap.insert(QVideoFrame::Format_ARGB32, GL_BGRA_EXT);
|
||||
static_VideoFormat2GLFormatMap.insert(QVideoFrame::Format_BGR32, GL_RGBA);
|
||||
static_VideoFormat2GLFormatMap.insert(QVideoFrame::Format_BGRA32, GL_RGBA);
|
||||
static_VideoFormat2GLFormatMap.insert(QVideoFrame::Format_RGB565, GL_RGB565);
|
||||
static_VideoFormat2GLFormatMap.insert(QVideoFrame::Format_BGRA32, GL_BGRA_EXT);
|
||||
}
|
||||
|
||||
return static_VideoFormat2GLFormatMap;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
*imx6* {
|
||||
config_gpu_vivante {
|
||||
SUBDIRS += imx6
|
||||
}
|
||||
|
||||
@@ -1325,8 +1325,10 @@ void MFPlayerSession::setVolume(int volume)
|
||||
if (m_volume == volume)
|
||||
return;
|
||||
m_volume = volume;
|
||||
if (m_volumeControl)
|
||||
m_volumeControl->SetMasterVolume(m_volume * 0.01f);
|
||||
|
||||
if (!m_muted)
|
||||
setVolumeInternal(volume);
|
||||
|
||||
emit volumeChanged(m_volume);
|
||||
}
|
||||
|
||||
@@ -1340,11 +1342,26 @@ void MFPlayerSession::setMuted(bool muted)
|
||||
if (m_muted == muted)
|
||||
return;
|
||||
m_muted = muted;
|
||||
if (m_volumeControl)
|
||||
m_volumeControl->SetMute(BOOL(m_muted));
|
||||
|
||||
setVolumeInternal(muted ? 0 : m_volume);
|
||||
|
||||
emit mutedChanged(m_muted);
|
||||
}
|
||||
|
||||
void MFPlayerSession::setVolumeInternal(int volume)
|
||||
{
|
||||
if (m_volumeControl) {
|
||||
quint32 channelCount = 0;
|
||||
if (!SUCCEEDED(m_volumeControl->GetChannelCount(&channelCount))
|
||||
|| channelCount == 0)
|
||||
return;
|
||||
|
||||
float scaled = volume * 0.01f;
|
||||
for (quint32 i = 0; i < channelCount; ++i)
|
||||
m_volumeControl->SetChannelVolume(i, scaled);
|
||||
}
|
||||
}
|
||||
|
||||
int MFPlayerSession::bufferStatus()
|
||||
{
|
||||
if (!m_netsourceStatistics)
|
||||
@@ -1570,10 +1587,8 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent)
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(MFGetService(m_session, MR_POLICY_VOLUME_SERVICE, IID_PPV_ARGS(&m_volumeControl)))) {
|
||||
m_volumeControl->SetMasterVolume(m_volume * 0.01f);
|
||||
m_volumeControl->SetMute(m_muted);
|
||||
}
|
||||
if (SUCCEEDED(MFGetService(m_session, MR_STREAM_VOLUME_SERVICE, IID_PPV_ARGS(&m_volumeControl))))
|
||||
setVolumeInternal(m_muted ? 0 : m_volume);
|
||||
|
||||
DWORD dwCharacteristics = 0;
|
||||
m_sourceResolver->mediaSource()->GetCharacteristics(&dwCharacteristics);
|
||||
@@ -1619,25 +1634,6 @@ void MFPlayerSession::handleSessionEvent(IMFMediaEvent *sessionEvent)
|
||||
break;
|
||||
case MEEndOfPresentationSegment:
|
||||
break;
|
||||
case MEAudioSessionVolumeChanged:
|
||||
if (m_volumeControl) {
|
||||
float currentVolume = 1;
|
||||
if (SUCCEEDED(m_volumeControl->GetMasterVolume(¤tVolume))) {
|
||||
int scaledVolume = currentVolume * 100;
|
||||
if (scaledVolume != m_volume) {
|
||||
m_volume = scaledVolume;
|
||||
emit volumeChanged(scaledVolume);
|
||||
}
|
||||
}
|
||||
BOOL currentMuted = FALSE;
|
||||
if (SUCCEEDED(m_volumeControl->GetMute(¤tMuted))) {
|
||||
if (currentMuted != BOOL(m_muted)) {
|
||||
m_muted = bool(currentMuted);
|
||||
emit mutedChanged(m_muted);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MESessionTopologyStatus: {
|
||||
UINT32 status;
|
||||
if (SUCCEEDED(sessionEvent->GetUINT32(MF_EVENT_TOPOLOGY_STATUS, &status))) {
|
||||
|
||||
@@ -152,7 +152,7 @@ private:
|
||||
IMFPresentationClock *m_presentationClock;
|
||||
IMFRateControl *m_rateControl;
|
||||
IMFRateSupport *m_rateSupport;
|
||||
IMFSimpleAudioVolume *m_volumeControl;
|
||||
IMFAudioStreamVolume *m_volumeControl;
|
||||
IPropertyStore *m_netsourceStatistics;
|
||||
PROPVARIANT m_varStart;
|
||||
UINT64 m_duration;
|
||||
@@ -218,6 +218,8 @@ private:
|
||||
int m_volume;
|
||||
bool m_muted;
|
||||
|
||||
void setVolumeInternal(int volume);
|
||||
|
||||
void createSession();
|
||||
void setupPlaybackTopology(IMFMediaSource *source, IMFPresentationDescriptor *sourcePD);
|
||||
IMFTopologyNode* addSourceNode(IMFTopology* topology, IMFMediaSource* source,
|
||||
|
||||
@@ -105,6 +105,11 @@ QMediaServiceProviderHint::Features WMFServicePlugin::supportedFeatures(
|
||||
return QMediaServiceProviderHint::Features();
|
||||
}
|
||||
|
||||
QByteArray WMFServicePlugin::defaultDevice(const QByteArray &) const
|
||||
{
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QList<QByteArray> WMFServicePlugin::devices(const QByteArray &) const
|
||||
{
|
||||
return QList<QByteArray>();
|
||||
|
||||
@@ -49,10 +49,12 @@ QT_USE_NAMESPACE
|
||||
class WMFServicePlugin
|
||||
: public QMediaServiceProviderPlugin
|
||||
, public QMediaServiceSupportedDevicesInterface
|
||||
, public QMediaServiceDefaultDeviceInterface
|
||||
, public QMediaServiceFeaturesInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
|
||||
Q_INTERFACES(QMediaServiceDefaultDeviceInterface)
|
||||
Q_INTERFACES(QMediaServiceFeaturesInterface)
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "wmf.json")
|
||||
public:
|
||||
@@ -61,6 +63,7 @@ public:
|
||||
|
||||
QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const;
|
||||
|
||||
QByteArray defaultDevice(const QByteArray &service) const;
|
||||
QList<QByteArray> devices(const QByteArray &service) const;
|
||||
QString deviceDescription(const QByteArray &service, const QByteArray &device);
|
||||
};
|
||||
|
||||
@@ -273,12 +273,22 @@ void QDeclarativeVideoOutput::_q_updateMediaObject()
|
||||
|
||||
m_mediaObject.clear();
|
||||
m_service.clear();
|
||||
m_cameraInfo = QCameraInfo();
|
||||
|
||||
if (mediaObject) {
|
||||
if (QMediaService *service = mediaObject->service()) {
|
||||
if (createBackend(service)) {
|
||||
m_service = service;
|
||||
m_mediaObject = mediaObject;
|
||||
const QCamera *camera = qobject_cast<const QCamera *>(mediaObject);
|
||||
if (camera) {
|
||||
m_cameraInfo = QCameraInfo(*camera);
|
||||
|
||||
// The camera position and orientation need to be taken into account for
|
||||
// the viewport auto orientation
|
||||
if (m_autoOrientation)
|
||||
_q_screenOrientationChanged(m_screenOrientationHandler->currentOrientation());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -375,7 +385,21 @@ void QDeclarativeVideoOutput::_q_updateGeometry()
|
||||
|
||||
void QDeclarativeVideoOutput::_q_screenOrientationChanged(int orientation)
|
||||
{
|
||||
setOrientation(orientation);
|
||||
// If the source is a camera, take into account its sensor position and orientation
|
||||
if (!m_cameraInfo.isNull()) {
|
||||
switch (m_cameraInfo.position()) {
|
||||
case QCamera::FrontFace:
|
||||
// Front facing cameras are flipped horizontally, compensate the mirror
|
||||
orientation += (360 - m_cameraInfo.orientation());
|
||||
break;
|
||||
case QCamera::BackFace:
|
||||
default:
|
||||
orientation += m_cameraInfo.orientation();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setOrientation(orientation % 360);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#include <qcameracapturedestinationcontrol.h>
|
||||
#include <qmediaservice.h>
|
||||
#include <qcamera.h>
|
||||
#include <qcamerainfo.h>
|
||||
#include <qcameraimagecapture.h>
|
||||
#include <qvideorenderercontrol.h>
|
||||
#include <private/qmediaserviceprovider_p.h>
|
||||
@@ -82,7 +83,10 @@ public slots:
|
||||
private slots:
|
||||
void testAvailableDevices();
|
||||
void testDeviceDescription();
|
||||
void testCameraInfo();
|
||||
void testCtorWithDevice();
|
||||
void testCtorWithCameraInfo();
|
||||
void testCtorWithPosition();
|
||||
|
||||
void testCameraStates();
|
||||
void testCaptureMode();
|
||||
@@ -126,6 +130,23 @@ void tst_QCameraBackend::testDeviceDescription()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QCameraBackend::testCameraInfo()
|
||||
{
|
||||
int deviceCount = QMediaServiceProvider::defaultServiceProvider()->devices(QByteArray(Q_MEDIASERVICE_CAMERA)).count();
|
||||
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
|
||||
QCOMPARE(cameras.count(), deviceCount);
|
||||
if (cameras.isEmpty()) {
|
||||
QVERIFY(QCameraInfo::defaultCamera().isNull());
|
||||
QSKIP("Camera selection is not supported");
|
||||
}
|
||||
|
||||
foreach (const QCameraInfo &info, cameras) {
|
||||
QVERIFY(!info.deviceName().isEmpty());
|
||||
QVERIFY(!info.description().isEmpty());
|
||||
QVERIFY(info.orientation() % 90 == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QCameraBackend::testCtorWithDevice()
|
||||
{
|
||||
if (QCamera::availableDevices().isEmpty())
|
||||
@@ -142,6 +163,58 @@ void tst_QCameraBackend::testCtorWithDevice()
|
||||
delete camera;
|
||||
}
|
||||
|
||||
void tst_QCameraBackend::testCtorWithCameraInfo()
|
||||
{
|
||||
if (QCameraInfo::availableCameras().isEmpty())
|
||||
QSKIP("Camera selection not supported");
|
||||
|
||||
{
|
||||
QCameraInfo info = QCameraInfo::defaultCamera();
|
||||
QCamera camera(info);
|
||||
QCOMPARE(camera.error(), QCamera::NoError);
|
||||
QCOMPARE(QCameraInfo(camera), info);
|
||||
}
|
||||
{
|
||||
QCameraInfo info = QCameraInfo::availableCameras().first();
|
||||
QCamera camera(info);
|
||||
QCOMPARE(camera.error(), QCamera::NoError);
|
||||
QCOMPARE(QCameraInfo(camera), info);
|
||||
}
|
||||
{
|
||||
// loading an invalid CameraInfo should fail
|
||||
QCamera *camera = new QCamera(QCameraInfo());
|
||||
QCOMPARE(camera->error(), QCamera::ServiceMissingError);
|
||||
QVERIFY(QCameraInfo(*camera).isNull());
|
||||
delete camera;
|
||||
}
|
||||
{
|
||||
// loading non existing camera should fail
|
||||
QCamera camera(QCameraInfo(QUuid::createUuid().toByteArray()));
|
||||
QCOMPARE(camera.error(), QCamera::ServiceMissingError);
|
||||
QVERIFY(QCameraInfo(camera).isNull());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QCameraBackend::testCtorWithPosition()
|
||||
{
|
||||
{
|
||||
QCamera camera(QCamera::UnspecifiedPosition);
|
||||
QCOMPARE(camera.error(), QCamera::NoError);
|
||||
}
|
||||
{
|
||||
QCamera camera(QCamera::FrontFace);
|
||||
// even if no camera is available at this position, it should not fail
|
||||
// and load the default camera
|
||||
QCOMPARE(camera.error(), QCamera::NoError);
|
||||
}
|
||||
{
|
||||
QCamera camera(QCamera::BackFace);
|
||||
// even if no camera is available at this position, it should not fail
|
||||
// and load the default camera
|
||||
QCOMPARE(camera.error(), QCamera::NoError);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QCameraBackend::testCameraStates()
|
||||
{
|
||||
QCamera camera;
|
||||
@@ -283,7 +356,7 @@ void tst_QCameraBackend::testCameraCapture()
|
||||
|
||||
QSignalSpy capturedSignal(&imageCapture, SIGNAL(imageCaptured(int,QImage)));
|
||||
QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString)));
|
||||
QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int, QCameraImageCapture::Error,QString)));
|
||||
QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int,QCameraImageCapture::Error,QString)));
|
||||
|
||||
imageCapture.capture();
|
||||
QTRY_COMPARE(errorSignal.size(), 1);
|
||||
@@ -354,7 +427,7 @@ void tst_QCameraBackend::testCaptureToBuffer()
|
||||
QSignalSpy capturedSignal(&imageCapture, SIGNAL(imageCaptured(int,QImage)));
|
||||
QSignalSpy imageAvailableSignal(&imageCapture, SIGNAL(imageAvailable(int,QVideoFrame)));
|
||||
QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString)));
|
||||
QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int, QCameraImageCapture::Error,QString)));
|
||||
QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int,QCameraImageCapture::Error,QString)));
|
||||
|
||||
camera.start();
|
||||
QTRY_VERIFY(imageCapture.isReadyForCapture());
|
||||
|
||||
@@ -736,9 +736,9 @@ void tst_QMediaPlayerBackend::probes()
|
||||
QAudioProbe *audioProbe = new QAudioProbe;
|
||||
|
||||
ProbeDataHandler probeHandler;
|
||||
connect(videoProbe, SIGNAL(videoFrameProbed(const QVideoFrame&)), &probeHandler, SLOT(processFrame(QVideoFrame)));
|
||||
connect(videoProbe, SIGNAL(videoFrameProbed(QVideoFrame)), &probeHandler, SLOT(processFrame(QVideoFrame)));
|
||||
connect(videoProbe, SIGNAL(flush()), &probeHandler, SLOT(flushVideo()));
|
||||
connect(audioProbe, SIGNAL(audioBufferProbed(const QAudioBuffer&)), &probeHandler, SLOT(processBuffer(QAudioBuffer)));
|
||||
connect(audioProbe, SIGNAL(audioBufferProbed(QAudioBuffer)), &probeHandler, SLOT(processBuffer(QAudioBuffer)));
|
||||
connect(audioProbe, SIGNAL(flush()), &probeHandler, SLOT(flushAudio()));
|
||||
|
||||
QVERIFY(videoProbe->setSource(player));
|
||||
@@ -762,8 +762,8 @@ void tst_QMediaPlayerBackend::playlist()
|
||||
{
|
||||
QMediaPlayer player;
|
||||
|
||||
QSignalSpy mediaSpy(&player, SIGNAL(mediaChanged(const QMediaContent&)));
|
||||
QSignalSpy currentMediaSpy(&player, SIGNAL(currentMediaChanged(const QMediaContent&)));
|
||||
QSignalSpy mediaSpy(&player, SIGNAL(mediaChanged(QMediaContent)));
|
||||
QSignalSpy currentMediaSpy(&player, SIGNAL(currentMediaChanged(QMediaContent)));
|
||||
QSignalSpy stateSpy(&player, SIGNAL(stateChanged(QMediaPlayer::State)));
|
||||
QSignalSpy errorSpy(&player, SIGNAL(error(QMediaPlayer::Error)));
|
||||
|
||||
|
||||
@@ -152,16 +152,86 @@ void tst_QSoundEffect::testLooping()
|
||||
|
||||
sound->setLoopCount(5);
|
||||
sound->setVolume(0.1f);
|
||||
QCOMPARE(sound->loopCount(),5);
|
||||
QCOMPARE(readSignal_Count.count(),1);
|
||||
QCOMPARE(sound->loopCount(), 5);
|
||||
QCOMPARE(readSignal_Count.count(), 1);
|
||||
QCOMPARE(sound->loopsRemaining(), 0);
|
||||
QCOMPARE(readSignal_Remaining.count(), 0);
|
||||
|
||||
sound->play();
|
||||
QCOMPARE(sound->loopsRemaining(), 5);
|
||||
QCOMPARE(readSignal_Remaining.count(), 1);
|
||||
|
||||
// test.wav is about 200ms, wait until it has finished playing 5 times
|
||||
QTestEventLoop::instance().enterLoop(3);
|
||||
|
||||
QTRY_COMPARE(sound->loopsRemaining(), 0);
|
||||
QCOMPARE(readSignal_Remaining.count(),5);
|
||||
QVERIFY(readSignal_Remaining.count() >= 6);
|
||||
QTRY_VERIFY(!sound->isPlaying());
|
||||
|
||||
// QTBUG-36643 (setting the loop count while playing should work)
|
||||
{
|
||||
readSignal_Count.clear();
|
||||
readSignal_Remaining.clear();
|
||||
|
||||
sound->setLoopCount(30);
|
||||
QCOMPARE(sound->loopCount(), 30);
|
||||
QCOMPARE(readSignal_Count.count(), 1);
|
||||
QCOMPARE(sound->loopsRemaining(), 0);
|
||||
QCOMPARE(readSignal_Remaining.count(), 0);
|
||||
|
||||
sound->play();
|
||||
QCOMPARE(sound->loopsRemaining(), 30);
|
||||
QCOMPARE(readSignal_Remaining.count(), 1);
|
||||
|
||||
// wait for the sound to be played several times
|
||||
QTRY_COMPARE(sound->loopsRemaining(), 20);
|
||||
QVERIFY(readSignal_Remaining.count() >= 10);
|
||||
readSignal_Count.clear();
|
||||
readSignal_Remaining.clear();
|
||||
|
||||
// change the loop count while playing
|
||||
sound->setLoopCount(5);
|
||||
QCOMPARE(sound->loopCount(), 5);
|
||||
QCOMPARE(readSignal_Count.count(), 1);
|
||||
QCOMPARE(sound->loopsRemaining(), 5);
|
||||
QCOMPARE(readSignal_Remaining.count(), 1);
|
||||
|
||||
// wait for all the loops to be completed
|
||||
QTRY_COMPARE(sound->loopsRemaining(), 0);
|
||||
QVERIFY(readSignal_Remaining.count() >= 6);
|
||||
QTRY_VERIFY(!sound->isPlaying());
|
||||
}
|
||||
|
||||
{
|
||||
readSignal_Count.clear();
|
||||
readSignal_Remaining.clear();
|
||||
|
||||
sound->setLoopCount(QSoundEffect::Infinite);
|
||||
QCOMPARE(sound->loopCount(), int(QSoundEffect::Infinite));
|
||||
QCOMPARE(readSignal_Count.count(), 1);
|
||||
QCOMPARE(sound->loopsRemaining(), 0);
|
||||
QCOMPARE(readSignal_Remaining.count(), 0);
|
||||
|
||||
sound->play();
|
||||
QCOMPARE(sound->loopsRemaining(), int(QSoundEffect::Infinite));
|
||||
QCOMPARE(readSignal_Remaining.count(), 1);
|
||||
|
||||
QTest::qWait(1500);
|
||||
QVERIFY(sound->isPlaying());
|
||||
readSignal_Count.clear();
|
||||
readSignal_Remaining.clear();
|
||||
|
||||
// Setting the loop count to 0 should play it one last time
|
||||
sound->setLoopCount(0);
|
||||
QCOMPARE(sound->loopCount(), 1);
|
||||
QCOMPARE(readSignal_Count.count(), 1);
|
||||
QCOMPARE(sound->loopsRemaining(), 1);
|
||||
QCOMPARE(readSignal_Remaining.count(), 1);
|
||||
|
||||
QTRY_COMPARE(sound->loopsRemaining(), 0);
|
||||
QVERIFY(readSignal_Remaining.count() >= 2);
|
||||
QTRY_VERIFY(!sound->isPlaying());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QSoundEffect::testVolume()
|
||||
|
||||
@@ -7,6 +7,7 @@ SUBDIRS += \
|
||||
qaudioformat \
|
||||
qaudionamespace \
|
||||
qcamera \
|
||||
qcamerainfo \
|
||||
qcameraimagecapture \
|
||||
qmediabindableinterface \
|
||||
qmediacontainercontrol \
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#include <qcameracapturedestinationcontrol.h>
|
||||
#include <qmediaservice.h>
|
||||
#include <qcamera.h>
|
||||
#include <qcamerainfo.h>
|
||||
#include <qcameraimagecapture.h>
|
||||
#include <qvideorenderercontrol.h>
|
||||
|
||||
@@ -101,7 +102,7 @@ private slots:
|
||||
void testCaptureDestination();
|
||||
void testCaptureFormat();
|
||||
|
||||
void testConstructorWithDefaultProvider();
|
||||
void testConstructor();
|
||||
void testCaptureMode();
|
||||
void testIsCaptureModeSupported();
|
||||
void testRequestedLocks();
|
||||
@@ -330,7 +331,7 @@ void tst_QCamera::testSimpleCameraCapture()
|
||||
QCOMPARE(imageCapture.error(), QCameraImageCapture::NoError);
|
||||
QVERIFY(imageCapture.errorString().isEmpty());
|
||||
|
||||
QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int, QCameraImageCapture::Error,QString)));
|
||||
QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int,QCameraImageCapture::Error,QString)));
|
||||
imageCapture.capture(QString::fromLatin1("/dev/null"));
|
||||
QCOMPARE(errorSignal.size(), 1);
|
||||
QCOMPARE(imageCapture.error(), QCameraImageCapture::NotSupportedFeatureError);
|
||||
@@ -348,7 +349,7 @@ void tst_QCamera::testSimpleCameraLock()
|
||||
|
||||
QSignalSpy lockedSignal(&camera, SIGNAL(locked()));
|
||||
QSignalSpy lockFailedSignal(&camera, SIGNAL(lockFailed()));
|
||||
QSignalSpy lockStatusChangedSignal(&camera, SIGNAL(lockStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
|
||||
QSignalSpy lockStatusChangedSignal(&camera, SIGNAL(lockStatusChanged(QCamera::LockStatus,QCamera::LockChangeReason)));
|
||||
|
||||
camera.searchAndLock();
|
||||
QCOMPARE(camera.lockStatus(), QCamera::Locked);
|
||||
@@ -460,7 +461,7 @@ void tst_QCamera::testCameraCapture()
|
||||
QVERIFY(!imageCapture.isReadyForCapture());
|
||||
|
||||
QSignalSpy capturedSignal(&imageCapture, SIGNAL(imageCaptured(int,QImage)));
|
||||
QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int, QCameraImageCapture::Error,QString)));
|
||||
QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int,QCameraImageCapture::Error,QString)));
|
||||
|
||||
imageCapture.capture(QString::fromLatin1("/dev/null"));
|
||||
QCOMPARE(capturedSignal.size(), 0);
|
||||
@@ -941,7 +942,7 @@ void tst_QCamera::testCameraLockCancel()
|
||||
|
||||
QSignalSpy lockedSignal(&camera, SIGNAL(locked()));
|
||||
QSignalSpy lockFailedSignal(&camera, SIGNAL(lockFailed()));
|
||||
QSignalSpy lockStatusChangedSignal(&camera, SIGNAL(lockStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
|
||||
QSignalSpy lockStatusChangedSignal(&camera, SIGNAL(lockStatusChanged(QCamera::LockStatus,QCamera::LockChangeReason)));
|
||||
camera.searchAndLock();
|
||||
QCOMPARE(camera.lockStatus(), QCamera::Searching);
|
||||
QCOMPARE(lockedSignal.count(), 0);
|
||||
@@ -1141,6 +1142,8 @@ void tst_QCamera::testEnumDebug()
|
||||
qDebug() << QCamera::NoLock;
|
||||
QTest::ignoreMessage(QtDebugMsg, "QCamera::LockExposure");
|
||||
qDebug() << QCamera::LockExposure;
|
||||
QTest::ignoreMessage(QtDebugMsg, "QCamera::FrontFace ");
|
||||
qDebug() << QCamera::FrontFace;
|
||||
}
|
||||
|
||||
void tst_QCamera::testCameraControl()
|
||||
@@ -1149,13 +1152,75 @@ void tst_QCamera::testCameraControl()
|
||||
QVERIFY(m_cameraControl != NULL);
|
||||
}
|
||||
|
||||
/* Test case for constructor with default provider */
|
||||
void tst_QCamera::testConstructorWithDefaultProvider()
|
||||
void tst_QCamera::testConstructor()
|
||||
{
|
||||
QCamera *camera = new QCamera(0);
|
||||
QVERIFY(camera != NULL);
|
||||
QCOMPARE(camera->state(), QCamera::UnloadedState);
|
||||
delete camera;
|
||||
// Service doesn't implement QVideoDeviceSelectorControl
|
||||
provider->service = mockSimpleCameraService;
|
||||
|
||||
{
|
||||
QCamera camera;
|
||||
QCOMPARE(camera.availability(), QMultimedia::Available);
|
||||
QCOMPARE(camera.error(), QCamera::NoError);
|
||||
}
|
||||
|
||||
{
|
||||
// Requesting a camera at a specific position from a service which doesn't implement
|
||||
// the QVideoDeviceSelectorControl should result in loading the default camera
|
||||
QCamera camera(QCamera::FrontFace);
|
||||
QCOMPARE(camera.availability(), QMultimedia::Available);
|
||||
QCOMPARE(camera.error(), QCamera::NoError);
|
||||
}
|
||||
|
||||
// Service implements QVideoDeviceSelectorControl
|
||||
provider->service = mockCameraService;
|
||||
|
||||
{
|
||||
QCamera camera;
|
||||
QCOMPARE(camera.availability(), QMultimedia::Available);
|
||||
QCOMPARE(camera.error(), QCamera::NoError);
|
||||
QCOMPARE(mockCameraService->mockVideoDeviceSelectorControl->selectedDevice(), 1); // default is 1
|
||||
}
|
||||
|
||||
{
|
||||
QCamera camera(QCameraInfo::defaultCamera());
|
||||
QCOMPARE(camera.availability(), QMultimedia::Available);
|
||||
QCOMPARE(camera.error(), QCamera::NoError);
|
||||
QCOMPARE(mockCameraService->mockVideoDeviceSelectorControl->selectedDevice(), 1);
|
||||
QCOMPARE(QCameraInfo(camera), QCameraInfo::defaultCamera());
|
||||
}
|
||||
|
||||
{
|
||||
QCameraInfo cameraInfo = QCameraInfo::availableCameras().at(0);
|
||||
QCamera camera(cameraInfo);
|
||||
QCOMPARE(camera.availability(), QMultimedia::Available);
|
||||
QCOMPARE(camera.error(), QCamera::NoError);
|
||||
QCOMPARE(mockCameraService->mockVideoDeviceSelectorControl->selectedDevice(), 0);
|
||||
QCOMPARE(QCameraInfo(camera), cameraInfo);
|
||||
}
|
||||
|
||||
{
|
||||
// Requesting a camera at a position which is not available should result in
|
||||
// loading the default camera
|
||||
QCamera camera(QCamera::FrontFace);
|
||||
QCOMPARE(camera.availability(), QMultimedia::Available);
|
||||
QCOMPARE(camera.error(), QCamera::NoError);
|
||||
QCOMPARE(mockCameraService->mockVideoDeviceSelectorControl->selectedDevice(), 1);
|
||||
}
|
||||
|
||||
{
|
||||
QCamera camera(QCamera::BackFace);
|
||||
QCOMPARE(camera.availability(), QMultimedia::Available);
|
||||
QCOMPARE(camera.error(), QCamera::NoError);
|
||||
QCOMPARE(mockCameraService->mockVideoDeviceSelectorControl->selectedDevice(), 0);
|
||||
}
|
||||
|
||||
{
|
||||
// Should load the default camera when UnspecifiedPosition is requested
|
||||
QCamera camera(QCamera::UnspecifiedPosition);
|
||||
QCOMPARE(camera.availability(), QMultimedia::Available);
|
||||
QCOMPARE(camera.error(), QCamera::NoError);
|
||||
QCOMPARE(mockCameraService->mockVideoDeviceSelectorControl->selectedDevice(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* captureModeChanged Signal test case. */
|
||||
@@ -1257,8 +1322,8 @@ void tst_QCamera::testSearchAndLockWithLockTypes()
|
||||
/* Spy the signals */
|
||||
QSignalSpy lockedSignal(&camera, SIGNAL(locked()));
|
||||
QSignalSpy lockFailedSignal(&camera, SIGNAL(lockFailed()));
|
||||
QSignalSpy lockStatusChangedSignal(&camera, SIGNAL(lockStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
|
||||
QSignalSpy lockStatusChangedSignalWithType(&camera, SIGNAL(lockStatusChanged(QCamera::LockType,QCamera::LockStatus, QCamera::LockChangeReason)));
|
||||
QSignalSpy lockStatusChangedSignal(&camera, SIGNAL(lockStatusChanged(QCamera::LockStatus,QCamera::LockChangeReason)));
|
||||
QSignalSpy lockStatusChangedSignalWithType(&camera, SIGNAL(lockStatusChanged(QCamera::LockType,QCamera::LockStatus,QCamera::LockChangeReason)));
|
||||
|
||||
/* search and lock the camera with QCamera::LockExposure and verify if the signal is emitted correctly */
|
||||
camera.searchAndLock(QCamera::LockExposure);
|
||||
@@ -1292,8 +1357,8 @@ void tst_QCamera::testUnlockWithType()
|
||||
/* Spy the signal */
|
||||
QSignalSpy lockedSignal(&camera, SIGNAL(locked()));
|
||||
QSignalSpy lockFailedSignal(&camera, SIGNAL(lockFailed()));
|
||||
QSignalSpy lockStatusChangedSignal(&camera, SIGNAL(lockStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason)));
|
||||
QSignalSpy lockStatusChangedSignalWithType(&camera, SIGNAL(lockStatusChanged(QCamera::LockType,QCamera::LockStatus, QCamera::LockChangeReason)));
|
||||
QSignalSpy lockStatusChangedSignal(&camera, SIGNAL(lockStatusChanged(QCamera::LockStatus,QCamera::LockChangeReason)));
|
||||
QSignalSpy lockStatusChangedSignalWithType(&camera, SIGNAL(lockStatusChanged(QCamera::LockType,QCamera::LockStatus,QCamera::LockChangeReason)));
|
||||
|
||||
/* lock the camera with QCamera::LockExposure and Verify if the signal is emitted correctly */
|
||||
camera.searchAndLock(QCamera::LockExposure);
|
||||
@@ -1373,7 +1438,7 @@ void tst_QCamera::testLockStatusChangedWithTypesSignal()
|
||||
QCOMPARE(camera.lockStatus(), QCamera::Unlocked);
|
||||
|
||||
/* Spy the signal lockStatusChanged(QCamera::LockType,QCamera::LockStatus, QCamera::LockChangeReason) */
|
||||
QSignalSpy lockStatusChangedSignalWithType(&camera, SIGNAL(lockStatusChanged(QCamera::LockType,QCamera::LockStatus, QCamera::LockChangeReason)));
|
||||
QSignalSpy lockStatusChangedSignalWithType(&camera, SIGNAL(lockStatusChanged(QCamera::LockType,QCamera::LockStatus,QCamera::LockChangeReason)));
|
||||
|
||||
/* Lock the camera with type QCamera::LockExposure */
|
||||
camera.searchAndLock(QCamera::LockExposure);
|
||||
@@ -1519,7 +1584,7 @@ void tst_QCamera::testLockChangeReason()
|
||||
|
||||
QCamera camera;
|
||||
|
||||
QSignalSpy lockStatusChangedSignalWithType(&camera, SIGNAL(lockStatusChanged(QCamera::LockType,QCamera::LockStatus, QCamera::LockChangeReason)));
|
||||
QSignalSpy lockStatusChangedSignalWithType(&camera, SIGNAL(lockStatusChanged(QCamera::LockType,QCamera::LockStatus,QCamera::LockChangeReason)));
|
||||
|
||||
/* Set the lockChangeReason */
|
||||
service.mockLocksControl->setLockChangeReason(QCamera::LockAcquired);
|
||||
@@ -1530,6 +1595,7 @@ void tst_QCamera::testLockChangeReason()
|
||||
QVERIFY(LockChangeReason == QCamera::LockAcquired);
|
||||
|
||||
}
|
||||
|
||||
/* All the enums test case for QCameraControl class*/
|
||||
void tst_QCamera::testEnumsOfQCameraControl()
|
||||
{
|
||||
|
||||
10
tests/auto/unit/qcamerainfo/qcamerainfo.pro
Normal file
10
tests/auto/unit/qcamerainfo/qcamerainfo.pro
Normal file
@@ -0,0 +1,10 @@
|
||||
CONFIG += testcase
|
||||
TARGET = tst_qcamerainfo
|
||||
|
||||
QT += multimedia-private testlib
|
||||
|
||||
include (../qmultimedia_common/mock.pri)
|
||||
include (../qmultimedia_common/mockcamera.pri)
|
||||
|
||||
SOURCES += tst_qcamerainfo.cpp
|
||||
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
|
||||
217
tests/auto/unit/qcamerainfo/tst_qcamerainfo.cpp
Normal file
217
tests/auto/unit/qcamerainfo/tst_qcamerainfo.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** 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 <QtTest/QtTest>
|
||||
#include <QDebug>
|
||||
|
||||
#include <qcamera.h>
|
||||
#include <qcamerainfo.h>
|
||||
|
||||
#include "mockcameraservice.h"
|
||||
#include "mockmediaserviceprovider.h"
|
||||
|
||||
QT_USE_NAMESPACE
|
||||
|
||||
class tst_QCameraInfo: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public slots:
|
||||
void initTestCase();
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
private slots:
|
||||
void constructor();
|
||||
void defaultCamera();
|
||||
void availableCameras();
|
||||
void equality_operators();
|
||||
|
||||
private:
|
||||
MockSimpleCameraService *mockSimpleCameraService;
|
||||
MockCameraService *mockCameraService;
|
||||
MockMediaServiceProvider *provider;
|
||||
};
|
||||
|
||||
void tst_QCameraInfo::initTestCase()
|
||||
{
|
||||
}
|
||||
|
||||
void tst_QCameraInfo::init()
|
||||
{
|
||||
provider = new MockMediaServiceProvider;
|
||||
mockSimpleCameraService = new MockSimpleCameraService;
|
||||
mockCameraService = new MockCameraService;
|
||||
|
||||
provider->service = mockCameraService;
|
||||
QMediaServiceProvider::setDefaultServiceProvider(provider);
|
||||
}
|
||||
|
||||
void tst_QCameraInfo::cleanup()
|
||||
{
|
||||
delete provider;
|
||||
delete mockCameraService;
|
||||
delete mockSimpleCameraService;
|
||||
}
|
||||
|
||||
void tst_QCameraInfo::constructor()
|
||||
{
|
||||
// Service doesn't implement QVideoDeviceSelectorControl
|
||||
// QCameraInfo should not be valid in this case
|
||||
provider->service = mockSimpleCameraService;
|
||||
|
||||
{
|
||||
QCamera camera;
|
||||
QCameraInfo info(camera);
|
||||
QVERIFY(info.isNull());
|
||||
QVERIFY(info.deviceName().isEmpty());
|
||||
QVERIFY(info.description().isEmpty());
|
||||
QCOMPARE(info.position(), QCamera::UnspecifiedPosition);
|
||||
QCOMPARE(info.orientation(), 0);
|
||||
}
|
||||
|
||||
// Service implements QVideoDeviceSelectorControl
|
||||
provider->service = mockCameraService;
|
||||
|
||||
{
|
||||
// default camera
|
||||
QCamera camera;
|
||||
QCameraInfo info(camera);
|
||||
QVERIFY(!info.isNull());
|
||||
QCOMPARE(info.deviceName(), QStringLiteral("othercamera"));
|
||||
QCOMPARE(info.description(), QStringLiteral("othercamera desc"));
|
||||
QCOMPARE(info.position(), QCamera::UnspecifiedPosition);
|
||||
QCOMPARE(info.orientation(), 0);
|
||||
}
|
||||
|
||||
QCamera camera("backcamera");
|
||||
QCameraInfo info(camera);
|
||||
QVERIFY(!info.isNull());
|
||||
QCOMPARE(info.deviceName(), QStringLiteral("backcamera"));
|
||||
QCOMPARE(info.description(), QStringLiteral("backcamera desc"));
|
||||
QCOMPARE(info.position(), QCamera::BackFace);
|
||||
QCOMPARE(info.orientation(), 90);
|
||||
|
||||
QCameraInfo info2(info);
|
||||
QVERIFY(!info2.isNull());
|
||||
QCOMPARE(info2.deviceName(), QStringLiteral("backcamera"));
|
||||
QCOMPARE(info2.description(), QStringLiteral("backcamera desc"));
|
||||
QCOMPARE(info2.position(), QCamera::BackFace);
|
||||
QCOMPARE(info2.orientation(), 90);
|
||||
}
|
||||
|
||||
void tst_QCameraInfo::defaultCamera()
|
||||
{
|
||||
provider->service = mockCameraService;
|
||||
|
||||
QCameraInfo info = QCameraInfo::defaultCamera();
|
||||
|
||||
QVERIFY(!info.isNull());
|
||||
QCOMPARE(info.deviceName(), QStringLiteral("othercamera"));
|
||||
QCOMPARE(info.description(), QStringLiteral("othercamera desc"));
|
||||
QCOMPARE(info.position(), QCamera::UnspecifiedPosition);
|
||||
QCOMPARE(info.orientation(), 0);
|
||||
|
||||
QCamera camera(info);
|
||||
QCOMPARE(QCameraInfo(camera), info);
|
||||
}
|
||||
|
||||
void tst_QCameraInfo::availableCameras()
|
||||
{
|
||||
provider->service = mockCameraService;
|
||||
|
||||
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
|
||||
QCOMPARE(cameras.count(), 2);
|
||||
|
||||
QCameraInfo info = cameras.at(0);
|
||||
QVERIFY(!info.isNull());
|
||||
QCOMPARE(info.deviceName(), QStringLiteral("backcamera"));
|
||||
QCOMPARE(info.description(), QStringLiteral("backcamera desc"));
|
||||
QCOMPARE(info.position(), QCamera::BackFace);
|
||||
QCOMPARE(info.orientation(), 90);
|
||||
|
||||
info = cameras.at(1);
|
||||
QVERIFY(!info.isNull());
|
||||
QCOMPARE(info.deviceName(), QStringLiteral("othercamera"));
|
||||
QCOMPARE(info.description(), QStringLiteral("othercamera desc"));
|
||||
QCOMPARE(info.position(), QCamera::UnspecifiedPosition);
|
||||
QCOMPARE(info.orientation(), 0);
|
||||
|
||||
cameras = QCameraInfo::availableCameras(QCamera::BackFace);
|
||||
QCOMPARE(cameras.count(), 1);
|
||||
info = cameras.at(0);
|
||||
QVERIFY(!info.isNull());
|
||||
QCOMPARE(info.deviceName(), QStringLiteral("backcamera"));
|
||||
QCOMPARE(info.description(), QStringLiteral("backcamera desc"));
|
||||
QCOMPARE(info.position(), QCamera::BackFace);
|
||||
QCOMPARE(info.orientation(), 90);
|
||||
|
||||
cameras = QCameraInfo::availableCameras(QCamera::FrontFace);
|
||||
QCOMPARE(cameras.count(), 0);
|
||||
}
|
||||
|
||||
void tst_QCameraInfo::equality_operators()
|
||||
{
|
||||
provider->service = mockCameraService;
|
||||
|
||||
QCameraInfo defaultCamera = QCameraInfo::defaultCamera();
|
||||
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
|
||||
|
||||
QVERIFY(defaultCamera == cameras.at(1));
|
||||
QVERIFY(defaultCamera != cameras.at(0));
|
||||
QVERIFY(cameras.at(0) != cameras.at(1));
|
||||
|
||||
{
|
||||
QCamera camera(defaultCamera);
|
||||
QVERIFY(QCameraInfo(camera) == defaultCamera);
|
||||
QVERIFY(QCameraInfo(camera) == cameras.at(1));
|
||||
}
|
||||
|
||||
{
|
||||
QCamera camera(cameras.at(0));
|
||||
QVERIFY(QCameraInfo(camera) == cameras.at(0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QTEST_MAIN(tst_QCameraInfo)
|
||||
|
||||
#include "tst_qcamerainfo.moc"
|
||||
@@ -380,7 +380,7 @@ void tst_QMediaObject::metaDataChanged()
|
||||
QtTestMediaObject object(&service);
|
||||
|
||||
QSignalSpy changedSpy(&object, SIGNAL(metaDataChanged()));
|
||||
QSignalSpy changedWithValueSpy(&object, SIGNAL(metaDataChanged(QString, QVariant)));
|
||||
QSignalSpy changedWithValueSpy(&object, SIGNAL(metaDataChanged(QString,QVariant)));
|
||||
|
||||
service.metaData.setMetaData("key", "Value");
|
||||
QCOMPARE(changedSpy.count(), 1);
|
||||
|
||||
@@ -44,12 +44,10 @@
|
||||
#include "../mockservice.h"
|
||||
|
||||
class MockServicePlugin1 : public QMediaServiceProviderPlugin,
|
||||
public QMediaServiceSupportedFormatsInterface,
|
||||
public QMediaServiceSupportedDevicesInterface
|
||||
public QMediaServiceSupportedFormatsInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QMediaServiceSupportedFormatsInterface)
|
||||
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "mockserviceplugin1.json")
|
||||
public:
|
||||
QStringList keys() const
|
||||
@@ -87,21 +85,6 @@ public:
|
||||
{
|
||||
return QStringList("audio/ogg");
|
||||
}
|
||||
|
||||
QList<QByteArray> devices(const QByteArray &service) const
|
||||
{
|
||||
Q_UNUSED(service);
|
||||
QList<QByteArray> res;
|
||||
return res;
|
||||
}
|
||||
|
||||
QString deviceDescription(const QByteArray &service, const QByteArray &device)
|
||||
{
|
||||
if (devices(service).contains(device))
|
||||
return QString(device)+" description";
|
||||
else
|
||||
return QString();
|
||||
}
|
||||
};
|
||||
|
||||
#include "mockserviceplugin1.moc"
|
||||
|
||||
@@ -44,17 +44,22 @@
|
||||
#include "../mockservice.h"
|
||||
|
||||
class MockServicePlugin3 : public QMediaServiceProviderPlugin,
|
||||
public QMediaServiceSupportedDevicesInterface
|
||||
public QMediaServiceSupportedDevicesInterface,
|
||||
public QMediaServiceDefaultDeviceInterface,
|
||||
public QMediaServiceCameraInfoInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
|
||||
Q_INTERFACES(QMediaServiceDefaultDeviceInterface)
|
||||
Q_INTERFACES(QMediaServiceCameraInfoInterface)
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "mockserviceplugin3.json")
|
||||
public:
|
||||
QStringList keys() const
|
||||
{
|
||||
return QStringList() <<
|
||||
QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER) <<
|
||||
QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE);
|
||||
QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE) <<
|
||||
QLatin1String(Q_MEDIASERVICE_CAMERA);
|
||||
}
|
||||
|
||||
QMediaService* create(QString const& key)
|
||||
@@ -70,12 +75,26 @@ public:
|
||||
delete service;
|
||||
}
|
||||
|
||||
QByteArray defaultDevice(const QByteArray &service) const
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_AUDIOSOURCE)
|
||||
return "audiosource1";
|
||||
|
||||
if (service == Q_MEDIASERVICE_CAMERA)
|
||||
return "frontcamera";
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QList<QByteArray> devices(const QByteArray &service) const
|
||||
{
|
||||
QList<QByteArray> res;
|
||||
if (service == QByteArray(Q_MEDIASERVICE_AUDIOSOURCE))
|
||||
if (service == Q_MEDIASERVICE_AUDIOSOURCE)
|
||||
res << "audiosource1" << "audiosource2";
|
||||
|
||||
if (service == Q_MEDIASERVICE_CAMERA)
|
||||
res << "frontcamera";
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -86,6 +105,22 @@ public:
|
||||
else
|
||||
return QString();
|
||||
}
|
||||
|
||||
QCamera::Position cameraPosition(const QByteArray &device) const
|
||||
{
|
||||
if (device == "frontcamera")
|
||||
return QCamera::FrontFace;
|
||||
|
||||
return QCamera::UnspecifiedPosition;
|
||||
}
|
||||
|
||||
int cameraOrientation(const QByteArray &device) const
|
||||
{
|
||||
if (device == "frontcamera")
|
||||
return 270;
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#include "mockserviceplugin3.moc"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"Keys": ["mockserviceplugin3"],
|
||||
"Services": ["org.qt-project.qt.mediaplayer", "org.qt-project.qt.audiosource"]
|
||||
"Services": ["org.qt-project.qt.mediaplayer", "org.qt-project.qt.audiosource", "org.qt-project.qt.camera"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** 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 <qmediaserviceproviderplugin.h>
|
||||
#include <qmediaservice.h>
|
||||
#include "../mockservice.h"
|
||||
|
||||
class MockServicePlugin5 : public QMediaServiceProviderPlugin,
|
||||
public QMediaServiceSupportedDevicesInterface,
|
||||
public QMediaServiceDefaultDeviceInterface,
|
||||
public QMediaServiceCameraInfoInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
|
||||
Q_INTERFACES(QMediaServiceDefaultDeviceInterface)
|
||||
Q_INTERFACES(QMediaServiceCameraInfoInterface)
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "mockserviceplugin5.json")
|
||||
public:
|
||||
QStringList keys() const
|
||||
{
|
||||
return QStringList() << QLatin1String(Q_MEDIASERVICE_CAMERA);
|
||||
}
|
||||
|
||||
QMediaService* create(QString const& key)
|
||||
{
|
||||
if (keys().contains(key))
|
||||
return new MockMediaService("MockServicePlugin5");
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void release(QMediaService *service)
|
||||
{
|
||||
delete service;
|
||||
}
|
||||
|
||||
QByteArray defaultDevice(const QByteArray &service) const
|
||||
{
|
||||
if (service == Q_MEDIASERVICE_CAMERA)
|
||||
return "backcamera";
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QList<QByteArray> devices(const QByteArray &service) const
|
||||
{
|
||||
QList<QByteArray> res;
|
||||
if (service == Q_MEDIASERVICE_CAMERA)
|
||||
res << "backcamera" << "somecamera";
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
QString deviceDescription(const QByteArray &service, const QByteArray &device)
|
||||
{
|
||||
if (devices(service).contains(device))
|
||||
return QString(device)+" description";
|
||||
else
|
||||
return QString();
|
||||
}
|
||||
|
||||
QCamera::Position cameraPosition(const QByteArray &device) const
|
||||
{
|
||||
if (device == "backcamera")
|
||||
return QCamera::BackFace;
|
||||
|
||||
return QCamera::UnspecifiedPosition;
|
||||
}
|
||||
|
||||
int cameraOrientation(const QByteArray &device) const
|
||||
{
|
||||
if (device == "backcamera")
|
||||
return 90;
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#include "mockserviceplugin5.moc"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"Keys": ["mockserviceplugin5"],
|
||||
"Services": ["org.qt-project.qt.camera"]
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user