diff options
Diffstat (limited to 'src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm')
-rw-r--r-- | src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm | 414 |
1 files changed, 0 insertions, 414 deletions
diff --git a/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm b/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm deleted file mode 100644 index 33064827d..000000000 --- a/src/plugins/avfoundation/camera/avfmediarecordercontrol_ios.mm +++ /dev/null @@ -1,414 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: https://www.qt.io/licensing/ -** -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "avfmediarecordercontrol_ios.h" -#include "avfcamerarenderercontrol.h" -#include "avfcamerasession.h" -#include "avfcameracontrol.h" -#include "avfcameraservice.h" -#include "avfcameradebug.h" -#include "avfaudioencodersettingscontrol.h" -#include "avfvideoencodersettingscontrol.h" -#include "avfmediacontainercontrol.h" -#include "avfcamerautility.h" - -#include <QtCore/qmath.h> -#include <QtCore/qdebug.h> - -QT_USE_NAMESPACE - -namespace { - -bool qt_is_writable_file_URL(NSURL *fileURL) -{ - Q_ASSERT(fileURL); - - if (![fileURL isFileURL]) - return false; - - if (NSString *path = [[fileURL path] stringByExpandingTildeInPath]) { - return [[NSFileManager defaultManager] - isWritableFileAtPath:[path stringByDeletingLastPathComponent]]; - } - - return false; -} - -bool qt_file_exists(NSURL *fileURL) -{ - Q_ASSERT(fileURL); - - if (NSString *path = [[fileURL path] stringByExpandingTildeInPath]) - return [[NSFileManager defaultManager] fileExistsAtPath:path]; - - return false; -} - -} - -AVFMediaRecorderControlIOS::AVFMediaRecorderControlIOS(AVFCameraService *service, QObject *parent) - : QMediaRecorderControl(parent) - , m_service(service) - , m_state(QMediaRecorder::StoppedState) - , m_lastStatus(QMediaRecorder::UnloadedStatus) - , m_audioSettings(nil) - , m_videoSettings(nil) -{ - Q_ASSERT(service); - - m_writer.reset([[QT_MANGLE_NAMESPACE(AVFMediaAssetWriter) alloc] initWithDelegate:this]); - if (!m_writer) { - qDebugCamera() << Q_FUNC_INFO << "failed to create an asset writer"; - return; - } - - AVFCameraControl *cameraControl = m_service->cameraControl(); - if (!cameraControl) { - qDebugCamera() << Q_FUNC_INFO << "camera control is nil"; - return; - } - - connect(cameraControl, SIGNAL(captureModeChanged(QCamera::CaptureModes)), - SLOT(captureModeChanged(QCamera::CaptureModes))); - connect(cameraControl, SIGNAL(statusChanged(QCamera::Status)), - SLOT(cameraStatusChanged(QCamera::Status))); -} - -AVFMediaRecorderControlIOS::~AVFMediaRecorderControlIOS() -{ - [m_writer abort]; - - if (m_audioSettings) - [m_audioSettings release]; - if (m_videoSettings) - [m_videoSettings release]; -} - -QUrl AVFMediaRecorderControlIOS::outputLocation() const -{ - return m_outputLocation; -} - -bool AVFMediaRecorderControlIOS::setOutputLocation(const QUrl &location) -{ - m_outputLocation = location; - return location.scheme() == QLatin1String("file") || location.scheme().isEmpty(); -} - -QMediaRecorder::State AVFMediaRecorderControlIOS::state() const -{ - return m_state; -} - -QMediaRecorder::Status AVFMediaRecorderControlIOS::status() const -{ - return m_lastStatus; -} - -qint64 AVFMediaRecorderControlIOS::duration() const -{ - return m_writer.data().durationInMs; -} - -bool AVFMediaRecorderControlIOS::isMuted() const -{ - return false; -} - -qreal AVFMediaRecorderControlIOS::volume() const -{ - return 1.; -} - -void AVFMediaRecorderControlIOS::applySettings() -{ - AVFCameraSession *session = m_service->session(); - if (!session) - return; - - if (m_state != QMediaRecorder::StoppedState - || (session->state() != QCamera::ActiveState && session->state() != QCamera::LoadedState) - || !m_service->cameraControl()->captureMode().testFlag(QCamera::CaptureVideo)) { - return; - } - - // audio settings - m_audioSettings = m_service->audioEncoderSettingsControl()->applySettings(); - if (m_audioSettings) - [m_audioSettings retain]; - - // video settings - AVCaptureConnection *conn = [m_service->videoOutput()->videoDataOutput() connectionWithMediaType:AVMediaTypeVideo]; - m_videoSettings = m_service->videoEncoderSettingsControl()->applySettings(conn); - if (m_videoSettings) - [m_videoSettings retain]; -} - -void AVFMediaRecorderControlIOS::unapplySettings() -{ - m_service->audioEncoderSettingsControl()->unapplySettings(); - - AVCaptureConnection *conn = [m_service->videoOutput()->videoDataOutput() connectionWithMediaType:AVMediaTypeVideo]; - m_service->videoEncoderSettingsControl()->unapplySettings(conn); - - if (m_audioSettings) { - [m_audioSettings release]; - m_audioSettings = nil; - } - if (m_videoSettings) { - [m_videoSettings release]; - m_videoSettings = nil; - } -} - -void AVFMediaRecorderControlIOS::setState(QMediaRecorder::State state) -{ - Q_ASSERT(m_service->session() - && m_service->session()->captureSession()); - - if (!m_writer) { - qDebugCamera() << Q_FUNC_INFO << "Invalid recorder"; - return; - } - - if (state == m_state) - return; - - switch (state) { - case QMediaRecorder::RecordingState: - { - AVFCameraControl *cameraControl = m_service->cameraControl(); - Q_ASSERT(cameraControl); - - if (!(cameraControl->captureMode() & QCamera::CaptureVideo)) { - qDebugCamera() << Q_FUNC_INFO << "wrong capture mode, CaptureVideo expected"; - Q_EMIT error(QMediaRecorder::ResourceError, tr("Failed to start recording")); - return; - } - - if (cameraControl->status() != QCamera::ActiveStatus) { - qDebugCamera() << Q_FUNC_INFO << "can not start record while camera is not active"; - Q_EMIT error(QMediaRecorder::ResourceError, tr("Failed to start recording")); - return; - } - - const QString path(m_outputLocation.scheme() == QLatin1String("file") ? - m_outputLocation.path() : m_outputLocation.toString()); - const QUrl fileURL(QUrl::fromLocalFile(m_storageLocation.generateFileName(path, QCamera::CaptureVideo, - QLatin1String("clip_"), - m_service->mediaContainerControl()->containerFormat()))); - - NSURL *nsFileURL = fileURL.toNSURL(); - if (!nsFileURL) { - qWarning() << Q_FUNC_INFO << "invalid output URL:" << fileURL; - Q_EMIT error(QMediaRecorder::ResourceError, tr("Invalid output file URL")); - return; - } - if (!qt_is_writable_file_URL(nsFileURL)) { - qWarning() << Q_FUNC_INFO << "invalid output URL:" << fileURL - << "(the location is not writable)"; - Q_EMIT error(QMediaRecorder::ResourceError, tr("Non-writeable file location")); - return; - } - if (qt_file_exists(nsFileURL)) { - // We test for/handle this error here since AWAssetWriter will raise an - // Objective-C exception, which is not good at all. - qWarning() << Q_FUNC_INFO << "invalid output URL:" << fileURL - << "(file already exists)"; - Q_EMIT error(QMediaRecorder::ResourceError, tr("File already exists")); - return; - } - - AVCaptureSession *session = m_service->session()->captureSession(); - // We stop session now so that no more frames for renderer's queue - // generated, will restart in assetWriterStarted. - [session stopRunning]; - - applySettings(); - - // Make sure the video is recorded in device orientation. - // The top of the video will match the side of the device which is on top - // when recording starts (regardless of the UI orientation). - AVFCameraInfo cameraInfo = m_service->session()->activeCameraInfo(); - int screenOrientation = 360 - m_orientationHandler.currentOrientation(); - float rotation = 0; - if (cameraInfo.position == QCamera::FrontFace) - rotation = (screenOrientation + cameraInfo.orientation) % 360; - else - rotation = (screenOrientation + (360 - cameraInfo.orientation)) % 360; - - if ([m_writer setupWithFileURL:nsFileURL - cameraService:m_service - audioSettings:m_audioSettings - videoSettings:m_videoSettings - transform:CGAffineTransformMakeRotation(qDegreesToRadians(rotation))]) { - - m_state = QMediaRecorder::RecordingState; - m_lastStatus = QMediaRecorder::StartingStatus; - - Q_EMIT actualLocationChanged(fileURL); - Q_EMIT stateChanged(m_state); - Q_EMIT statusChanged(m_lastStatus); - - // Apple recommends to call startRunning and do all - // setup on a special queue, and that's what we had - // initially (dispatch_async to writerQueue). Unfortunately, - // writer's queue is not the only queue/thread that can - // access/modify the session, and as a result we have - // all possible data/race-conditions with Obj-C exceptions - // at best and something worse in general. - // Now we try to only modify session on the same thread. - [m_writer start]; - } else { - [session startRunning]; - Q_EMIT error(QMediaRecorder::FormatError, tr("Failed to start recording")); - } - } break; - case QMediaRecorder::PausedState: - { - Q_EMIT error(QMediaRecorder::FormatError, tr("Recording pause not supported")); - return; - } break; - case QMediaRecorder::StoppedState: - { - // Do not check the camera status, we can stop if we started. - stopWriter(); - } - } -} - -void AVFMediaRecorderControlIOS::setMuted(bool muted) -{ - Q_UNUSED(muted); - qDebugCamera() << Q_FUNC_INFO << "not implemented"; -} - -void AVFMediaRecorderControlIOS::setVolume(qreal volume) -{ - Q_UNUSED(volume); - qDebugCamera() << Q_FUNC_INFO << "not implemented"; -} - -void AVFMediaRecorderControlIOS::assetWriterStarted() -{ - m_lastStatus = QMediaRecorder::RecordingStatus; - Q_EMIT statusChanged(QMediaRecorder::RecordingStatus); -} - -void AVFMediaRecorderControlIOS::assetWriterFinished() -{ - AVFCameraControl *cameraControl = m_service->cameraControl(); - Q_ASSERT(cameraControl); - - const QMediaRecorder::Status lastStatus = m_lastStatus; - const QMediaRecorder::State lastState = m_state; - if (cameraControl->captureMode() & QCamera::CaptureVideo) - m_lastStatus = QMediaRecorder::LoadedStatus; - else - m_lastStatus = QMediaRecorder::UnloadedStatus; - - unapplySettings(); - - m_service->videoOutput()->resetCaptureDelegate(); - [m_service->session()->captureSession() startRunning]; - m_state = QMediaRecorder::StoppedState; - if (m_lastStatus != lastStatus) - Q_EMIT statusChanged(m_lastStatus); - if (m_state != lastState) - Q_EMIT stateChanged(m_state); -} - -void AVFMediaRecorderControlIOS::captureModeChanged(QCamera::CaptureModes newMode) -{ - AVFCameraControl *cameraControl = m_service->cameraControl(); - Q_ASSERT(cameraControl); - - const QMediaRecorder::Status lastStatus = m_lastStatus; - - if (newMode & QCamera::CaptureVideo) { - if (cameraControl->status() == QCamera::ActiveStatus) - m_lastStatus = QMediaRecorder::LoadedStatus; - } else { - if (m_lastStatus == QMediaRecorder::RecordingStatus) - return stopWriter(); - else - m_lastStatus = QMediaRecorder::UnloadedStatus; - } - - if (m_lastStatus != lastStatus) - Q_EMIT statusChanged(m_lastStatus); -} - -void AVFMediaRecorderControlIOS::cameraStatusChanged(QCamera::Status newStatus) -{ - AVFCameraControl *cameraControl = m_service->cameraControl(); - Q_ASSERT(cameraControl); - - const QMediaRecorder::Status lastStatus = m_lastStatus; - const bool isCapture = cameraControl->captureMode() & QCamera::CaptureVideo; - if (newStatus == QCamera::StartingStatus) { - if (isCapture && m_lastStatus == QMediaRecorder::UnloadedStatus) - m_lastStatus = QMediaRecorder::LoadingStatus; - } else if (newStatus == QCamera::ActiveStatus) { - if (isCapture && m_lastStatus == QMediaRecorder::LoadingStatus) - m_lastStatus = QMediaRecorder::LoadedStatus; - } else { - if (m_lastStatus == QMediaRecorder::RecordingStatus) - return stopWriter(); - if (newStatus == QCamera::UnloadedStatus) - m_lastStatus = QMediaRecorder::UnloadedStatus; - } - - if (lastStatus != m_lastStatus) - Q_EMIT statusChanged(m_lastStatus); -} - -void AVFMediaRecorderControlIOS::stopWriter() -{ - if (m_lastStatus == QMediaRecorder::RecordingStatus) { - m_lastStatus = QMediaRecorder::FinalizingStatus; - - Q_EMIT statusChanged(m_lastStatus); - - [m_writer stop]; - } -} - -#include "moc_avfmediarecordercontrol_ios.cpp" |