diff options
Diffstat (limited to 'src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp')
-rw-r--r-- | src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp | 794 |
1 files changed, 0 insertions, 794 deletions
diff --git a/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp b/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp deleted file mode 100644 index 38b819352..000000000 --- a/src/multimedia/platform/android/mediacapture/qandroidcamerasession.cpp +++ /dev/null @@ -1,794 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "qandroidcamerasession_p.h" - -#include "androidcamera_p.h" -#include "androidmultimediautils_p.h" -#include "qandroidvideooutput_p.h" -#include "qandroidmultimediautils_p.h" -#include <qvideosink.h> -#include <QtConcurrent/qtconcurrentrun.h> -#include <qfile.h> -#include <qguiapplication.h> -#include <qscreen.h> -#include <qdebug.h> -#include <qvideoframe.h> -#include <private/qplatformimagecapture_p.h> -#include <private/qmemoryvideobuffer_p.h> -#include <private/qcameradevice_p.h> -#include <private/qmediastoragelocation_p.h> - -QT_BEGIN_NAMESPACE - -Q_GLOBAL_STATIC(QList<QCameraDevice>, g_availableCameras) - -QAndroidCameraSession::QAndroidCameraSession(QObject *parent) - : QObject(parent) - , m_selectedCamera(0) - , m_camera(0) - , m_videoOutput(0) - , m_savedState(-1) - , m_previewStarted(false) - , m_lastImageCaptureId(0) - , m_readyForCapture(false) - , m_currentImageCaptureId(-1) - , m_previewCallback(0) - , m_keepActive(false) -{ - if (qApp) { - connect(qApp, &QGuiApplication::applicationStateChanged, - this, &QAndroidCameraSession::onApplicationStateChanged); - - auto screen = qApp->primaryScreen(); - if (screen) { - connect(screen, &QScreen::orientationChanged, this, - &QAndroidCameraSession::updateOrientation); - enableRotation(); - } - } -} - -QAndroidCameraSession::~QAndroidCameraSession() -{ - close(); -} - -//void QAndroidCameraSession::setCaptureMode(QCamera::CaptureModes mode) -//{ -// if (m_captureMode == mode || !isCaptureModeSupported(mode)) -// return; - -// m_captureMode = mode; -// emit captureModeChanged(m_captureMode); - -// if (m_previewStarted && m_captureMode.testFlag(QCamera::CaptureStillImage)) -// applyResolution(m_actualImageSettings.resolution()); -//} - -void QAndroidCameraSession::setActive(bool active) -{ - if (m_active == active) - return; - - m_active = active; - - // If the application is inactive, the camera shouldn't be started. Save the desired state - // instead and it will be set when the application becomes active. - if (qApp->applicationState() == Qt::ApplicationActive) - setActiveHelper(active); - else - m_savedState = active; - - emit activeChanged(m_active); -} - -void QAndroidCameraSession::setActiveHelper(bool active) -{ - if (!active) { - stopPreview(); - close(); - } else { - if (!m_camera && !open()) { - emit error(QCamera::CameraError, QStringLiteral("Failed to open camera")); - return; - } - startPreview(); - } -} - -void QAndroidCameraSession::updateAvailableCameras() -{ - g_availableCameras->clear(); - - const int numCameras = AndroidCamera::getNumberOfCameras(); - for (int i = 0; i < numCameras; ++i) { - QCameraDevicePrivate *info = new QCameraDevicePrivate; - AndroidCamera::getCameraInfo(i, info); - - if (!info->id.isEmpty()) { - AndroidCamera::getSupportedFormats(i, info->videoFormats); - // Add supported picture sizes to the camera info - AndroidCamera *camera = AndroidCamera::open(i); - if (camera) - info->photoResolutions = camera->getSupportedPictureSizes(); - delete camera; - g_availableCameras->append(info->create()); - } - } -} - -const QList<QCameraDevice> &QAndroidCameraSession::availableCameras() -{ - if (g_availableCameras->isEmpty()) - updateAvailableCameras(); - - return *g_availableCameras; -} - -bool QAndroidCameraSession::open() -{ - close(); - - m_camera = AndroidCamera::open(m_selectedCamera); - - if (m_camera) { - connect(m_camera, &AndroidCamera::pictureExposed, - this, &QAndroidCameraSession::onCameraPictureExposed); - connect(m_camera, &AndroidCamera::lastPreviewFrameFetched, - this, &QAndroidCameraSession::onLastPreviewFrameFetched, - Qt::DirectConnection); - connect(m_camera, &AndroidCamera::newPreviewFrame, - this, &QAndroidCameraSession::onNewPreviewFrame, - Qt::DirectConnection); - connect(m_camera, &AndroidCamera::pictureCaptured, - this, &QAndroidCameraSession::onCameraPictureCaptured); - connect(m_camera, &AndroidCamera::previewStarted, - this, &QAndroidCameraSession::onCameraPreviewStarted); - connect(m_camera, &AndroidCamera::previewStopped, - this, &QAndroidCameraSession::onCameraPreviewStopped); - connect(m_camera, &AndroidCamera::previewFailedToStart, - this, &QAndroidCameraSession::onCameraPreviewFailedToStart); - connect(m_camera, &AndroidCamera::takePictureFailed, - this, &QAndroidCameraSession::onCameraTakePictureFailed); - - if (m_camera->getPreviewFormat() != AndroidCamera::NV21) - m_camera->setPreviewFormat(AndroidCamera::NV21); - - m_camera->notifyNewFrames(m_previewCallback); - - emit opened(); - setActive(true); - } - - return m_camera != 0; -} - -void QAndroidCameraSession::close() -{ - if (!m_camera) - return; - - stopPreview(); - - m_readyForCapture = false; - m_currentImageCaptureId = -1; - m_currentImageCaptureFileName.clear(); - m_actualImageSettings = m_requestedImageSettings; - - m_camera->release(); - delete m_camera; - m_camera = 0; - - setActive(false); -} - -void QAndroidCameraSession::setVideoOutput(QAndroidVideoOutput *output) -{ - if (m_videoOutput) { - m_videoOutput->stop(); - m_videoOutput->reset(); - } - - if (output) { - m_videoOutput = output; - if (m_videoOutput->isReady()) { - onVideoOutputReady(true); - } else { - connect(m_videoOutput, &QAndroidVideoOutput::readyChanged, - this, &QAndroidCameraSession::onVideoOutputReady); - } - } else { - m_videoOutput = 0; - } -} - -void QAndroidCameraSession::setCameraFormat(const QCameraFormat &format) -{ - m_requestedFpsRange.min = format.minFrameRate(); - m_requestedFpsRange.max = format.maxFrameRate(); - m_requestedPixelFromat = AndroidCamera::AndroidImageFormatFromQtPixelFormat(format.pixelFormat()); - - m_requestedImageSettings.setResolution(format.resolution()); - m_actualImageSettings.setResolution(format.resolution()); - if (m_readyForCapture) - applyResolution(m_actualImageSettings.resolution()); -} - -void QAndroidCameraSession::applyResolution(const QSize &captureSize, bool restartPreview) -{ - if (!m_camera) - return; - - const QSize currentViewfinderResolution = m_camera->previewSize(); - const AndroidCamera::ImageFormat currentPreviewFormat = m_camera->getPreviewFormat(); - const AndroidCamera::FpsRange currentFpsRange = m_camera->getPreviewFpsRange(); - - // -- adjust resolution - QSize adjustedViewfinderResolution; - const bool validCaptureSize = captureSize.width() > 0 && captureSize.height() > 0; - if (validCaptureSize - && m_camera->getPreferredPreviewSizeForVideo().isEmpty()) { - // According to the Android doc, if getPreferredPreviewSizeForVideo() returns null, it means - // the preview size cannot be different from the capture size - adjustedViewfinderResolution = captureSize; - } else { - qreal captureAspectRatio = 0; - 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; - QSize closestResolution; - for (int i = previewSizes.count() - 1; i >= 0; --i) { - const QSize &size = previewSizes.at(i); - const qreal sizeAspect = qreal(size.width()) / size.height(); - if (qFuzzyCompare(captureAspectRatio, sizeAspect)) { - adjustedViewfinderResolution = size; - break; - } else if (minAspectDiff > qAbs(sizeAspect - captureAspectRatio)) { - closestResolution = size; - minAspectDiff = qAbs(sizeAspect - captureAspectRatio); - } - } - if (!adjustedViewfinderResolution.isValid()) { - qWarning("Cannot find a viewfinder resolution matching the capture aspect ratio."); - if (closestResolution.isValid()) { - adjustedViewfinderResolution = closestResolution; - qWarning("Using closest viewfinder resolution."); - } else { - return; - } - } - } else { - adjustedViewfinderResolution = previewSizes.last(); - } - } - - // -- adjust pixel format - - AndroidCamera::ImageFormat adjustedPreviewFormat = m_requestedPixelFromat; - if (adjustedPreviewFormat == AndroidCamera::UnknownImageFormat) - adjustedPreviewFormat = AndroidCamera::NV21; - - // -- adjust FPS - - AndroidCamera::FpsRange adjustedFps = m_requestedFpsRange;; - if (adjustedFps.min == 0 || adjustedFps.max == 0) - adjustedFps = currentFpsRange; - - // -- Set values on camera - - if (currentViewfinderResolution != adjustedViewfinderResolution - || currentPreviewFormat != adjustedPreviewFormat - || currentFpsRange.min != adjustedFps.min - || currentFpsRange.max != adjustedFps.max) { - - if (m_videoOutput) { - // fix the resolution of output based on the orientation - QSize outputResolution = adjustedViewfinderResolution; - const int rotation = currentCameraRotation(); - if (rotation == 90 || rotation == 270) - outputResolution.transpose(); - m_videoOutput->setVideoSize(outputResolution); - } - - // if preview is started, we have to stop it first before changing its size - if (m_previewStarted && restartPreview) - m_camera->stopPreview(); - - m_camera->setPreviewSize(adjustedViewfinderResolution); - m_camera->setPreviewFormat(adjustedPreviewFormat); - m_camera->setPreviewFpsRange(adjustedFps); - - // restart preview - if (m_previewStarted && restartPreview) - m_camera->startPreview(); - } -} - -QList<QSize> QAndroidCameraSession::getSupportedPreviewSizes() const -{ - return m_camera ? m_camera->getSupportedPreviewSizes() : QList<QSize>(); -} - -QList<QVideoFrameFormat::PixelFormat> QAndroidCameraSession::getSupportedPixelFormats() const -{ - QList<QVideoFrameFormat::PixelFormat> formats; - - if (!m_camera) - return formats; - - const QList<AndroidCamera::ImageFormat> nativeFormats = m_camera->getSupportedPreviewFormats(); - - formats.reserve(nativeFormats.size()); - - for (AndroidCamera::ImageFormat nativeFormat : nativeFormats) { - QVideoFrameFormat::PixelFormat format = AndroidCamera::QtPixelFormatFromAndroidImageFormat(nativeFormat); - if (format != QVideoFrameFormat::Format_Invalid) - formats.append(format); - } - - return formats; -} - -QList<AndroidCamera::FpsRange> QAndroidCameraSession::getSupportedPreviewFpsRange() const -{ - return m_camera ? m_camera->getSupportedPreviewFpsRange() : QList<AndroidCamera::FpsRange>(); -} - - -bool QAndroidCameraSession::startPreview() -{ - if (!m_camera || !m_videoOutput) - return false; - - if (m_previewStarted) - return true; - - if (!m_videoOutput->isReady()) - return true; // delay starting until the video output is ready - - Q_ASSERT(m_videoOutput->surfaceTexture() || m_videoOutput->surfaceHolder()); - - if ((m_videoOutput->surfaceTexture() && !m_camera->setPreviewTexture(m_videoOutput->surfaceTexture())) - || (m_videoOutput->surfaceHolder() && !m_camera->setPreviewDisplay(m_videoOutput->surfaceHolder()))) - return false; - - applyImageSettings(); - applyResolution(m_actualImageSettings.resolution()); - - AndroidMultimediaUtils::enableOrientationListener(true); - - updateOrientation(); - - m_camera->startPreview(); - m_previewStarted = true; - - return true; -} - -void QAndroidCameraSession::stopPreview() -{ - if (!m_camera || !m_previewStarted) - return; - - AndroidMultimediaUtils::enableOrientationListener(false); - - m_camera->stopPreview(); - m_camera->setPreviewSize(QSize()); - m_camera->setPreviewTexture(0); - m_camera->setPreviewDisplay(0); - - if (m_videoOutput) { - m_videoOutput->stop(); - m_videoOutput->reset(); - } - m_previewStarted = false; -} - -void QAndroidCameraSession::setImageSettings(const QImageEncoderSettings &settings) -{ - if (m_requestedImageSettings == settings) - return; - - m_requestedImageSettings = m_actualImageSettings = settings; - - applyImageSettings(); - - if (m_readyForCapture) - applyResolution(m_actualImageSettings.resolution()); -} - -void QAndroidCameraSession::enableRotation() -{ - m_rotationEnabled = true; -} - -void QAndroidCameraSession::disableRotation() -{ - m_rotationEnabled = false; -} - -void QAndroidCameraSession::updateOrientation() -{ - if (!m_camera || !m_rotationEnabled) - return; - - m_camera->setDisplayOrientation(currentCameraRotation()); - applyResolution(m_actualImageSettings.resolution()); -} - - -int QAndroidCameraSession::currentCameraRotation() const -{ - if (!m_camera) - return 0; - - auto screen = QGuiApplication::primaryScreen(); - auto screenOrientation = screen->orientation(); - if (screenOrientation == Qt::PrimaryOrientation) - screenOrientation = screen->primaryOrientation(); - - int deviceOrientation = 0; - switch (screenOrientation) { - case Qt::PrimaryOrientation: - case Qt::PortraitOrientation: - break; - case Qt::LandscapeOrientation: - deviceOrientation = 90; - break; - case Qt::InvertedPortraitOrientation: - deviceOrientation = 180; - break; - case Qt::InvertedLandscapeOrientation: - deviceOrientation = 270; - break; - } - - int nativeCameraOrientation = m_camera->getNativeOrientation(); - - int rotation; - // subtract natural camera orientation and physical device orientation - if (m_camera->getFacing() == AndroidCamera::CameraFacingFront) { - rotation = (nativeCameraOrientation + deviceOrientation) % 360; - rotation = (360 - rotation) % 360; // compensate the mirror - } else { // back-facing camera - rotation = (nativeCameraOrientation - deviceOrientation + 360) % 360; - } - return rotation; -} - -void QAndroidCameraSession::setPreviewFormat(AndroidCamera::ImageFormat format) -{ - if (format == AndroidCamera::UnknownImageFormat) - return; - - m_camera->setPreviewFormat(format); -} - -void QAndroidCameraSession::setPreviewCallback(PreviewCallback *callback) -{ - m_videoFrameCallbackMutex.lock(); - m_previewCallback = callback; - if (m_camera) - m_camera->notifyNewFrames(m_previewCallback); - m_videoFrameCallbackMutex.unlock(); -} - -void QAndroidCameraSession::applyImageSettings() -{ - if (!m_camera) - return; - - // only supported format right now. - m_actualImageSettings.setFormat(QImageCapture::JPEG); - - const QSize requestedResolution = m_requestedImageSettings.resolution(); - const QList<QSize> supportedResolutions = m_camera->getSupportedPictureSizes(); - if (!requestedResolution.isValid()) { - // use the highest supported one - m_actualImageSettings.setResolution(supportedResolutions.last()); - } else if (!supportedResolutions.contains(requestedResolution)) { - // if the requested resolution is not supported, find the closest one - int reqPixelCount = requestedResolution.width() * requestedResolution.height(); - QList<int> supportedPixelCounts; - for (int i = 0; i < supportedResolutions.size(); ++i) { - const QSize &s = supportedResolutions.at(i); - supportedPixelCounts.append(s.width() * s.height()); - } - int closestIndex = qt_findClosestValue(supportedPixelCounts, reqPixelCount); - m_actualImageSettings.setResolution(supportedResolutions.at(closestIndex)); - } - m_camera->setPictureSize(m_actualImageSettings.resolution()); - - int jpegQuality = 100; - switch (m_requestedImageSettings.quality()) { - case QImageCapture::VeryLowQuality: - jpegQuality = 20; - break; - case QImageCapture::LowQuality: - jpegQuality = 40; - break; - case QImageCapture::NormalQuality: - jpegQuality = 60; - break; - case QImageCapture::HighQuality: - jpegQuality = 80; - break; - case QImageCapture::VeryHighQuality: - jpegQuality = 100; - break; - } - m_camera->setJpegQuality(jpegQuality); -} - -bool QAndroidCameraSession::isReadyForCapture() const -{ - return isActive() && m_readyForCapture; -} - -void QAndroidCameraSession::setReadyForCapture(bool ready) -{ - if (m_readyForCapture == ready) - return; - - m_readyForCapture = ready; - emit readyForCaptureChanged(ready); -} - -int QAndroidCameraSession::capture(const QString &fileName) -{ - ++m_lastImageCaptureId; - - if (!isReadyForCapture()) { - emit imageCaptureError(m_lastImageCaptureId, QImageCapture::NotReadyError, - QPlatformImageCapture::msgCameraNotReady()); - return m_lastImageCaptureId; - } - - setReadyForCapture(false); - - m_currentImageCaptureId = m_lastImageCaptureId; - m_currentImageCaptureFileName = fileName; - - applyImageSettings(); - applyResolution(m_actualImageSettings.resolution()); - - // adjust picture rotation depending on the device orientation - m_camera->setRotation(currentCameraRotation()); - - m_camera->takePicture(); - - return m_lastImageCaptureId; -} - -void QAndroidCameraSession::onCameraTakePictureFailed() -{ - emit imageCaptureError(m_currentImageCaptureId, QImageCapture::ResourceError, - tr("Failed to capture image")); - - // Preview needs to be restarted and the preview call back must be setup again - m_camera->startPreview(); -} - -void QAndroidCameraSession::onCameraPictureExposed() -{ - if (!m_camera) - return; - - emit imageExposed(m_currentImageCaptureId); - m_camera->fetchLastPreviewFrame(); -} - -void QAndroidCameraSession::onLastPreviewFrameFetched(const QVideoFrame &frame) -{ - if (!m_camera) - return; - - (void) QtConcurrent::run(&QAndroidCameraSession::processPreviewImage, this, - m_currentImageCaptureId, - frame, - m_camera->getRotation()); -} - -void QAndroidCameraSession::processPreviewImage(int id, const QVideoFrame &frame, int rotation) -{ - // Preview display of front-facing cameras is flipped horizontally, but the frame data - // we get here is not. Flip it ourselves if the camera is front-facing to match what the user - // sees on the viewfinder. - QTransform transform; - if (m_camera->getFacing() == AndroidCamera::CameraFacingFront) - transform.scale(-1, 1); - transform.rotate(rotation); - - emit imageCaptured(id, frame.toImage().transformed(transform)); -} - -void QAndroidCameraSession::onNewPreviewFrame(const QVideoFrame &frame) -{ - if (!m_camera) - return; - - m_videoFrameCallbackMutex.lock(); - - if (m_previewCallback) - m_previewCallback->onFrameAvailable(frame); - - m_videoFrameCallbackMutex.unlock(); -} - -void QAndroidCameraSession::onCameraPictureCaptured(const QByteArray &data) -{ - // Loading and saving the captured image can be slow, do it in a separate thread - (void) QtConcurrent::run(&QAndroidCameraSession::processCapturedImage, this, - m_currentImageCaptureId, - data, - m_actualImageSettings.resolution(), - /* captureToBuffer = */ false, - m_currentImageCaptureFileName); - - // Preview needs to be restarted after taking a picture - if (m_camera) - m_camera->startPreview(); -} - -void QAndroidCameraSession::onCameraPreviewStarted() -{ - setReadyForCapture(true); -} - -void QAndroidCameraSession::onCameraPreviewFailedToStart() -{ - if (isActive()) { - Q_EMIT error(QCamera::CameraError, tr("Camera preview failed to start.")); - - AndroidMultimediaUtils::enableOrientationListener(false); - m_camera->setPreviewSize(QSize()); - m_camera->setPreviewTexture(0); - if (m_videoOutput) { - m_videoOutput->stop(); - m_videoOutput->reset(); - } - m_previewStarted = false; - - setActive(false); - setReadyForCapture(false); - } -} - -void QAndroidCameraSession::onCameraPreviewStopped() -{ - if (!m_previewStarted) - setActive(false); - setReadyForCapture(false); -} - -void QAndroidCameraSession::processCapturedImage(int id, - const QByteArray &data, - const QSize &resolution, - bool captureToBuffer, - const QString &fileName) -{ - - - if (!captureToBuffer) { - const QString actualFileName = QMediaStorageLocation::generateFileName(fileName, QStandardPaths::PicturesLocation, QLatin1String("jpg")); - - QFile file(actualFileName); - if (file.open(QFile::WriteOnly)) { - if (file.write(data) == data.size()) { - // if the picture is saved into the standard picture location, register it - // with the Android media scanner so it appears immediately in apps - // such as the gallery. - if (fileName.isEmpty() || QFileInfo(fileName).isRelative()) - AndroidMultimediaUtils::registerMediaFile(actualFileName); - - emit imageSaved(id, actualFileName); - } else { - emit imageCaptureError(id, QImageCapture::OutOfSpaceError, file.errorString()); - } - } else { - const QString errorMessage = tr("Could not open destination file: %1").arg(actualFileName); - emit imageCaptureError(id, QImageCapture::ResourceError, errorMessage); - } - } else { - QVideoFrame frame(new QMemoryVideoBuffer(data, -1), QVideoFrameFormat(resolution, QVideoFrameFormat::Format_Jpeg)); - emit imageAvailable(id, frame); - } -} - -void QAndroidCameraSession::onVideoOutputReady(bool ready) -{ - if (ready && m_active) - startPreview(); -} - -void QAndroidCameraSession::onApplicationStateChanged(Qt::ApplicationState state) -{ - switch (state) { - case Qt::ApplicationInactive: - if (!m_keepActive && m_active) { - m_savedState = m_active; - close(); - setActive(false); - } - break; - case Qt::ApplicationActive: - if (m_savedState != -1) { - setActiveHelper(m_savedState); - m_savedState = -1; - } - break; - default: - break; - } -} - -bool QAndroidCameraSession::requestCameraPermission() -{ - m_keepActive = true; - const bool result = qt_androidRequestCameraPermission(); - m_keepActive = false; - return result; -} - -void QAndroidCameraSession::setVideoSink(QVideoSink *sink) -{ - if (m_sink == sink) - return; - - m_sink = sink; - - if (m_sink) { - delete m_textureOutput; - m_textureOutput = nullptr; - - m_textureOutput = new QAndroidTextureVideoOutput(this); - m_textureOutput->setSurface(m_sink); - } - - setVideoOutput(m_textureOutput); -} - -QT_END_NAMESPACE |