diff options
Diffstat (limited to 'src/plugins/multimedia/android/mediacapture/qandroidcamerasession.cpp')
-rw-r--r-- | src/plugins/multimedia/android/mediacapture/qandroidcamerasession.cpp | 128 |
1 files changed, 58 insertions, 70 deletions
diff --git a/src/plugins/multimedia/android/mediacapture/qandroidcamerasession.cpp b/src/plugins/multimedia/android/mediacapture/qandroidcamerasession.cpp index 83ac04545..f7dd1c653 100644 --- a/src/plugins/multimedia/android/mediacapture/qandroidcamerasession.cpp +++ b/src/plugins/multimedia/android/mediacapture/qandroidcamerasession.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Copyright (C) 2016 Ruslan Baratov -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2016 Ruslan Baratov +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qandroidcamerasession_p.h" @@ -53,6 +17,7 @@ #include <qdebug.h> #include <qvideoframe.h> #include <private/qplatformimagecapture_p.h> +#include <private/qplatformvideosink_p.h> #include <private/qmemoryvideobuffer_p.h> #include <private/qcameradevice_p.h> #include <private/qmediastoragelocation_p.h> @@ -89,6 +54,8 @@ QAndroidCameraSession::QAndroidCameraSession(QObject *parent) QAndroidCameraSession::~QAndroidCameraSession() { + if (m_sink) + disconnect(m_retryPreviewConnection); close(); } @@ -269,6 +236,8 @@ void QAndroidCameraSession::applyResolution(const QSize &captureSize, bool resta // -- adjust resolution QSize adjustedViewfinderResolution; + const QList<QSize> previewSizes = m_camera->getSupportedPreviewSizes(); + const bool validCaptureSize = captureSize.width() > 0 && captureSize.height() > 0; if (validCaptureSize && m_camera->getPreferredPreviewSizeForVideo().isEmpty()) { @@ -280,8 +249,6 @@ void QAndroidCameraSession::applyResolution(const QSize &captureSize, bool resta if (validCaptureSize) captureAspectRatio = qreal(captureSize.width()) / qreal(captureSize.height()); - const QList<QSize> previewSizes = m_camera->getSupportedPreviewSizes(); - if (validCaptureSize) { // search for viewfinder resolution with the same aspect ratio qreal minAspectDiff = 1; @@ -319,31 +286,37 @@ void QAndroidCameraSession::applyResolution(const QSize &captureSize, bool resta // -- adjust FPS - AndroidCamera::FpsRange adjustedFps = m_requestedFpsRange;; + AndroidCamera::FpsRange adjustedFps = m_requestedFpsRange; if (adjustedFps.min == 0 || adjustedFps.max == 0) adjustedFps = currentFpsRange; // -- Set values on camera // fix the resolution of output based on the orientation - QSize outputResolution = adjustedViewfinderResolution; + QSize cameraOutputResolution = adjustedViewfinderResolution; + QSize videoOutputResolution = adjustedViewfinderResolution; + QSize currentVideoOutputResolution = m_videoOutput ? m_videoOutput->getVideoSize() : QSize(0, 0); const int rotation = currentCameraRotation(); - if (rotation == 90 || rotation == 270) - outputResolution.transpose(); + // only transpose if it's valid for the preview + if (rotation == 90 || rotation == 270) { + videoOutputResolution.transpose(); + if (previewSizes.contains(cameraOutputResolution.transposed())) + cameraOutputResolution.transpose(); + } - if (currentViewfinderResolution != outputResolution + if (currentViewfinderResolution != cameraOutputResolution + || (m_videoOutput && currentVideoOutputResolution != videoOutputResolution) || currentPreviewFormat != adjustedPreviewFormat || currentFpsRange.min != adjustedFps.min || currentFpsRange.max != adjustedFps.max) { - if (m_videoOutput) { - m_videoOutput->setVideoSize(outputResolution); + m_videoOutput->setVideoSize(videoOutputResolution); } // if preview is started, we have to stop it first before changing its size if (m_previewStarted && restartPreview) m_camera->stopPreview(); - m_camera->setPreviewSize(outputResolution); + m_camera->setPreviewSize(cameraOutputResolution); m_camera->setPreviewFormat(adjustedPreviewFormat); m_camera->setPreviewFpsRange(adjustedFps); @@ -444,7 +417,6 @@ void QAndroidCameraSession::stopPreview() if (m_videoOutput) { m_videoOutput->stop(); - m_videoOutput->reset(); } m_previewStarted = false; } @@ -612,7 +584,6 @@ int QAndroidCameraSession::captureImage() m_currentImageCaptureId = newImageCaptureId; - applyImageSettings(); applyResolution(m_actualImageSettings.resolution()); m_camera->takePicture(); @@ -689,12 +660,16 @@ void QAndroidCameraSession::onNewPreviewFrame(const QVideoFrame &frame) m_videoFrameCallbackMutex.unlock(); } -void QAndroidCameraSession::onCameraPictureCaptured(const QVideoFrame &frame) +void QAndroidCameraSession::onCameraPictureCaptured(const QByteArray &bytes, + QVideoFrameFormat::PixelFormat format, QSize size,int bytesPerLine) { - // Loading and saving the captured image can be slow, do it in a separate thread - (void)QtConcurrent::run(&QAndroidCameraSession::processCapturedImage, this, - m_currentImageCaptureId, frame, m_imageCaptureToBuffer, - m_currentImageCaptureFileName); + if (m_imageCaptureToBuffer) { + processCapturedImageToBuffer(m_currentImageCaptureId, bytes, format, size, bytesPerLine); + } else { + // Loading and saving the captured image can be slow, do it in a separate thread + (void)QtConcurrent::run(&QAndroidCameraSession::processCapturedImage, this, + m_currentImageCaptureId, bytes, m_currentImageCaptureFileName); + } // Preview needs to be restarted after taking a picture if (m_camera) @@ -732,37 +707,37 @@ void QAndroidCameraSession::onCameraPreviewStopped() setReadyForCapture(false); } -void QAndroidCameraSession::processCapturedImage(int id, const QVideoFrame &frame, - bool captureToBuffer, const QString &fileName) +void QAndroidCameraSession::processCapturedImage(int id, const QByteArray &bytes, const QString &fileName) { - if (captureToBuffer) { - emit imageAvailable(id, frame); - return; - } - const QString actualFileName = QMediaStorageLocation::generateFileName( fileName, QStandardPaths::PicturesLocation, QLatin1String("jpg")); - QImageWriter writer(actualFileName); - - if (!writer.canWrite()) { + QFile writer(actualFileName); + if (!writer.open(QIODeviceBase::WriteOnly)) { const QString errorMessage = tr("File is not available: %1").arg(writer.errorString()); emit imageCaptureError(id, QImageCapture::Error::ResourceError, errorMessage); return; } - const bool written = writer.write(frame.toImage()); - if (!written) { + if (writer.write(bytes) < 0) { const QString errorMessage = tr("Could not save to file: %1").arg(writer.errorString()); emit imageCaptureError(id, QImageCapture::Error::ResourceError, errorMessage); return; } + writer.close(); if (fileName.isEmpty() || QFileInfo(fileName).isRelative()) AndroidMultimediaUtils::registerMediaFile(actualFileName); emit imageSaved(id, actualFileName); } +void QAndroidCameraSession::processCapturedImageToBuffer(int id, const QByteArray &bytes, + QVideoFrameFormat::PixelFormat format, QSize size, int bytesPerLine) +{ + QVideoFrame frame(new QMemoryVideoBuffer(bytes, bytesPerLine), QVideoFrameFormat(size, format)); + emit imageAvailable(id, frame); +} + void QAndroidCameraSession::onVideoOutputReady(bool ready) { if (ready && m_active) @@ -801,17 +776,30 @@ void QAndroidCameraSession::setVideoSink(QVideoSink *sink) if (m_sink == sink) return; + if (m_sink) + disconnect(m_retryPreviewConnection); + m_sink = sink; + if (m_sink) + m_retryPreviewConnection = + connect(m_sink->platformVideoSink(), &QPlatformVideoSink::rhiChanged, this, [&]() + { + if (m_active) { + setActive(false); + setActive(true); + } + }, Qt::DirectConnection); if (m_sink) { delete m_textureOutput; m_textureOutput = nullptr; - m_textureOutput = new QAndroidTextureVideoOutput(this); - m_textureOutput->setSurface(m_sink); + m_textureOutput = new QAndroidTextureVideoOutput(m_sink, this); } setVideoOutput(m_textureOutput); } QT_END_NAMESPACE + +#include "moc_qandroidcamerasession_p.cpp" |