Initial implementation of Mac camera backend

Based on AVFoundation framework

Change-Id: If4cfd105a592f50b42606624548b9ffc870e3e47
Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
This commit is contained in:
Dmytro Poplavskiy
2012-08-17 13:44:14 +10:00
committed by Qt by Nokia
parent 09a7fda971
commit 37b872da9e
27 changed files with 3009 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
TEMPLATE = subdirs
SUBDIRS += camera

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AVFAUDIOINPUTSELECTORCONTROL_H
#define AVFAUDIOINPUTSELECTORCONTROL_H
#include <QtMultimedia/qaudioinputselectorcontrol.h>
#include <QtCore/qstringlist.h>
#import <AVFoundation/AVFoundation.h>
QT_BEGIN_NAMESPACE
class AVFCameraSession;
class AVFCameraService;
class AVFAudioInputSelectorControl : public QAudioInputSelectorControl
{
Q_OBJECT
public:
AVFAudioInputSelectorControl(AVFCameraService *service, QObject *parent = 0);
~AVFAudioInputSelectorControl();
QList<QString> availableInputs() const;
QString inputDescription(const QString &name) const;
QString defaultInput() const;
QString activeInput() const;
public Q_SLOTS:
void setActiveInput(const QString &name);
public:
//device changed since the last createCaptureDevice()
bool isDirty() const { return m_dirty; }
AVCaptureDevice *createCaptureDevice();
private:
AVFCameraService *m_service;
QString m_activeInput;
bool m_dirty;
QStringList m_devices;
QMap<QString, QString> m_deviceDescriptions;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,117 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "avfcameradebug.h"
#include "avfaudioinputselectorcontrol.h"
#include "avfcameraservice.h"
#import <AVFoundation/AVFoundation.h>
QT_USE_NAMESPACE
AVFAudioInputSelectorControl::AVFAudioInputSelectorControl(AVFCameraService *service, QObject *parent)
: QAudioInputSelectorControl(parent)
, m_service(service)
, m_dirty(true)
{
NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
for (AVCaptureDevice *device in videoDevices) {
QString deviceId = QString::fromUtf8([[device uniqueID] UTF8String]);
m_devices << deviceId;
m_deviceDescriptions.insert(deviceId,
QString::fromUtf8([[device localizedName] UTF8String]));
}
m_activeInput = m_devices.first();
}
AVFAudioInputSelectorControl::~AVFAudioInputSelectorControl()
{
}
QList<QString> AVFAudioInputSelectorControl::availableInputs() const
{
return m_devices;
}
QString AVFAudioInputSelectorControl::inputDescription(const QString &name) const
{
return m_deviceDescriptions.value(name);
}
QString AVFAudioInputSelectorControl::defaultInput() const
{
return m_devices.first();
}
QString AVFAudioInputSelectorControl::activeInput() const
{
return m_activeInput;
}
void AVFAudioInputSelectorControl::setActiveInput(const QString &name)
{
if (name != m_activeInput) {
m_activeInput = name;
m_dirty = true;
Q_EMIT activeInputChanged(m_activeInput);
}
}
AVCaptureDevice *AVFAudioInputSelectorControl::createCaptureDevice()
{
m_dirty = false;
AVCaptureDevice *device = 0;
if (!m_activeInput.isEmpty()) {
device = [AVCaptureDevice deviceWithUniqueID:
[NSString stringWithUTF8String:
m_activeInput.toUtf8().constData()]];
}
if (!device)
device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
return device;
}
#include "moc_avfaudioinputselectorcontrol.cpp"

View File

@@ -0,0 +1,3 @@
{
"Keys": ["org.qt-project.qt.camera"]
}

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AVFCAMERACONTROL_H
#define AVFCAMERACONTROL_H
#include <QtCore/qobject.h>
#include <QtMultimedia/qcameracontrol.h>
QT_BEGIN_NAMESPACE
class AVFCameraSession;
class AVFCameraService;
class AVFCameraControl : public QCameraControl
{
Q_OBJECT
public:
AVFCameraControl(AVFCameraService *service, QObject *parent = 0);
~AVFCameraControl();
QCamera::State state() const;
void setState(QCamera::State state);
QCamera::Status status() const;
QCamera::CaptureModes captureMode() const;
void setCaptureMode(QCamera::CaptureModes);
bool isCaptureModeSupported(QCamera::CaptureModes mode) const;
bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const;
private Q_SLOTS:
void updateStatus();
private:
AVFCameraService *m_service;
AVFCameraSession *m_session;
QCamera::State m_state;
QCamera::Status m_lastStatus;
QCamera::CaptureModes m_captureMode;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,135 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "avfcameradebug.h"
#include "avfcameracontrol.h"
#include "avfcamerasession.h"
#include "avfcameraservice.h"
QT_USE_NAMESPACE
AVFCameraControl::AVFCameraControl(AVFCameraService *service, QObject *parent)
: QCameraControl(parent)
, m_service(service)
, m_session(service->session())
, m_state(QCamera::UnloadedState)
, m_lastStatus(QCamera::UnloadedStatus)
, m_captureMode(QCamera::CaptureStillImage)
{
connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateStatus()));
}
AVFCameraControl::~AVFCameraControl()
{
}
QCamera::State AVFCameraControl::state() const
{
return m_state;
}
void AVFCameraControl::setState(QCamera::State state)
{
if (m_state == state)
return;
m_state = state;
m_session->setState(state);
Q_EMIT stateChanged(m_state);
updateStatus();
}
QCamera::Status AVFCameraControl::status() const
{
static QCamera::Status statusTable[3][3] = {
{ QCamera::UnloadedStatus, QCamera::UnloadingStatus, QCamera::StoppingStatus }, //Unloaded state
{ QCamera::LoadingStatus, QCamera::LoadedStatus, QCamera::StoppingStatus }, //Loaded state
{ QCamera::LoadingStatus, QCamera::StartingStatus, QCamera::ActiveStatus } //ActiveState
};
return statusTable[m_state][m_session->state()];
}
void AVFCameraControl::updateStatus()
{
QCamera::Status newStatus = status();
if (m_lastStatus != newStatus) {
qDebugCamera() << "Camera status changed: " << m_lastStatus << " -> " << newStatus;
m_lastStatus = newStatus;
Q_EMIT statusChanged(m_lastStatus);
}
}
QCamera::CaptureModes AVFCameraControl::captureMode() const
{
return m_captureMode;
}
void AVFCameraControl::setCaptureMode(QCamera::CaptureModes mode)
{
if (m_captureMode == mode)
return;
if (!isCaptureModeSupported(mode)) {
Q_EMIT error(QCamera::NotSupportedFeatureError, tr("Requested capture mode is not supported"));
return;
}
m_captureMode = mode;
Q_EMIT captureModeChanged(mode);
}
bool AVFCameraControl::isCaptureModeSupported(QCamera::CaptureModes mode) const
{
//all the capture modes are supported, including QCamera::CaptureStillImage | QCamera::CaptureVideo
return (mode & (QCamera::CaptureStillImage | QCamera::CaptureVideo)) == mode;
}
bool AVFCameraControl::canChangeProperty(QCameraControl::PropertyChangeType changeType, QCamera::Status status) const
{
Q_UNUSED(changeType);
Q_UNUSED(status);
return true;
}
#include "moc_avfcameracontrol.cpp"

View File

@@ -0,0 +1,59 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AVFDEBUG_H
#define AVFDEBUG_H
#include "qtmultimediadefs.h"
#include <QtCore/qdebug.h>
QT_USE_NAMESPACE
//#define AVF_DEBUG_CAMERA
#ifdef AVF_DEBUG_CAMERA
#define qDebugCamera qDebug
#else
#define qDebugCamera QT_NO_QDEBUG_MACRO
#endif
#endif

View File

@@ -0,0 +1,72 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AVFCAMERAMETADATACONTROL_H
#define AVFCAMERAMETADATACONTROL_H
#include <qmetadatawritercontrol.h>
QT_BEGIN_NAMESPACE
class AVFCameraService;
class AVFCameraMetaDataControl : public QMetaDataWriterControl
{
Q_OBJECT
public:
AVFCameraMetaDataControl(AVFCameraService *service, QObject *parent=0);
virtual ~AVFCameraMetaDataControl();
bool isMetaDataAvailable() const;
bool isWritable() const;
QVariant metaData(const QString &key) const;
void setMetaData(const QString &key, const QVariant &value);
QStringList availableMetaData() const;
private:
AVFCameraService *m_service;
QMap<QString, QVariant> m_tags;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,84 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "avfcamerametadatacontrol.h"
#include "avfcamerasession.h"
#include "avfcameraservice.h"
QT_USE_NAMESPACE
//metadata support is not implemented yet
AVFCameraMetaDataControl::AVFCameraMetaDataControl(AVFCameraService *service, QObject *parent)
:QMetaDataWriterControl(parent), m_service(service)
{
}
AVFCameraMetaDataControl::~AVFCameraMetaDataControl()
{
}
bool AVFCameraMetaDataControl::isMetaDataAvailable() const
{
return !m_tags.isEmpty();
}
bool AVFCameraMetaDataControl::isWritable() const
{
return false;
}
QVariant AVFCameraMetaDataControl::metaData(const QString &key) const
{
return m_tags.value(key);
}
void AVFCameraMetaDataControl::setMetaData(const QString &key, const QVariant &value)
{
m_tags.insert(key, value);
}
QStringList AVFCameraMetaDataControl::availableMetaData() const
{
return m_tags.keys();
}
#include "moc_avfcamerametadatacontrol.cpp"

View File

@@ -0,0 +1,95 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AVFCAMERASERVICE_H
#define AVFCAMERASERVICE_H
#include <QtCore/qobject.h>
#include <QtCore/qset.h>
#include <qmediaservice.h>
QT_BEGIN_NAMESPACE
class QCameraControl;
class AVFCameraControl;
class AVFCameraMetaDataControl;
class AVFVideoWindowControl;
class AVFVideoWidgetControl;
class AVFVideoRendererControl;
class AVFMediaRecorderControl;
class AVFImageCaptureControl;
class AVFCameraSession;
class AVFVideoDeviceControl;
class AVFAudioInputSelectorControl;
class AVFCameraService : public QMediaService
{
Q_OBJECT
public:
AVFCameraService(QObject *parent = 0);
~AVFCameraService();
QMediaControl* requestControl(const char *name);
void releaseControl(QMediaControl *control);
AVFCameraSession *session() const { return m_session; }
AVFCameraControl *cameraControl() const { return m_cameraControl; }
AVFVideoDeviceControl *videoDeviceControl() const { return m_videoDeviceControl; }
AVFAudioInputSelectorControl *audioInputSelectorControl() const { return m_audioInputSelectorControl; }
AVFCameraMetaDataControl *metaDataControl() const { return m_metaDataControl; }
AVFMediaRecorderControl *recorderControl() const { return m_recorderControl; }
AVFImageCaptureControl *imageCaptureControl() const { return m_imageCaptureControl; }
private:
AVFCameraSession *m_session;
AVFCameraControl *m_cameraControl;
AVFVideoDeviceControl *m_videoDeviceControl;
AVFAudioInputSelectorControl *m_audioInputSelectorControl;
AVFVideoRendererControl *m_videoOutput;
AVFCameraMetaDataControl *m_metaDataControl;
AVFMediaRecorderControl *m_recorderControl;
AVFImageCaptureControl *m_imageCaptureControl;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,139 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qvariant.h>
#include <QtCore/qdebug.h>
#include "avfcameraservice.h"
#include "avfcameracontrol.h"
#include "avfcamerasession.h"
#include "avfvideodevicecontrol.h"
#include "avfaudioinputselectorcontrol.h"
#include "avfcamerametadatacontrol.h"
#include "avfmediarecordercontrol.h"
#include "avfimagecapturecontrol.h"
#include "avfvideorenderercontrol.h"
#include "avfmediarecordercontrol.h"
#include "avfimagecapturecontrol.h"
#include <private/qmediaplaylistnavigator_p.h>
#include <qmediaplaylist.h>
QT_USE_NAMESPACE
AVFCameraService::AVFCameraService(QObject *parent):
QMediaService(parent),
m_videoOutput(0)
{
m_session = new AVFCameraSession(this);
m_cameraControl = new AVFCameraControl(this);
m_videoDeviceControl = new AVFVideoDeviceControl(this);
m_audioInputSelectorControl = new AVFAudioInputSelectorControl(this);
m_metaDataControl = new AVFCameraMetaDataControl(this);
m_recorderControl = new AVFMediaRecorderControl(this);
m_imageCaptureControl = new AVFImageCaptureControl(this);
}
AVFCameraService::~AVFCameraService()
{
m_cameraControl->setState(QCamera::UnloadedState);
if (m_videoOutput) {
m_session->setVideoOutput(0);
delete m_videoOutput;
m_videoOutput = 0;
}
//delete controls before session,
//so they have a chance to do deinitialization
delete m_imageCaptureControl;
//delete m_recorderControl;
delete m_metaDataControl;
delete m_cameraControl;
delete m_session;
}
QMediaControl *AVFCameraService::requestControl(const char *name)
{
if (qstrcmp(name, QCameraControl_iid) == 0)
return m_cameraControl;
if (qstrcmp(name, QVideoDeviceSelectorControl_iid) == 0)
return m_videoDeviceControl;
if (qstrcmp(name, QAudioInputSelectorControl_iid) == 0)
return m_audioInputSelectorControl;
//metadata support is not implemented yet
//if (qstrcmp(name, QMetaDataWriterControl_iid) == 0)
// return m_metaDataControl;
if (qstrcmp(name, QMediaRecorderControl_iid) == 0)
return m_recorderControl;
if (qstrcmp(name, QCameraImageCaptureControl_iid) == 0)
return m_imageCaptureControl;
if (!m_videoOutput) {
if (qstrcmp(name, QVideoRendererControl_iid) == 0)
m_videoOutput = new AVFVideoRendererControl(this);
if (m_videoOutput) {
m_session->setVideoOutput(m_videoOutput);
return m_videoOutput;
}
}
return 0;
}
void AVFCameraService::releaseControl(QMediaControl *control)
{
if (m_videoOutput == control) {
m_videoOutput = 0;
m_session->setVideoOutput(0);
delete control;
}
}
#include "moc_avfcameraservice.cpp"

View File

@@ -0,0 +1,76 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AVFSERVICEPLUGIN_H
#define AVFSERVICEPLUGIN_H
#include <qmediaserviceproviderplugin.h>
#include <QtCore/qmap.h>
QT_BEGIN_NAMESPACE
class AVFServicePlugin : public QMediaServiceProviderPlugin,
public QMediaServiceSupportedDevicesInterface
{
Q_OBJECT
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "avfcamera.json")
public:
AVFServicePlugin();
QMediaService* create(QString const& key);
void release(QMediaService *service);
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;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,112 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qstring.h>
#include <QtCore/qdebug.h>
#include "avfcameraserviceplugin.h"
#include "avfcameraservice.h"
#include <qmediaserviceproviderplugin.h>
#import <AVFoundation/AVFoundation.h>
QT_BEGIN_NAMESPACE
AVFServicePlugin::AVFServicePlugin()
{
}
QMediaService* AVFServicePlugin::create(QString const& key)
{
if (key == QLatin1String(Q_MEDIASERVICE_CAMERA))
return new AVFCameraService;
else
qWarning() << "unsupported key:" << key;
return 0;
}
void AVFServicePlugin::release(QMediaService *service)
{
delete service;
}
QList<QByteArray> AVFServicePlugin::devices(const QByteArray &service) const
{
if (service == Q_MEDIASERVICE_CAMERA) {
if (m_cameraDevices.isEmpty())
updateDevices();
return m_cameraDevices;
}
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);
}
return QString();
}
void AVFServicePlugin::updateDevices() const
{
m_cameraDevices.clear();
m_cameraDescriptions.clear();
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]));
}
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,101 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AVFCAMERASESSION_H
#define AVFCAMERASESSION_H
#include <QtCore/qmutex.h>
#include <QtMultimedia/qcamera.h>
#import <AVFoundation/AVFoundation.h>
QT_BEGIN_NAMESPACE
class AVFCameraControl;
class AVFCameraService;
class AVFVideoRendererControl;
@class AVFCameraSessionObserver;
class AVFCameraSession : public QObject
{
Q_OBJECT
public:
AVFCameraSession(AVFCameraService *service, QObject *parent = 0);
~AVFCameraSession();
void setVideoOutput(AVFVideoRendererControl *output);
AVCaptureSession *captureSession() const { return m_captureSession; }
QCamera::State state() const;
QCamera::State requestedState() const { return m_state; }
bool isActive() const { return m_active; }
public Q_SLOTS:
void setState(QCamera::State state);
void processRuntimeError();
void processSessionStarted();
void processSessionStopped();
Q_SIGNALS:
void readyToConfigureConnections();
void stateChanged(QCamera::State newState);
void activeChanged(bool);
void error(int error, const QString &errorString);
private:
void attachInputDevices();
AVFCameraService *m_service;
AVFVideoRendererControl *m_videoOutput;
QCamera::State m_state;
bool m_active;
AVCaptureSession *m_captureSession;
AVCaptureDeviceInput *m_videoInput;
AVCaptureDeviceInput *m_audioInput;
AVFCameraSessionObserver *m_observer;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,277 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "avfcameradebug.h"
#include "avfcamerasession.h"
#include "avfcameraservice.h"
#include "avfcameracontrol.h"
#include "avfvideorenderercontrol.h"
#include "avfvideodevicecontrol.h"
#include "avfaudioinputselectorcontrol.h"
#include <CoreFoundation/CoreFoundation.h>
#include <Foundation/Foundation.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qurl.h>
#include <QtCore/qdebug.h>
QT_USE_NAMESPACE
@interface AVFCameraSessionObserver : NSObject
{
@private
AVFCameraSession *m_session;
AVCaptureSession *m_captureSession;
}
- (AVFCameraSessionObserver *) initWithCameraSession:(AVFCameraSession*)session;
- (void) processRuntimeError:(NSNotification *)notification;
- (void) processSessionStarted:(NSNotification *)notification;
- (void) processSessionStopped:(NSNotification *)notification;
@end
@implementation AVFCameraSessionObserver
- (AVFCameraSessionObserver *) initWithCameraSession:(AVFCameraSession*)session
{
if (!(self = [super init]))
return nil;
self->m_session = session;
self->m_captureSession = session->captureSession();
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(processRuntimeError:)
name:AVCaptureSessionRuntimeErrorNotification
object:m_captureSession];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(processSessionStarted:)
name:AVCaptureSessionDidStartRunningNotification
object:m_captureSession];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(processSessionStopped:)
name:AVCaptureSessionDidStopRunningNotification
object:m_captureSession];
return self;
}
- (void) processRuntimeError:(NSNotification *)notification
{
Q_UNUSED(notification);
QMetaObject::invokeMethod(m_session, "processRuntimeError", Qt::AutoConnection);
}
- (void) processSessionStarted:(NSNotification *)notification
{
Q_UNUSED(notification);
QMetaObject::invokeMethod(m_session, "processSessionStarted", Qt::AutoConnection);
}
- (void) processSessionStopped:(NSNotification *)notification
{
Q_UNUSED(notification);
QMetaObject::invokeMethod(m_session, "processSessionStopped", Qt::AutoConnection);
}
@end
AVFCameraSession::AVFCameraSession(AVFCameraService *service, QObject *parent)
: QObject(parent)
, m_service(service)
, m_state(QCamera::UnloadedState)
, m_active(false)
, m_videoInput(nil)
, m_audioInput(nil)
{
m_captureSession = [[AVCaptureSession alloc] init];
m_observer = [[AVFCameraSessionObserver alloc] initWithCameraSession:this];
//configuration is commited during transition to Active state
[m_captureSession beginConfiguration];
}
AVFCameraSession::~AVFCameraSession()
{
if (m_videoInput) {
[m_captureSession removeInput:m_videoInput];
[m_videoInput release];
}
if (m_audioInput) {
[m_captureSession removeInput:m_audioInput];
[m_audioInput release];
}
[m_observer release];
[m_captureSession release];
}
void AVFCameraSession::setVideoOutput(AVFVideoRendererControl *output)
{
m_videoOutput = output;
if (output)
output->configureAVCaptureSession(m_captureSession);
}
QCamera::State AVFCameraSession::state() const
{
if (m_active)
return QCamera::ActiveState;
return m_state == QCamera::ActiveState ? QCamera::LoadedState : m_state;
}
void AVFCameraSession::setState(QCamera::State newState)
{
if (m_state == newState)
return;
qDebugCamera() << Q_FUNC_INFO << m_state << " -> " << newState;
QCamera::State oldState = m_state;
m_state = newState;
//attach audio and video inputs during Unloaded->Loaded transition
if (oldState == QCamera::UnloadedState) {
attachInputDevices();
}
if (m_state == QCamera::ActiveState) {
Q_EMIT readyToConfigureConnections();
[m_captureSession commitConfiguration];
[m_captureSession startRunning];
}
if (oldState == QCamera::ActiveState) {
[m_captureSession stopRunning];
[m_captureSession beginConfiguration];
}
Q_EMIT stateChanged(m_state);
}
void AVFCameraSession::processRuntimeError()
{
qWarning() << tr("Runtime camera error");
Q_EMIT error(QCamera::CameraError, tr("Runtime camera error"));
}
void AVFCameraSession::processSessionStarted()
{
qDebugCamera() << Q_FUNC_INFO;
if (!m_active) {
m_active = true;
Q_EMIT activeChanged(m_active);
Q_EMIT stateChanged(state());
}
}
void AVFCameraSession::processSessionStopped()
{
qDebugCamera() << Q_FUNC_INFO;
if (m_active) {
m_active = false;
Q_EMIT activeChanged(m_active);
Q_EMIT stateChanged(state());
}
}
void AVFCameraSession::attachInputDevices()
{
//Attach video input device:
if (m_service->videoDeviceControl()->isDirty()) {
if (m_videoInput) {
[m_captureSession removeInput:m_videoInput];
[m_videoInput release];
m_videoInput = 0;
}
AVCaptureDevice *videoDevice = m_service->videoDeviceControl()->createCaptureDevice();
NSError *error = nil;
m_videoInput = [AVCaptureDeviceInput
deviceInputWithDevice:videoDevice
error:&error];
if (!m_videoInput) {
qWarning() << "Failed to create video device input";
} else {
if ([m_captureSession canAddInput:m_videoInput]) {
[m_videoInput retain];
[m_captureSession addInput:m_videoInput];
} else {
qWarning() << "Failed to connect video device input";
}
}
}
//Attach audio input device:
if (m_service->audioInputSelectorControl()->isDirty()) {
if (m_audioInput) {
[m_captureSession removeInput:m_audioInput];
[m_audioInput release];
m_audioInput = 0;
}
AVCaptureDevice *audioDevice = m_service->audioInputSelectorControl()->createCaptureDevice();
NSError *error = nil;
m_audioInput = [AVCaptureDeviceInput
deviceInputWithDevice:audioDevice
error:&error];
if (!m_audioInput) {
qWarning() << "Failed to create audio device input";
} else {
[m_audioInput retain];
[m_captureSession addInput:m_audioInput];
}
}
}
#include "moc_avfcamerasession.cpp"

View File

@@ -0,0 +1,88 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AVFIMAGECAPTURECONTROL_H
#define AVFIMAGECAPTURECONTROL_H
#import <AVFoundation/AVFoundation.h>
#include <QtMultimedia/qcameraimagecapturecontrol.h>
#include "avfstoragelocation.h"
QT_BEGIN_NAMESPACE
class AVFCameraSession;
class AVFCameraService;
class AVFCameraControl;
class AVFImageCaptureControl : public QCameraImageCaptureControl
{
Q_OBJECT
public:
AVFImageCaptureControl(AVFCameraService *service, QObject *parent = 0);
~AVFImageCaptureControl();
bool isReadyForCapture() const;
QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; }
void setDriveMode(QCameraImageCapture::DriveMode ) {}
int capture(const QString &fileName);
void cancelCapture();
private Q_SLOTS:
void updateCaptureConnection();
void updateReadyStatus();
private:
AVFCameraService *m_service;
AVFCameraSession *m_session;
AVFCameraControl *m_cameraControl;
bool m_ready;
int m_lastCaptureId;
AVCaptureStillImageOutput *m_stillImageOutput;
AVCaptureConnection *m_videoConnection;
AVFStorageLocation m_storageLocation;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,222 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "avfcameradebug.h"
#include "avfimagecapturecontrol.h"
#include "avfcamerasession.h"
#include "avfcameraservice.h"
#include "avfcameracontrol.h"
#include <QtCore/qurl.h>
#include <QtCore/qfile.h>
#include <QtCore/qbuffer.h>
#include <QtGui/qimagereader.h>
QT_USE_NAMESPACE
AVFImageCaptureControl::AVFImageCaptureControl(AVFCameraService *service, QObject *parent)
: QCameraImageCaptureControl(parent)
, m_service(service)
, m_session(service->session())
, m_cameraControl(service->cameraControl())
, m_ready(false)
, m_lastCaptureId(0)
, m_videoConnection(nil)
{
m_stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:
AVVideoCodecJPEG, AVVideoCodecKey, nil];
[m_stillImageOutput setOutputSettings:outputSettings];
[outputSettings release];
connect(m_cameraControl, SIGNAL(captureModeChanged(QCamera::CaptureModes)), SLOT(updateReadyStatus()));
connect(m_cameraControl, SIGNAL(statusChanged(QCamera::Status)), SLOT(updateReadyStatus()));
connect(m_session, SIGNAL(readyToConfigureConnections()), SLOT(updateCaptureConnection()));
}
AVFImageCaptureControl::~AVFImageCaptureControl()
{
}
bool AVFImageCaptureControl::isReadyForCapture() const
{
return m_videoConnection &&
m_cameraControl->captureMode().testFlag(QCamera::CaptureStillImage) &&
m_cameraControl->status() == QCamera::ActiveStatus;
}
void AVFImageCaptureControl::updateReadyStatus()
{
if (m_ready != isReadyForCapture()) {
m_ready = !m_ready;
qDebugCamera() << "ReadyToCapture status changed:" << m_ready;
Q_EMIT readyForCaptureChanged(m_ready);
}
}
int AVFImageCaptureControl::capture(const QString &fileName)
{
m_lastCaptureId++;
if (!isReadyForCapture()) {
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(int, m_lastCaptureId),
Q_ARG(int, QCameraImageCapture::NotReadyError),
Q_ARG(QString, tr("Camera not ready")));
return m_lastCaptureId;
}
QString actualFileName = m_storageLocation.generateFileName(fileName,
QCamera::CaptureStillImage,
QLatin1String("img_"),
QLatin1String("jpg"));
qDebugCamera() << "Capture image to" << actualFileName;
int captureId = m_lastCaptureId;
[m_stillImageOutput captureStillImageAsynchronouslyFromConnection:m_videoConnection
completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
if (error) {
QStringList messageParts;
messageParts << QString::fromUtf8([[error localizedDescription] UTF8String]);
messageParts << QString::fromUtf8([[error localizedFailureReason] UTF8String]);
messageParts << QString::fromUtf8([[error localizedRecoverySuggestion] UTF8String]);
QString errorMessage = messageParts.join(" ");
qDebugCamera() << "Image capture failed:" << errorMessage;
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(int, captureId),
Q_ARG(int, QCameraImageCapture::ResourceError),
Q_ARG(QString, errorMessage));
} else {
qDebugCamera() << "Image captured:" << actualFileName;
//we can't find the exact time the image is exposed,
//but image capture is very fast on desktop, so emit it here
QMetaObject::invokeMethod(this, "imageExposed", Qt::QueuedConnection,
Q_ARG(int, captureId));
NSData *nsJpgData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
QByteArray jpgData = QByteArray::fromRawData((const char *)[nsJpgData bytes], [nsJpgData length]);
//Generate snap preview as downscalled image
{
QBuffer buffer(&jpgData);
QImageReader imageReader(&buffer);
QSize imgSize = imageReader.size();
int downScaleSteps = 0;
while (imgSize.width() > 800 && downScaleSteps < 8) {
imgSize.rwidth() /= 2;
imgSize.rheight() /= 2;
downScaleSteps++;
}
imageReader.setScaledSize(imgSize);
QImage snapPreview = imageReader.read();
QMetaObject::invokeMethod(this, "imageCaptured", Qt::QueuedConnection,
Q_ARG(int, captureId),
Q_ARG(QImage, snapPreview));
}
qDebugCamera() << "Image captured" << actualFileName;
QFile f(actualFileName);
if (f.open(QFile::WriteOnly)) {
if (f.write(jpgData) != -1) {
QMetaObject::invokeMethod(this, "imageSaved", Qt::QueuedConnection,
Q_ARG(int, captureId),
Q_ARG(QString, actualFileName));
} else {
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(int, captureId),
Q_ARG(int, QCameraImageCapture::OutOfSpaceError),
Q_ARG(QString, f.errorString()));
}
} else {
QString errorMessage = tr("Could not open destination file:\n%1").arg(actualFileName);
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(int, captureId),
Q_ARG(int, QCameraImageCapture::ResourceError),
Q_ARG(QString, errorMessage));
}
}
}];
return captureId;
}
void AVFImageCaptureControl::cancelCapture()
{
//not supported
}
void AVFImageCaptureControl::updateCaptureConnection()
{
if (!m_videoConnection &&
m_cameraControl->captureMode().testFlag(QCamera::CaptureStillImage)) {
qDebugCamera() << Q_FUNC_INFO;
AVCaptureSession *captureSession = m_session->captureSession();
if ([captureSession canAddOutput:m_stillImageOutput]) {
[captureSession addOutput:m_stillImageOutput];
for (AVCaptureConnection *connection in m_stillImageOutput.connections) {
for (AVCaptureInputPort *port in [connection inputPorts]) {
if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
m_videoConnection = connection;
break;
}
}
if (m_videoConnection)
break;
}
}
updateReadyStatus();
}
}
#include "moc_avfimagecapturecontrol.cpp"

View File

@@ -0,0 +1,113 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AVFMEDIARECORDERCONTROL_H
#define AVFMEDIARECORDERCONTROL_H
#include <QtCore/qurl.h>
#include <QtMultimedia/qmediarecordercontrol.h>
#import <AVFoundation/AVFoundation.h>
#include "avfstoragelocation.h"
QT_BEGIN_NAMESPACE
class AVFCameraSession;
class AVFCameraControl;
class AVFCameraService;
@class AVFMediaRecorderDelegate;
class AVFMediaRecorderControl : public QMediaRecorderControl
{
Q_OBJECT
public:
AVFMediaRecorderControl(AVFCameraService *service, QObject *parent = 0);
~AVFMediaRecorderControl();
QUrl outputLocation() const;
bool setOutputLocation(const QUrl &location);
QMediaRecorder::State state() const;
QMediaRecorder::Status status() const;
qint64 duration() const;
bool isMuted() const;
qreal volume() const;
void applySettings();
public Q_SLOTS:
void setState(QMediaRecorder::State state);
void setMuted(bool muted);
void setVolume(qreal volume);
void handleRecordingStarted();
void handleRecordingFinished();
void handleRecordingFailed(const QString &message);
private Q_SLOTS:
void reconnectMovieOutput();
void updateStatus();
private:
AVFCameraControl *m_cameraControl;
AVFCameraSession *m_session;
bool m_connected;
QUrl m_outputLocation;
QMediaRecorder::State m_state;
QMediaRecorder::Status m_lastStatus;
bool m_recordingStarted;
bool m_recordingFinished;
bool m_muted;
qreal m_volume;
AVCaptureMovieFileOutput *m_movieOutput;
AVFMediaRecorderDelegate *m_recorderDelagate;
AVFStorageLocation m_storageLocation;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,342 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "avfcameradebug.h"
#include "avfmediarecordercontrol.h"
#include "avfcamerasession.h"
#include "avfcameraservice.h"
#include "avfcameracontrol.h"
#include <QtCore/qurl.h>
#include <QtCore/qfileinfo.h>
#include <QtMultimedia/qcameracontrol.h>
QT_USE_NAMESPACE
@interface AVFMediaRecorderDelegate : NSObject <AVCaptureFileOutputRecordingDelegate>
{
@private
AVFMediaRecorderControl *m_recorder;
}
- (AVFMediaRecorderDelegate *) initWithRecorder:(AVFMediaRecorderControl*)recorder;
- (void) captureOutput:(AVCaptureFileOutput *)captureOutput
didStartRecordingToOutputFileAtURL:(NSURL *)fileURL
fromConnections:(NSArray *)connections;
- (void) captureOutput:(AVCaptureFileOutput *)captureOutput
didFinishRecordingToOutputFileAtURL:(NSURL *)fileURL
fromConnections:(NSArray *)connections
error:(NSError *)error;
@end
@implementation AVFMediaRecorderDelegate
- (AVFMediaRecorderDelegate *) initWithRecorder:(AVFMediaRecorderControl*)recorder
{
if (!(self = [super init]))
return nil;
self->m_recorder = recorder;
return self;
}
- (void) captureOutput:(AVCaptureFileOutput *)captureOutput
didStartRecordingToOutputFileAtURL:(NSURL *)fileURL
fromConnections:(NSArray *)connections
{
Q_UNUSED(captureOutput);
Q_UNUSED(fileURL);
Q_UNUSED(connections)
QMetaObject::invokeMethod(m_recorder, "handleRecordingStarted", Qt::QueuedConnection);
}
- (void) captureOutput:(AVCaptureFileOutput *)captureOutput
didFinishRecordingToOutputFileAtURL:(NSURL *)fileURL
fromConnections:(NSArray *)connections
error:(NSError *)error
{
Q_UNUSED(captureOutput);
Q_UNUSED(fileURL);
Q_UNUSED(connections)
if (error) {
QStringList messageParts;
messageParts << QString::fromUtf8([[error localizedDescription] UTF8String]);
messageParts << QString::fromUtf8([[error localizedFailureReason] UTF8String]);
messageParts << QString::fromUtf8([[error localizedRecoverySuggestion] UTF8String]);
QString errorMessage = messageParts.join(" ");
QMetaObject::invokeMethod(m_recorder, "handleRecordingFailed", Qt::QueuedConnection,
Q_ARG(QString, errorMessage));
} else {
QMetaObject::invokeMethod(m_recorder, "handleRecordingFinished", Qt::QueuedConnection);
}
}
@end
AVFMediaRecorderControl::AVFMediaRecorderControl(AVFCameraService *service, QObject *parent)
: QMediaRecorderControl(parent)
, m_cameraControl(service->cameraControl())
, m_session(service->session())
, m_connected(false)
, m_state(QMediaRecorder::StoppedState)
, m_lastStatus(QMediaRecorder::UnloadedStatus)
, m_recordingStarted(false)
, m_recordingFinished(false)
, m_muted(false)
, m_volume(1.0)
{
m_movieOutput = [[AVCaptureMovieFileOutput alloc] init];
m_recorderDelagate = [[AVFMediaRecorderDelegate alloc] initWithRecorder:this];
connect(m_cameraControl, SIGNAL(stateChanged(QCamera::State)), SLOT(updateStatus()));
connect(m_cameraControl, SIGNAL(statusChanged(QCamera::Status)), SLOT(updateStatus()));
connect(m_cameraControl, SIGNAL(captureModeChanged(QCamera::CaptureModes)), SLOT(reconnectMovieOutput()));
reconnectMovieOutput();
}
AVFMediaRecorderControl::~AVFMediaRecorderControl()
{
if (m_movieOutput)
[m_session->captureSession() removeOutput:m_movieOutput];
[m_recorderDelagate release];
}
QUrl AVFMediaRecorderControl::outputLocation() const
{
return m_outputLocation;
}
bool AVFMediaRecorderControl::setOutputLocation(const QUrl &location)
{
m_outputLocation = location;
return location.scheme() == QLatin1String("file") || location.scheme().isEmpty();
}
QMediaRecorder::State AVFMediaRecorderControl::state() const
{
return m_state;
}
QMediaRecorder::Status AVFMediaRecorderControl::status() const
{
QMediaRecorder::Status status = m_lastStatus;
//bool videoEnabled = m_cameraControl->captureMode().testFlag(QCamera::CaptureVideo);
if (m_cameraControl->status() == QCamera::ActiveStatus && m_connected) {
if (m_state == QMediaRecorder::StoppedState) {
if (m_recordingStarted && !m_recordingFinished)
status = QMediaRecorder::FinalizingStatus;
else
status = QMediaRecorder::LoadedStatus;
} else {
status = m_recordingStarted ? QMediaRecorder::RecordingStatus :
QMediaRecorder::StartingStatus;
}
} else {
//camera not started yet
status = m_cameraControl->state() == QCamera::ActiveState && m_connected ?
QMediaRecorder::LoadingStatus:
QMediaRecorder::UnloadedStatus;
}
return status;
}
void AVFMediaRecorderControl::updateStatus()
{
QMediaRecorder::Status newStatus = status();
if (m_lastStatus != newStatus) {
qDebugCamera() << "Camera recorder status changed: " << m_lastStatus << " -> " << newStatus;
m_lastStatus = newStatus;
Q_EMIT statusChanged(m_lastStatus);
}
}
qint64 AVFMediaRecorderControl::duration() const
{
if (!m_movieOutput)
return 0;
return qint64(CMTimeGetSeconds(m_movieOutput.recordedDuration) * 1000);
}
bool AVFMediaRecorderControl::isMuted() const
{
return m_muted;
}
qreal AVFMediaRecorderControl::volume() const
{
return m_volume;
}
void AVFMediaRecorderControl::applySettings()
{
}
void AVFMediaRecorderControl::setState(QMediaRecorder::State state)
{
if (m_state == state)
return;
qDebugCamera() << Q_FUNC_INFO << m_state << " -> " << state;
switch (state) {
case QMediaRecorder::RecordingState:
{
if (m_connected) {
m_state = QMediaRecorder::RecordingState;
m_recordingStarted = false;
m_recordingFinished = false;
QString outputLocationPath = m_outputLocation.scheme() == QLatin1String("file") ?
m_outputLocation.path() : m_outputLocation.toString();
QUrl actualLocation = QUrl::fromLocalFile(
m_storageLocation.generateFileName(outputLocationPath,
QCamera::CaptureVideo,
QLatin1String("clip_"),
QLatin1String("mp4")));
qDebugCamera() << "Video capture location:" << actualLocation.toString();
NSString *urlString = [NSString stringWithUTF8String:actualLocation.toString().toUtf8().constData()];
NSURL *fileURL = [NSURL URLWithString:urlString];
[m_movieOutput startRecordingToOutputFileURL:fileURL recordingDelegate:m_recorderDelagate];
Q_EMIT actualLocationChanged(actualLocation);
} else {
Q_EMIT error(QMediaRecorder::FormatError, tr("Recorder not configured"));
}
} break;
case QMediaRecorder::PausedState:
{
Q_EMIT error(QMediaRecorder::FormatError, tr("Recording pause not supported"));
return;
} break;
case QMediaRecorder::StoppedState:
{
m_state = QMediaRecorder::StoppedState;
[m_movieOutput stopRecording];
}
}
updateStatus();
Q_EMIT stateChanged(m_state);
}
void AVFMediaRecorderControl::setMuted(bool muted)
{
if (m_muted != muted) {
m_muted = muted;
Q_EMIT mutedChanged(muted);
}
}
void AVFMediaRecorderControl::setVolume(qreal volume)
{
if (m_volume != volume) {
m_volume = volume;
Q_EMIT volumeChanged(volume);
}
}
void AVFMediaRecorderControl::handleRecordingStarted()
{
m_recordingStarted = true;
updateStatus();
}
void AVFMediaRecorderControl::handleRecordingFinished()
{
m_recordingFinished = true;
updateStatus();
}
void AVFMediaRecorderControl::handleRecordingFailed(const QString &message)
{
m_recordingFinished = true;
if (m_state != QMediaRecorder::StoppedState) {
m_state = QMediaRecorder::StoppedState;
Q_EMIT stateChanged(m_state);
}
updateStatus();
Q_EMIT error(QMediaRecorder::ResourceError, message);
}
void AVFMediaRecorderControl::reconnectMovieOutput()
{
//adding movie output causes high CPU usage even when while recording is not active,
//connect it only while video capture mode is enabled
AVCaptureSession *captureSession = m_session->captureSession();
if (!m_connected && m_cameraControl->captureMode().testFlag(QCamera::CaptureVideo)) {
if ([captureSession canAddOutput:m_movieOutput]) {
[captureSession addOutput:m_movieOutput];
m_connected = true;
} else {
Q_EMIT error(QMediaRecorder::ResourceError, tr("Could not connect the video recorder"));
qWarning() << "Could not connect the video recorder";
}
} else if (m_connected && !m_cameraControl->captureMode().testFlag(QCamera::CaptureVideo)) {
[captureSession removeOutput:m_movieOutput];
m_connected = false;
}
updateStatus();
}
#include "moc_avfmediarecordercontrol.cpp"

View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AVFSTORAGE_H
#define AVFSTORAGE_H
#include "qtmultimediadefs.h"
#include <QtCore/qdir.h>
#include <QtMultimedia/qcamera.h>
QT_BEGIN_NAMESPACE
class AVFStorageLocation
{
public:
AVFStorageLocation();
~AVFStorageLocation();
QString generateFileName(const QString &requestedName,
QCamera::CaptureMode mode,
const QString &prefix,
const QString &ext) const;
QDir defaultDir(QCamera::CaptureMode mode) const;
QString generateFileName(const QString &prefix, const QDir &dir, const QString &ext) const;
private:
mutable QMap<QString, int> m_lastUsedIndex;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,137 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "avfstoragelocation.h"
#include "QtCore/qstandardpaths.h"
QT_BEGIN_NAMESPACE
AVFStorageLocation::AVFStorageLocation()
{
}
AVFStorageLocation::~AVFStorageLocation()
{
}
/*!
* Generate the actual file name from user requested one.
* requestedName may be either empty (the default dir and naming theme is used),
* points to existing dir (the default name used)
* or specify the full actual path.
*/
QString AVFStorageLocation::generateFileName(const QString &requestedName,
QCamera::CaptureMode mode,
const QString &prefix,
const QString &ext) const
{
if (requestedName.isEmpty())
return generateFileName(prefix, defaultDir(mode), ext);
if (QFileInfo(requestedName).isDir())
return generateFileName(prefix, QDir(requestedName), ext);
return requestedName;
}
QDir AVFStorageLocation::defaultDir(QCamera::CaptureMode mode) const
{
QStringList dirCandidates;
if (mode == QCamera::CaptureVideo) {
dirCandidates << QStandardPaths::writableLocation(QStandardPaths::MoviesLocation);
} else {
dirCandidates << QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
}
dirCandidates << QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
dirCandidates << QDir::homePath();
dirCandidates << QDir::currentPath();
dirCandidates << QDir::tempPath();
Q_FOREACH (const QString &path, dirCandidates) {
if (QFileInfo(path).isWritable())
return QDir(path);
}
return QDir();
}
QString AVFStorageLocation::generateFileName(const QString &prefix, const QDir &dir, const QString &ext) const
{
QString lastClipKey = dir.absolutePath()+QLatin1Char(' ')+prefix+QLatin1Char(' ')+ext;
int lastClip = m_lastUsedIndex.value(lastClipKey, 0);
if (lastClip == 0) {
//first run, find the maximum clip number during the fist capture
Q_FOREACH (const QString &fileName, dir.entryList(QStringList() << QString("%1*.%2").arg(prefix).arg(ext))) {
int imgNumber = fileName.mid(prefix.length(), fileName.size()-prefix.length()-ext.length()-1).toInt();
lastClip = qMax(lastClip, imgNumber);
}
}
//don't just rely on cached lastClip value,
//someone else may create a file after camera started
while (true) {
QString name = QString("%1%2.%3").arg(prefix)
.arg(lastClip+1,
4, //fieldWidth
10,
QLatin1Char('0'))
.arg(ext);
QString path = dir.absoluteFilePath(name);
if (!QFileInfo(path).exists()) {
m_lastUsedIndex[lastClipKey] = lastClip+1;
return path;
}
lastClip++;
}
return QString();
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,89 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AVFVIDEODEVICECONTROL_H
#define AVFVIDEODEVICECONTROL_H
#include <QtMultimedia/qvideodeviceselectorcontrol.h>
#include <QtCore/qstringlist.h>
#import <AVFoundation/AVFoundation.h>
QT_BEGIN_NAMESPACE
class AVFCameraSession;
class AVFCameraService;
class AVFVideoDeviceControl : public QVideoDeviceSelectorControl
{
Q_OBJECT
public:
AVFVideoDeviceControl(AVFCameraService *service, QObject *parent = 0);
~AVFVideoDeviceControl();
int deviceCount() const;
QString deviceName(int index) const;
QString deviceDescription(int index) const;
int defaultDevice() const;
int selectedDevice() const;
public Q_SLOTS:
void setSelectedDevice(int index);
public:
//device changed since the last createCaptureDevice()
bool isDirty() const { return m_dirty; }
AVCaptureDevice *createCaptureDevice();
private:
AVFCameraService *m_service;
int m_selectedDevice;
bool m_dirty;
QStringList m_devices;
QStringList m_deviceDescriptions;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,119 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "avfcameradebug.h"
#include "avfvideodevicecontrol.h"
#include "avfcameraservice.h"
QT_USE_NAMESPACE
AVFVideoDeviceControl::AVFVideoDeviceControl(AVFCameraService *service, QObject *parent)
: QVideoDeviceSelectorControl(parent)
, m_service(service)
, 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()
{
}
int AVFVideoDeviceControl::deviceCount() const
{
return m_devices.size();
}
QString AVFVideoDeviceControl::deviceName(int index) const
{
return m_devices[index];
}
QString AVFVideoDeviceControl::deviceDescription(int index) const
{
return m_deviceDescriptions[index];
}
int AVFVideoDeviceControl::defaultDevice() const
{
return 0;
}
int AVFVideoDeviceControl::selectedDevice() const
{
return m_selectedDevice;
}
void AVFVideoDeviceControl::setSelectedDevice(int index)
{
if (index != m_selectedDevice) {
m_dirty = true;
m_selectedDevice = index;
Q_EMIT selectedDeviceChanged(index);
Q_EMIT selectedDeviceChanged(m_devices[index]);
}
}
AVCaptureDevice *AVFVideoDeviceControl::createCaptureDevice()
{
m_dirty = false;
AVCaptureDevice *device = 0;
if (!m_devices.isEmpty()) {
QString deviceId = m_devices.at(m_selectedDevice);
device = [AVCaptureDevice deviceWithUniqueID:
[NSString stringWithUTF8String:
deviceId.toUtf8().constData()]];
}
if (!device)
device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
return device;
}
#include "moc_avfvideodevicecontrol.cpp"

View File

@@ -0,0 +1,90 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef AVFVIDEORENDERERCONTROL_H
#define AVFVIDEORENDERERCONTROL_H
#include <QtMultimedia/qvideorenderercontrol.h>
#include <QtMultimedia/qvideoframe.h>
#include <QtCore/qmutex.h>
#import <AVFoundation/AVFoundation.h>
QT_BEGIN_NAMESPACE
class AVFCameraSession;
class AVFCameraService;
class AVFVideoRendererControl;
@class AVFCaptureFramesDelegate;
class AVFVideoRendererControl : public QVideoRendererControl
{
Q_OBJECT
public:
AVFVideoRendererControl(QObject *parent = 0);
~AVFVideoRendererControl();
QAbstractVideoSurface *surface() const;
void setSurface(QAbstractVideoSurface *surface);
void configureAVCaptureSession(AVCaptureSession *captureSession);
void syncHandleViewfinderFrame(const QVideoFrame &frame);
Q_SIGNALS:
void surfaceChanged(QAbstractVideoSurface *surface);
private Q_SLOTS:
void handleViewfinderFrame();
private:
QAbstractVideoSurface *m_surface;
AVFCaptureFramesDelegate *m_viewfinderFramesDelegate;
AVCaptureSession *m_captureSession;
AVCaptureVideoDataOutput *m_videoDataOutput;
QVideoFrame m_lastViewfinderFrame;
QMutex m_vfMutex;
};
QT_END_NAMESPACE
#endif

View File

@@ -0,0 +1,237 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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, Nokia gives you certain additional
** rights. These rights are described in the Nokia 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "avfvideorenderercontrol.h"
#include "avfcamerasession.h"
#include "avfcameraservice.h"
#include "avfcameradebug.h"
#include <QtMultimedia/qabstractvideosurface.h>
#include <QtMultimedia/qabstractvideobuffer.h>
#include <QtMultimedia/qvideosurfaceformat.h>
QT_USE_NAMESPACE
class CVPixelBufferVideoBuffer : public QAbstractVideoBuffer
{
public:
CVPixelBufferVideoBuffer(CVPixelBufferRef buffer)
: QAbstractVideoBuffer(NoHandle)
, m_buffer(buffer)
, m_mode(NotMapped)
{
CVPixelBufferRetain(m_buffer);
}
virtual ~CVPixelBufferVideoBuffer()
{
CVPixelBufferRelease(m_buffer);
}
MapMode mapMode() const { return m_mode; }
uchar *map(MapMode mode, int *numBytes, int *bytesPerLine)
{
if (mode != NotMapped && m_mode == NotMapped) {
CVPixelBufferLockBaseAddress(m_buffer, 0);
if (numBytes)
*numBytes = CVPixelBufferGetDataSize(m_buffer);
if (bytesPerLine)
*bytesPerLine = CVPixelBufferGetBytesPerRow(m_buffer);
m_mode = mode;
return (uchar*)CVPixelBufferGetBaseAddress(m_buffer);
} else {
return 0;
}
}
void unmap()
{
if (m_mode != NotMapped) {
m_mode = NotMapped;
CVPixelBufferUnlockBaseAddress(m_buffer, 0);
}
}
private:
CVPixelBufferRef m_buffer;
MapMode m_mode;
};
@interface AVFCaptureFramesDelegate : NSObject <AVCaptureVideoDataOutputSampleBufferDelegate>
{
@private
AVFVideoRendererControl *m_renderer;
}
- (AVFCaptureFramesDelegate *) initWithRenderer:(AVFVideoRendererControl*)renderer;
- (void) captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection;
@end
@implementation AVFCaptureFramesDelegate
- (AVFCaptureFramesDelegate *) initWithRenderer:(AVFVideoRendererControl*)renderer
{
if (!(self = [super init]))
return nil;
self->m_renderer = renderer;
return self;
}
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection
{
Q_UNUSED(connection);
Q_UNUSED(captureOutput);
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
int width = CVPixelBufferGetWidth(imageBuffer);
int height = CVPixelBufferGetHeight(imageBuffer);
QAbstractVideoBuffer *buffer = new CVPixelBufferVideoBuffer(imageBuffer);
QVideoFrame frame(buffer, QSize(width, height), QVideoFrame::Format_RGB32);
m_renderer->syncHandleViewfinderFrame(frame);
}
@end
AVFVideoRendererControl::AVFVideoRendererControl(QObject *parent)
: QVideoRendererControl(parent)
, m_surface(0)
{
m_viewfinderFramesDelegate = [[AVFCaptureFramesDelegate alloc] initWithRenderer:this];
}
AVFVideoRendererControl::~AVFVideoRendererControl()
{
[m_captureSession removeOutput:m_videoDataOutput];
[m_viewfinderFramesDelegate release];
}
QAbstractVideoSurface *AVFVideoRendererControl::surface() const
{
return m_surface;
}
void AVFVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
{
if (m_surface != surface) {
m_surface = surface;
Q_EMIT surfaceChanged(surface);
}
}
void AVFVideoRendererControl::configureAVCaptureSession(AVCaptureSession *captureSession)
{
m_captureSession = captureSession;
m_videoDataOutput = [[[AVCaptureVideoDataOutput alloc] init] autorelease];
// Configure video output
dispatch_queue_t queue = dispatch_queue_create("vf_queue", NULL);
[m_videoDataOutput
setSampleBufferDelegate:m_viewfinderFramesDelegate
queue:queue];
dispatch_release(queue);
// Specify the pixel format
m_videoDataOutput.videoSettings =
[NSDictionary dictionaryWithObject:
[NSNumber numberWithInt:kCVPixelFormatType_32BGRA]
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
[m_captureSession addOutput:m_videoDataOutput];
}
//can be called from non main thread
void AVFVideoRendererControl::syncHandleViewfinderFrame(const QVideoFrame &frame)
{
QMutexLocker lock(&m_vfMutex);
if (!m_lastViewfinderFrame.isValid()) {
static QMetaMethod handleViewfinderFrameSlot = metaObject()->method(
metaObject()->indexOfMethod("handleViewfinderFrame()"));
handleViewfinderFrameSlot.invoke(this, Qt::QueuedConnection);
}
m_lastViewfinderFrame = frame;
}
void AVFVideoRendererControl::handleViewfinderFrame()
{
QVideoFrame frame;
{
QMutexLocker lock(&m_vfMutex);
frame = m_lastViewfinderFrame;
m_lastViewfinderFrame = QVideoFrame();
}
if (m_surface && frame.isValid()) {
if (m_surface->isActive() && m_surface->surfaceFormat().pixelFormat() != frame.pixelFormat())
m_surface->stop();
if (!m_surface->isActive()) {
QVideoSurfaceFormat format(frame.size(), frame.pixelFormat());
if (!m_surface->start(format)) {
qWarning() << "Failed to start viewfinder m_surface, format:" << format;
} else {
qDebugCamera() << "Viewfinder started: " << format;
}
}
if (m_surface->isActive())
m_surface->present(frame);
}
}
#include "moc_avfvideorenderercontrol.cpp"

View File

@@ -0,0 +1,52 @@
load(qt_build_config)
# Avoid clash with a variable named `slots' in a Quartz header
CONFIG += no_keywords
TARGET = qavfcamera
QT += multimedia-private network
PLUGIN_TYPE = mediaservice
load(qt_plugin)
DESTDIR = $$QT.multimedia.plugins/$${PLUGIN_TYPE}
LIBS += -framework AppKit -framework AudioUnit \
-framework AudioToolbox -framework CoreAudio \
-framework QuartzCore -framework AVFoundation \
-framework CoreMedia
target.path += $$[QT_INSTALL_PLUGINS]/$${PLUGIN_TYPE}
INSTALLS += target
OTHER_FILES += avfcamera.json
DEFINES += QMEDIA_AVF_CAMERA
HEADERS += \
avfcameradebug.h \
avfcameraserviceplugin.h \
avfcameracontrol.h \
avfvideorenderercontrol.h \
avfcamerametadatacontrol.h \
avfimagecapturecontrol.h \
avfmediarecordercontrol.h \
avfcameraservice.h \
avfcamerasession.h \
avfstoragelocation.h \
avfvideodevicecontrol.h \
avfaudioinputselectorcontrol.h \
OBJECTIVE_SOURCES += \
avfcameraserviceplugin.mm \
avfcameracontrol.mm \
avfvideorenderercontrol.mm \
avfcamerametadatacontrol.mm \
avfimagecapturecontrol.mm \
avfmediarecordercontrol.mm \
avfcameraservice.mm \
avfcamerasession.mm \
avfstoragelocation.mm \
avfvideodevicecontrol.mm \
avfaudioinputselectorcontrol.mm \

View File

@@ -38,5 +38,7 @@ unix:!mac {
mac:!simulator {
SUBDIRS += audiocapture qt7
config_avfoundation: SUBDIRS += avfoundation
}