From 9a215d954b00b6d07568392a1894341027c1af5a Mon Sep 17 00:00:00 2001 From: James Turner Date: Mon, 12 Jan 2015 17:15:28 +0000 Subject: Rename camera classes to avoid name clash. Change-Id: I08fe8f7e75bdbf2c4975863642072061741b5bc6 Reviewed-by: Filipe Azevedo Reviewed-by: Sean Harmer Reviewed-by: Yoann Lopes --- .../avfoundation/camera/avfcameradevicecontrol.h | 79 ++++++ .../avfoundation/camera/avfcameradevicecontrol.mm | 125 ++++++++++ .../avfoundation/camera/avfcamerarenderercontrol.h | 85 +++++++ .../camera/avfcamerarenderercontrol.mm | 276 +++++++++++++++++++++ src/plugins/avfoundation/camera/avfcameraservice.h | 10 +- .../avfoundation/camera/avfcameraservice.mm | 8 +- src/plugins/avfoundation/camera/avfcamerasession.h | 6 +- .../avfoundation/camera/avfcamerasession.mm | 6 +- .../avfoundation/camera/avfvideodevicecontrol.h | 79 ------ .../avfoundation/camera/avfvideodevicecontrol.mm | 124 --------- .../avfoundation/camera/avfvideorenderercontrol.h | 85 ------- .../avfoundation/camera/avfvideorenderercontrol.mm | 276 --------------------- src/plugins/avfoundation/camera/camera.pro | 14 +- 13 files changed, 588 insertions(+), 585 deletions(-) create mode 100644 src/plugins/avfoundation/camera/avfcameradevicecontrol.h create mode 100644 src/plugins/avfoundation/camera/avfcameradevicecontrol.mm create mode 100644 src/plugins/avfoundation/camera/avfcamerarenderercontrol.h create mode 100644 src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm delete mode 100644 src/plugins/avfoundation/camera/avfvideodevicecontrol.h delete mode 100644 src/plugins/avfoundation/camera/avfvideodevicecontrol.mm delete mode 100644 src/plugins/avfoundation/camera/avfvideorenderercontrol.h delete mode 100644 src/plugins/avfoundation/camera/avfvideorenderercontrol.mm (limited to 'src/plugins/avfoundation') diff --git a/src/plugins/avfoundation/camera/avfcameradevicecontrol.h b/src/plugins/avfoundation/camera/avfcameradevicecontrol.h new file mode 100644 index 000000000..20e78b77d --- /dev/null +++ b/src/plugins/avfoundation/camera/avfcameradevicecontrol.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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:LGPL21$ +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef AVFCAMERADEVICECONTROL_H +#define AVFCAMERADEVICECONTROL_H + +#include +#include + +#import + +QT_BEGIN_NAMESPACE + +class AVFCameraSession; +class AVFCameraService; + +class AVFCameraDeviceControl : public QVideoDeviceSelectorControl +{ +Q_OBJECT +public: + AVFCameraDeviceControl(AVFCameraService *service, QObject *parent = 0); + ~AVFCameraDeviceControl(); + + 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; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/avfoundation/camera/avfcameradevicecontrol.mm b/src/plugins/avfoundation/camera/avfcameradevicecontrol.mm new file mode 100644 index 000000000..15e6b4a55 --- /dev/null +++ b/src/plugins/avfoundation/camera/avfcameradevicecontrol.mm @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** 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 "avfcameradebug.h" +#include "avfcameradevicecontrol.h" +#include "avfcameraservice.h" +#include "avfcamerasession.h" + +QT_USE_NAMESPACE + +AVFCameraDeviceControl::AVFCameraDeviceControl(AVFCameraService *service, QObject *parent) + : QVideoDeviceSelectorControl(parent) + , m_service(service) + , m_selectedDevice(0) + , m_dirty(true) +{ + Q_UNUSED(m_service); +} + +AVFCameraDeviceControl::~AVFCameraDeviceControl() +{ +} + +int AVFCameraDeviceControl::deviceCount() const +{ + return AVFCameraSession::availableCameraDevices().count(); +} + +QString AVFCameraDeviceControl::deviceName(int index) const +{ + const QList &devices = AVFCameraSession::availableCameraDevices(); + if (index < 0 || index >= devices.count()) + return QString(); + + return QString::fromUtf8(devices.at(index)); +} + +QString AVFCameraDeviceControl::deviceDescription(int index) const +{ + const QList &devices = AVFCameraSession::availableCameraDevices(); + if (index < 0 || index >= devices.count()) + return QString(); + + return AVFCameraSession::cameraDeviceInfo(devices.at(index)).description; +} + +int AVFCameraDeviceControl::defaultDevice() const +{ + return AVFCameraSession::availableCameraDevices().indexOf(AVFCameraSession::defaultCameraDevice()); +} + +int AVFCameraDeviceControl::selectedDevice() const +{ + return m_selectedDevice; +} + +void AVFCameraDeviceControl::setSelectedDevice(int index) +{ + if (index >= 0 && + index < deviceCount() && + index != m_selectedDevice) { + m_dirty = true; + m_selectedDevice = index; + Q_EMIT selectedDeviceChanged(index); + Q_EMIT selectedDeviceChanged(deviceName(index)); + } +} + +AVCaptureDevice *AVFCameraDeviceControl::createCaptureDevice() +{ + m_dirty = false; + AVCaptureDevice *device = 0; + + QString deviceId = deviceName(m_selectedDevice); + if (!deviceId.isEmpty()) { + device = [AVCaptureDevice deviceWithUniqueID: + [NSString stringWithUTF8String: + deviceId.toUtf8().constData()]]; + } + + if (!device) + device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + + return device; +} + +#include "moc_avfcameradevicecontrol.cpp" diff --git a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.h b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.h new file mode 100644 index 000000000..92c8ba740 --- /dev/null +++ b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** 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:LGPL21$ +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef AVFCAMERARENDERERCONTROL_H +#define AVFCAMERARENDERERCONTROL_H + +#include +#include +#include + +#import + +@class AVFCaptureFramesDelegate; + +QT_BEGIN_NAMESPACE + +class AVFCameraSession; +class AVFCameraService; +class AVFCameraRendererControl; + +class AVFCameraRendererControl : public QVideoRendererControl +{ +Q_OBJECT +public: + AVFCameraRendererControl(QObject *parent = 0); + ~AVFCameraRendererControl(); + + QAbstractVideoSurface *surface() const; + void setSurface(QAbstractVideoSurface *surface); + + void configureAVCaptureSession(AVFCameraSession *cameraSession); + void syncHandleViewfinderFrame(const QVideoFrame &frame); + +Q_SIGNALS: + void surfaceChanged(QAbstractVideoSurface *surface); + +private Q_SLOTS: + void handleViewfinderFrame(); + void updateCaptureConnection(); + +private: + QAbstractVideoSurface *m_surface; + AVFCaptureFramesDelegate *m_viewfinderFramesDelegate; + AVFCameraSession *m_cameraSession; + AVCaptureVideoDataOutput *m_videoDataOutput; + + bool m_needsHorizontalMirroring; + + QVideoFrame m_lastViewfinderFrame; + QMutex m_vfMutex; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm new file mode 100644 index 000000000..6f9b64986 --- /dev/null +++ b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm @@ -0,0 +1,276 @@ +/**************************************************************************** +** +** 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 "avfcamerarenderercontrol.h" +#include "avfcamerasession.h" +#include "avfcameraservice.h" +#include "avfcameradebug.h" + +#include +#include +#include + +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 +{ +@private + AVFCameraRendererControl *m_renderer; +} + +- (AVFCaptureFramesDelegate *) initWithRenderer:(AVFCameraRendererControl*)renderer; + +- (void) captureOutput:(AVCaptureOutput *)captureOutput + didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer + fromConnection:(AVCaptureConnection *)connection; +@end + +@implementation AVFCaptureFramesDelegate + +- (AVFCaptureFramesDelegate *) initWithRenderer:(AVFCameraRendererControl*)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 + + +AVFCameraRendererControl::AVFCameraRendererControl(QObject *parent) + : QVideoRendererControl(parent) + , m_surface(0) + , m_needsHorizontalMirroring(false) +{ + m_viewfinderFramesDelegate = [[AVFCaptureFramesDelegate alloc] initWithRenderer:this]; +} + +AVFCameraRendererControl::~AVFCameraRendererControl() +{ + [m_cameraSession->captureSession() removeOutput:m_videoDataOutput]; + [m_viewfinderFramesDelegate release]; +} + +QAbstractVideoSurface *AVFCameraRendererControl::surface() const +{ + return m_surface; +} + +void AVFCameraRendererControl::setSurface(QAbstractVideoSurface *surface) +{ + if (m_surface != surface) { + m_surface = surface; + Q_EMIT surfaceChanged(surface); + } +} + +void AVFCameraRendererControl::configureAVCaptureSession(AVFCameraSession *cameraSession) +{ + m_cameraSession = cameraSession; + connect(m_cameraSession, SIGNAL(readyToConfigureConnections()), + this, SLOT(updateCaptureConnection())); + + m_needsHorizontalMirroring = false; + + 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_cameraSession->captureSession() addOutput:m_videoDataOutput]; +} + +void AVFCameraRendererControl::updateCaptureConnection() +{ + AVCaptureConnection *connection = [m_videoDataOutput connectionWithMediaType:AVMediaTypeVideo]; + if (connection == nil || !m_cameraSession->videoCaptureDevice()) + return; + + // Frames of front-facing cameras should be mirrored horizontally (it's the default when using + // AVCaptureVideoPreviewLayer but not with AVCaptureVideoDataOutput) + if (connection.isVideoMirroringSupported) + connection.videoMirrored = m_cameraSession->videoCaptureDevice().position == AVCaptureDevicePositionFront; + + // If the connection does't support mirroring, we'll have to do it ourselves + m_needsHorizontalMirroring = !connection.isVideoMirrored + && m_cameraSession->videoCaptureDevice().position == AVCaptureDevicePositionFront; +} + +//can be called from non main thread +void AVFCameraRendererControl::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; + + if (m_needsHorizontalMirroring) { + m_lastViewfinderFrame.map(QAbstractVideoBuffer::ReadOnly); + + // no deep copy + QImage image(m_lastViewfinderFrame.bits(), + m_lastViewfinderFrame.size().width(), + m_lastViewfinderFrame.size().height(), + m_lastViewfinderFrame.bytesPerLine(), + QImage::Format_RGB32); + + QImage mirrored = image.mirrored(true, false); + + m_lastViewfinderFrame.unmap(); + m_lastViewfinderFrame = QVideoFrame(mirrored); + } + if (m_cameraSession && m_lastViewfinderFrame.isValid()) + m_cameraSession->onCameraFrameFetched(m_lastViewfinderFrame); +} + +void AVFCameraRendererControl::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_avfcamerarenderercontrol.cpp" diff --git a/src/plugins/avfoundation/camera/avfcameraservice.h b/src/plugins/avfoundation/camera/avfcameraservice.h index 6e5465395..5d5d3b945 100644 --- a/src/plugins/avfoundation/camera/avfcameraservice.h +++ b/src/plugins/avfoundation/camera/avfcameraservice.h @@ -46,11 +46,11 @@ class AVFCameraInfoControl; class AVFCameraMetaDataControl; class AVFVideoWindowControl; class AVFVideoWidgetControl; -class AVFVideoRendererControl; +class AVFCameraRendererControl; class AVFMediaRecorderControl; class AVFImageCaptureControl; class AVFCameraSession; -class AVFVideoDeviceControl; +class AVFCameraDeviceControl; class AVFAudioInputSelectorControl; class AVFCameraService : public QMediaService @@ -65,7 +65,7 @@ public: AVFCameraSession *session() const { return m_session; } AVFCameraControl *cameraControl() const { return m_cameraControl; } - AVFVideoDeviceControl *videoDeviceControl() const { return m_videoDeviceControl; } + AVFCameraDeviceControl *videoDeviceControl() const { return m_videoDeviceControl; } AVFAudioInputSelectorControl *audioInputSelectorControl() const { return m_audioInputSelectorControl; } AVFCameraMetaDataControl *metaDataControl() const { return m_metaDataControl; } AVFMediaRecorderControl *recorderControl() const { return m_recorderControl; } @@ -76,9 +76,9 @@ private: AVFCameraSession *m_session; AVFCameraControl *m_cameraControl; AVFCameraInfoControl *m_cameraInfoControl; - AVFVideoDeviceControl *m_videoDeviceControl; + AVFCameraDeviceControl *m_videoDeviceControl; AVFAudioInputSelectorControl *m_audioInputSelectorControl; - AVFVideoRendererControl *m_videoOutput; + AVFCameraRendererControl *m_videoOutput; AVFCameraMetaDataControl *m_metaDataControl; AVFMediaRecorderControl *m_recorderControl; AVFImageCaptureControl *m_imageCaptureControl; diff --git a/src/plugins/avfoundation/camera/avfcameraservice.mm b/src/plugins/avfoundation/camera/avfcameraservice.mm index 77a145ba3..cdd983a22 100644 --- a/src/plugins/avfoundation/camera/avfcameraservice.mm +++ b/src/plugins/avfoundation/camera/avfcameraservice.mm @@ -46,12 +46,12 @@ #include "avfcameracontrol.h" #include "avfcamerainfocontrol.h" #include "avfcamerasession.h" -#include "avfvideodevicecontrol.h" +#include "avfcameradevicecontrol.h" #include "avfaudioinputselectorcontrol.h" #include "avfcamerametadatacontrol.h" #include "avfmediarecordercontrol.h" #include "avfimagecapturecontrol.h" -#include "avfvideorenderercontrol.h" +#include "avfcamerarenderercontrol.h" #include "avfmediarecordercontrol.h" #include "avfimagecapturecontrol.h" #include "avfmediavideoprobecontrol.h" @@ -68,7 +68,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_videoDeviceControl = new AVFCameraDeviceControl(this); m_audioInputSelectorControl = new AVFAudioInputSelectorControl(this); m_metaDataControl = new AVFCameraMetaDataControl(this); @@ -128,7 +128,7 @@ QMediaControl *AVFCameraService::requestControl(const char *name) } if (!m_videoOutput) { if (qstrcmp(name, QVideoRendererControl_iid) == 0) - m_videoOutput = new AVFVideoRendererControl(this); + m_videoOutput = new AVFCameraRendererControl(this); if (m_videoOutput) { m_session->setVideoOutput(m_videoOutput); diff --git a/src/plugins/avfoundation/camera/avfcamerasession.h b/src/plugins/avfoundation/camera/avfcamerasession.h index ec0c746c4..97577f416 100644 --- a/src/plugins/avfoundation/camera/avfcamerasession.h +++ b/src/plugins/avfoundation/camera/avfcamerasession.h @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE class AVFCameraControl; class AVFCameraService; -class AVFVideoRendererControl; +class AVFCameraRendererControl; class AVFMediaVideoProbeControl; struct AVFCameraInfo @@ -70,7 +70,7 @@ public: static const QList &availableCameraDevices(); static AVFCameraInfo cameraDeviceInfo(const QByteArray &device); - void setVideoOutput(AVFVideoRendererControl *output); + void setVideoOutput(AVFCameraRendererControl *output); AVCaptureSession *captureSession() const { return m_captureSession; } AVCaptureDevice *videoCaptureDevice() const; @@ -104,7 +104,7 @@ private: static QMap m_cameraInfo; AVFCameraService *m_service; - AVFVideoRendererControl *m_videoOutput; + AVFCameraRendererControl *m_videoOutput; QCamera::State m_state; bool m_active; diff --git a/src/plugins/avfoundation/camera/avfcamerasession.mm b/src/plugins/avfoundation/camera/avfcamerasession.mm index 3c58c25d6..c1b896cf1 100644 --- a/src/plugins/avfoundation/camera/avfcamerasession.mm +++ b/src/plugins/avfoundation/camera/avfcamerasession.mm @@ -43,8 +43,8 @@ #include "avfcamerasession.h" #include "avfcameraservice.h" #include "avfcameracontrol.h" -#include "avfvideorenderercontrol.h" -#include "avfvideodevicecontrol.h" +#include "avfcamerarenderercontrol.h" +#include "avfcameradevicecontrol.h" #include "avfaudioinputselectorcontrol.h" #include "avfmediavideoprobecontrol.h" @@ -241,7 +241,7 @@ void AVFCameraSession::updateCameraDevices() } } -void AVFCameraSession::setVideoOutput(AVFVideoRendererControl *output) +void AVFCameraSession::setVideoOutput(AVFCameraRendererControl *output) { m_videoOutput = output; if (output) diff --git a/src/plugins/avfoundation/camera/avfvideodevicecontrol.h b/src/plugins/avfoundation/camera/avfvideodevicecontrol.h deleted file mode 100644 index c46d1bd67..000000000 --- a/src/plugins/avfoundation/camera/avfvideodevicecontrol.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** 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:LGPL21$ -** 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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** 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. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef AVFVIDEODEVICECONTROL_H -#define AVFVIDEODEVICECONTROL_H - -#include -#include - -#import - -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; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/avfoundation/camera/avfvideodevicecontrol.mm b/src/plugins/avfoundation/camera/avfvideodevicecontrol.mm deleted file mode 100644 index 03736c395..000000000 --- a/src/plugins/avfoundation/camera/avfvideodevicecontrol.mm +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** 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 "avfcameradebug.h" -#include "avfvideodevicecontrol.h" -#include "avfcameraservice.h" -#include "avfcamerasession.h" - -QT_USE_NAMESPACE - -AVFVideoDeviceControl::AVFVideoDeviceControl(AVFCameraService *service, QObject *parent) - : QVideoDeviceSelectorControl(parent) - , m_service(service) - , m_selectedDevice(0) - , m_dirty(true) -{ -} - -AVFVideoDeviceControl::~AVFVideoDeviceControl() -{ -} - -int AVFVideoDeviceControl::deviceCount() const -{ - return AVFCameraSession::availableCameraDevices().count(); -} - -QString AVFVideoDeviceControl::deviceName(int index) const -{ - const QList &devices = AVFCameraSession::availableCameraDevices(); - if (index < 0 || index >= devices.count()) - return QString(); - - return QString::fromUtf8(devices.at(index)); -} - -QString AVFVideoDeviceControl::deviceDescription(int index) const -{ - const QList &devices = AVFCameraSession::availableCameraDevices(); - if (index < 0 || index >= devices.count()) - return QString(); - - return AVFCameraSession::cameraDeviceInfo(devices.at(index)).description; -} - -int AVFVideoDeviceControl::defaultDevice() const -{ - return AVFCameraSession::availableCameraDevices().indexOf(AVFCameraSession::defaultCameraDevice()); -} - -int AVFVideoDeviceControl::selectedDevice() const -{ - return m_selectedDevice; -} - -void AVFVideoDeviceControl::setSelectedDevice(int index) -{ - if (index >= 0 && - index < deviceCount() && - index != m_selectedDevice) { - m_dirty = true; - m_selectedDevice = index; - Q_EMIT selectedDeviceChanged(index); - Q_EMIT selectedDeviceChanged(deviceName(index)); - } -} - -AVCaptureDevice *AVFVideoDeviceControl::createCaptureDevice() -{ - m_dirty = false; - AVCaptureDevice *device = 0; - - QString deviceId = deviceName(m_selectedDevice); - if (!deviceId.isEmpty()) { - device = [AVCaptureDevice deviceWithUniqueID: - [NSString stringWithUTF8String: - deviceId.toUtf8().constData()]]; - } - - if (!device) - device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; - - return device; -} - -#include "moc_avfvideodevicecontrol.cpp" diff --git a/src/plugins/avfoundation/camera/avfvideorenderercontrol.h b/src/plugins/avfoundation/camera/avfvideorenderercontrol.h deleted file mode 100644 index 0f4f6ba70..000000000 --- a/src/plugins/avfoundation/camera/avfvideorenderercontrol.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** 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:LGPL21$ -** 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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** 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. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef AVFVIDEORENDERERCONTROL_H -#define AVFVIDEORENDERERCONTROL_H - -#include -#include -#include - -#import - -@class AVFCaptureFramesDelegate; - -QT_BEGIN_NAMESPACE - -class AVFCameraSession; -class AVFCameraService; -class AVFVideoRendererControl; - -class AVFVideoRendererControl : public QVideoRendererControl -{ -Q_OBJECT -public: - AVFVideoRendererControl(QObject *parent = 0); - ~AVFVideoRendererControl(); - - QAbstractVideoSurface *surface() const; - void setSurface(QAbstractVideoSurface *surface); - - void configureAVCaptureSession(AVFCameraSession *cameraSession); - void syncHandleViewfinderFrame(const QVideoFrame &frame); - -Q_SIGNALS: - void surfaceChanged(QAbstractVideoSurface *surface); - -private Q_SLOTS: - void handleViewfinderFrame(); - void updateCaptureConnection(); - -private: - QAbstractVideoSurface *m_surface; - AVFCaptureFramesDelegate *m_viewfinderFramesDelegate; - AVFCameraSession *m_cameraSession; - AVCaptureVideoDataOutput *m_videoDataOutput; - - bool m_needsHorizontalMirroring; - - QVideoFrame m_lastViewfinderFrame; - QMutex m_vfMutex; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/avfoundation/camera/avfvideorenderercontrol.mm b/src/plugins/avfoundation/camera/avfvideorenderercontrol.mm deleted file mode 100644 index 369ed473e..000000000 --- a/src/plugins/avfoundation/camera/avfvideorenderercontrol.mm +++ /dev/null @@ -1,276 +0,0 @@ -/**************************************************************************** -** -** 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 "avfvideorenderercontrol.h" -#include "avfcamerasession.h" -#include "avfcameraservice.h" -#include "avfcameradebug.h" - -#include -#include -#include - -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 -{ -@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_needsHorizontalMirroring(false) -{ - m_viewfinderFramesDelegate = [[AVFCaptureFramesDelegate alloc] initWithRenderer:this]; -} - -AVFVideoRendererControl::~AVFVideoRendererControl() -{ - [m_cameraSession->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(AVFCameraSession *cameraSession) -{ - m_cameraSession = cameraSession; - connect(m_cameraSession, SIGNAL(readyToConfigureConnections()), - this, SLOT(updateCaptureConnection())); - - m_needsHorizontalMirroring = false; - - 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_cameraSession->captureSession() addOutput:m_videoDataOutput]; -} - -void AVFVideoRendererControl::updateCaptureConnection() -{ - AVCaptureConnection *connection = [m_videoDataOutput connectionWithMediaType:AVMediaTypeVideo]; - if (connection == nil || !m_cameraSession->videoCaptureDevice()) - return; - - // Frames of front-facing cameras should be mirrored horizontally (it's the default when using - // AVCaptureVideoPreviewLayer but not with AVCaptureVideoDataOutput) - if (connection.isVideoMirroringSupported) - connection.videoMirrored = m_cameraSession->videoCaptureDevice().position == AVCaptureDevicePositionFront; - - // If the connection does't support mirroring, we'll have to do it ourselves - m_needsHorizontalMirroring = !connection.isVideoMirrored - && m_cameraSession->videoCaptureDevice().position == AVCaptureDevicePositionFront; -} - -//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; - - if (m_needsHorizontalMirroring) { - m_lastViewfinderFrame.map(QAbstractVideoBuffer::ReadOnly); - - // no deep copy - QImage image(m_lastViewfinderFrame.bits(), - m_lastViewfinderFrame.size().width(), - m_lastViewfinderFrame.size().height(), - m_lastViewfinderFrame.bytesPerLine(), - QImage::Format_RGB32); - - QImage mirrored = image.mirrored(true, false); - - m_lastViewfinderFrame.unmap(); - m_lastViewfinderFrame = QVideoFrame(mirrored); - } - if (m_cameraSession && m_lastViewfinderFrame.isValid()) - m_cameraSession->onCameraFrameFetched(m_lastViewfinderFrame); -} - -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" diff --git a/src/plugins/avfoundation/camera/camera.pro b/src/plugins/avfoundation/camera/camera.pro index 2cd3d56a5..0ceeb19dc 100644 --- a/src/plugins/avfoundation/camera/camera.pro +++ b/src/plugins/avfoundation/camera/camera.pro @@ -25,30 +25,32 @@ 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 \ avfcamerainfocontrol.h \ - avfmediavideoprobecontrol.h + avfmediavideoprobecontrol.h \ + avfcamerainfocontrol.h \ + avfcamerarenderercontrol.h \ + avfcameradevicecontrol.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 \ avfcamerainfocontrol.mm \ - avfmediavideoprobecontrol.mm + avfmediavideoprobecontrol.mm \ + avfcamerainfocontrol.mm \ + avfcameradevicecontrol.mm \ + avfcamerarenderercontrol.mm -- cgit v1.2.3