summaryrefslogtreecommitdiffstats
path: root/src/multimedia/platform/qnx/camera/bbcamerasession.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/multimedia/platform/qnx/camera/bbcamerasession.cpp')
-rw-r--r--src/multimedia/platform/qnx/camera/bbcamerasession.cpp1049
1 files changed, 0 insertions, 1049 deletions
diff --git a/src/multimedia/platform/qnx/camera/bbcamerasession.cpp b/src/multimedia/platform/qnx/camera/bbcamerasession.cpp
deleted file mode 100644
index d82cbe482..000000000
--- a/src/multimedia/platform/qnx/camera/bbcamerasession.cpp
+++ /dev/null
@@ -1,1049 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Research In Motion
-** 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 "bbcamerasession_p.h"
-
-#include "bbcameraorientationhandler_p.h"
-#include "windowgrabber_p.h"
-
-#include <QBuffer>
-#include <QDebug>
-#include <QImage>
-#include <QUrl>
-#include <QVideoFrameFormat>
-#include <qmath.h>
-#include <private/qmediarecorder_p.h>
-#include <private/qplatformimagecapture_p.h>
-#include <private/qmediastoragelocation_p.h>
-
-#include <algorithm>
-
-QT_BEGIN_NAMESPACE
-
-static QString errorToString(camera_error_t error)
-{
- switch (error) {
- case CAMERA_EOK:
- return QLatin1String("No error");
- case CAMERA_EAGAIN:
- return QLatin1String("Camera unavailable");
- case CAMERA_EINVAL:
- return QLatin1String("Invalid argument");
- case CAMERA_ENODEV:
- return QLatin1String("Camera not found");
- case CAMERA_EMFILE:
- return QLatin1String("File table overflow");
- case CAMERA_EBADF:
- return QLatin1String("Invalid handle passed");
- case CAMERA_EACCESS:
- return QLatin1String("No permission");
- case CAMERA_EBADR:
- return QLatin1String("Invalid file descriptor");
- case CAMERA_ENOENT:
- return QLatin1String("File or directory does not exists");
- case CAMERA_ENOMEM:
- return QLatin1String("Memory allocation failed");
- case CAMERA_EOPNOTSUPP:
- return QLatin1String("Operation not supported");
- case CAMERA_ETIMEDOUT:
- return QLatin1String("Communication timeout");
- case CAMERA_EALREADY:
- return QLatin1String("Operation already in progress");
- case CAMERA_EUNINIT:
- return QLatin1String("Camera library not initialized");
- case CAMERA_EREGFAULT:
- return QLatin1String("Callback registration failed");
- case CAMERA_EMICINUSE:
- return QLatin1String("Microphone in use already");
- case CAMERA_ENODATA:
- return QLatin1String("Data does not exist");
- case CAMERA_EBUSY:
- return QLatin1String("Camera busy");
- case CAMERA_EDESKTOPCAMERAINUSE:
- return QLatin1String("Desktop camera in use already");
- case CAMERA_ENOSPC:
- return QLatin1String("Disk is full");
- case CAMERA_EPOWERDOWN:
- return QLatin1String("Camera in power down state");
- case CAMERA_3ALOCKED:
- return QLatin1String("3A have been locked");
-// case CAMERA_EVIEWFINDERFROZEN: // not yet available in 10.2 NDK
-// return QLatin1String("Freeze flag set");
- default:
- return QLatin1String("Unknown error");
- }
-}
-
-QDebug operator<<(QDebug debug, camera_error_t error)
-{
- debug.nospace() << errorToString(error);
- return debug.space();
-}
-
-BbCameraSession::BbCameraSession(QObject *parent)
- : QObject(parent)
- , m_nativeCameraOrientation(0)
- , m_orientationHandler(new BbCameraOrientationHandler(this))
- , m_status(QCamera::UnloadedStatus)
- , m_state(QCamera::UnloadedState)
- , m_captureMode(QCamera::CaptureStillImage)
- , m_device("bb:RearCamera")
- , m_previewIsVideo(true)
- , m_surface(0)
- , m_lastImageCaptureId(0)
- , m_videoState(QMediaRecorder::StoppedState)
- , m_handle(CAMERA_HANDLE_INVALID)
- , m_windowGrabber(new WindowGrabber(this))
-{
- connect(this, SIGNAL(statusChanged(QCamera::Status)), SLOT(updateReadyForCapture()));
- connect(this, SIGNAL(captureModeChanged(QCamera::CaptureModes)), SLOT(updateReadyForCapture()));
- connect(m_orientationHandler, SIGNAL(orientationChanged(int)), SLOT(deviceOrientationChanged(int)));
-
- connect(m_windowGrabber, SIGNAL(frameGrabbed(QImage, int)), SLOT(viewfinderFrameGrabbed(QImage)));
-}
-
-BbCameraSession::~BbCameraSession()
-{
- stopViewFinder();
- closeCamera();
-}
-
-camera_handle_t BbCameraSession::handle() const
-{
- return m_handle;
-}
-
-QCamera::State BbCameraSession::state() const
-{
- return m_state;
-}
-
-void BbCameraSession::setState(QCamera::State state)
-{
- if (m_state == state)
- return;
-
- const QCamera::State previousState = m_state;
-
- if (previousState == QCamera::UnloadedState) {
- if (state == QCamera::LoadedState) {
- if (openCamera()) {
- m_state = state;
- }
- } else if (state == QCamera::ActiveState) {
- if (openCamera()) {
- QMetaObject::invokeMethod(this, "applyConfiguration", Qt::QueuedConnection);
- m_state = state;
- }
- }
- } else if (previousState == QCamera::LoadedState) {
- if (state == QCamera::UnloadedState) {
- closeCamera();
- m_state = state;
- } else if (state == QCamera::ActiveState) {
- QMetaObject::invokeMethod(this, "applyConfiguration", Qt::QueuedConnection);
- m_state = state;
- }
- } else if (previousState == QCamera::ActiveState) {
- if (state == QCamera::LoadedState) {
- stopViewFinder();
- m_state = state;
- } else if (state == QCamera::UnloadedState) {
- stopViewFinder();
- closeCamera();
- m_state = state;
- }
- }
-
- if (m_state != previousState)
- emit stateChanged(m_state);
-}
-
-QCamera::Status BbCameraSession::status() const
-{
- return m_status;
-}
-
-QCamera::CaptureModes BbCameraSession::captureMode() const
-{
- return m_captureMode;
-}
-
-void BbCameraSession::setCaptureMode(QCamera::CaptureModes captureMode)
-{
- if (m_captureMode == captureMode)
- return;
-
- m_captureMode = captureMode;
- emit captureModeChanged(m_captureMode);
-}
-
-bool BbCameraSession::isCaptureModeSupported(QCamera::CaptureModes mode) const
-{
- if (m_handle == CAMERA_HANDLE_INVALID) {
- // the camera has not been loaded yet via QCamera::load(), so
- // we open it temporarily to peek for the supported capture modes
-
- camera_unit_t unit = CAMERA_UNIT_REAR;
- if (m_device == cameraIdentifierFront())
- unit = CAMERA_UNIT_FRONT;
- else if (m_device == cameraIdentifierRear())
- unit = CAMERA_UNIT_REAR;
- else if (m_device == cameraIdentifierDesktop())
- unit = CAMERA_UNIT_DESKTOP;
-
- camera_handle_t handle;
- const camera_error_t result = camera_open(unit, CAMERA_MODE_RW, &handle);
- if (result != CAMERA_EOK)
- return true;
-
- const bool supported = isCaptureModeSupported(handle, mode);
-
- camera_close(handle);
-
- return supported;
- } else {
- return isCaptureModeSupported(m_handle, mode);
- }
-}
-
-QByteArray BbCameraSession::cameraIdentifierFront()
-{
- return "bb:FrontCamera";
-}
-
-QByteArray BbCameraSession::cameraIdentifierRear()
-{
- return "bb:RearCamera";
-}
-
-QByteArray BbCameraSession::cameraIdentifierDesktop()
-{
- return "bb:DesktopCamera";
-}
-
-void BbCameraSession::setDevice(const QByteArray &device)
-{
- m_device = device;
-}
-
-QByteArray BbCameraSession::device() const
-{
- return m_device;
-}
-
-void BbCameraSession::setSurface(QVideoSink *surface)
-{
- QMutexLocker locker(&m_surfaceMutex);
-
- if (m_surface == surface)
- return;
-
- m_surface = surface;
-}
-
-bool BbCameraSession::isReadyForCapture() const
-{
- if (m_captureMode & QCamera::CaptureStillImage)
- return (m_status == QCamera::ActiveStatus);
-
- if (m_captureMode & QCamera::CaptureVideo)
- return (m_status == QCamera::ActiveStatus);
-
- return false;
-}
-
-/**
- * A helper structure that keeps context data for image capture callbacks.
- */
-struct ImageCaptureData
-{
- int requestId;
- QString fileName;
- BbCameraSession *session;
-};
-
-static void imageCaptureShutterCallback(camera_handle_t handle, void *context)
-{
- Q_UNUSED(handle);
-
- const ImageCaptureData *data = static_cast<ImageCaptureData*>(context);
-
- // We are inside a worker thread here, so emit imageExposed inside the main thread
- QMetaObject::invokeMethod(data->session, "imageExposed", Qt::QueuedConnection,
- Q_ARG(int, data->requestId));
-}
-
-static void imageCaptureImageCallback(camera_handle_t handle, camera_buffer_t *buffer, void *context)
-{
- Q_UNUSED(handle);
-
- QScopedPointer<ImageCaptureData> data(static_cast<ImageCaptureData*>(context));
-
- if (buffer->frametype != CAMERA_FRAMETYPE_JPEG) {
- // We are inside a worker thread here, so emit error signal inside the main thread
- QMetaObject::invokeMethod(data->session, "imageCaptureError", Qt::QueuedConnection,
- Q_ARG(int, data->requestId),
- Q_ARG(QImageCapture::Error, QImageCapture::FormatError),
- Q_ARG(QString, BbCameraSession::tr("Camera provides image in unsupported format")));
- return;
- }
-
- const QByteArray rawData((const char*)buffer->framebuf, buffer->framedesc.jpeg.bufsize);
-
- QImage image;
- const bool ok = image.loadFromData(rawData, "JPG");
- if (!ok) {
- const QString errorMessage = BbCameraSession::tr("Could not load JPEG data from frame");
- // We are inside a worker thread here, so emit error signal inside the main thread
- QMetaObject::invokeMethod(data->session, "imageCaptureError", Qt::QueuedConnection,
- Q_ARG(int, data->requestId),
- Q_ARG(QImageCapture::Error, QImageCapture::FormatError),
- Q_ARG(QString, errorMessage));
- return;
- }
-
-
- // We are inside a worker thread here, so invoke imageCaptured inside the main thread
- QMetaObject::invokeMethod(data->session, "imageCaptured", Qt::QueuedConnection,
- Q_ARG(int, data->requestId),
- Q_ARG(QImage, image),
- Q_ARG(QString, data->fileName));
-}
-
-int BbCameraSession::capture(const QString &fileName)
-{
- m_lastImageCaptureId++;
-
- if (!isReadyForCapture()) {
- emit imageCaptureError(m_lastImageCaptureId, QImageCapture::NotReadyError,
- QPlatformImageCapture::msgCameraNotReady());
- return m_lastImageCaptureId;
- }
-
- // prepare context object for callback
- ImageCaptureData *context = new ImageCaptureData;
- context->requestId = m_lastImageCaptureId;
- context->fileName = fileName;
- context->session = this;
-
- const camera_error_t result = camera_take_photo(m_handle,
- imageCaptureShutterCallback,
- 0,
- 0,
- imageCaptureImageCallback,
- context, false);
-
- if (result != CAMERA_EOK)
- qWarning() << "Unable to take photo:" << result;
-
- return m_lastImageCaptureId;
-}
-
-void BbCameraSession::cancelCapture()
-{
- // BB10 API doesn't provide functionality for that
-}
-
-QList<QSize> BbCameraSession::supportedResolutions(const QImageEncoderSettings&, bool *continuous) const
-{
- if (continuous)
- *continuous = false;
-
- if (m_status == QCamera::UnloadedStatus)
- return QList<QSize>();
-
- if (m_captureMode & QCamera::CaptureStillImage) {
- return supportedResolutions(QCamera::CaptureStillImage);
- } else if (m_captureMode & QCamera::CaptureVideo) {
- return supportedResolutions(QCamera::CaptureVideo);
- }
-
- return QList<QSize>();
-}
-
-QImageEncoderSettings BbCameraSession::imageSettings() const
-{
- return m_imageEncoderSettings;
-}
-
-void BbCameraSession::setImageSettings(const QImageEncoderSettings &settings)
-{
- m_imageEncoderSettings = settings;
- if (m_imageEncoderSettings.codec().isEmpty())
- m_imageEncoderSettings.setCodec(QLatin1String("jpeg"));
-}
-
-QMediaRecorder::RecorderState BbCameraSession::videoState() const
-{
- return m_videoState;
-}
-
-qint64 BbCameraSession::duration() const
-{
- return (m_videoRecordingDuration.isValid() ? m_videoRecordingDuration.elapsed() : 0);
-}
-
-void BbCameraSession::applyVideoSettings()
-{
- if (m_handle == CAMERA_HANDLE_INVALID)
- return;
-
- // apply viewfinder configuration
- const QList<QSize> videoOutputResolutions = supportedResolutions(QCamera::CaptureVideo);
-
- if (!m_videoEncoderSettings.resolution().isValid() || !videoOutputResolutions.contains(m_videoEncoderSettings.resolution()))
- m_videoEncoderSettings.setResolution(videoOutputResolutions.first());
-
- QSize viewfinderResolution;
-
- if (m_previewIsVideo) {
- // The viewfinder is responsible for encoding the video frames, so the resolutions must match.
- viewfinderResolution = m_videoEncoderSettings.resolution();
- } else {
- // The frames are encoded separately from the viewfinder, so only the aspect ratio must match.
- const QSize videoResolution = m_videoEncoderSettings.resolution();
- const qreal aspectRatio = static_cast<qreal>(videoResolution.width())/static_cast<qreal>(videoResolution.height());
-
- QList<QSize> sizes = supportedViewfinderResolutions(QCamera::CaptureVideo);
- std::reverse(sizes.begin(), sizes.end()); // use smallest possible resolution
- for (const QSize &size : qAsConst(sizes)) {
- // search for viewfinder resolution with the same aspect ratio
- if (qFuzzyCompare(aspectRatio, (static_cast<qreal>(size.width())/static_cast<qreal>(size.height())))) {
- viewfinderResolution = size;
- break;
- }
- }
- }
-
- Q_ASSERT(viewfinderResolution.isValid());
-
- const QByteArray windowId = QString().sprintf("qcamera_vf_%p", this).toLatin1();
- m_windowGrabber->setWindowId(windowId);
-
- const QByteArray windowGroupId = m_windowGrabber->windowGroupId();
-
- const int rotationAngle = (360 - m_nativeCameraOrientation);
-
- camera_error_t result = CAMERA_EOK;
- result = camera_set_videovf_property(m_handle,
- CAMERA_IMGPROP_WIN_GROUPID, windowGroupId.data(),
- CAMERA_IMGPROP_WIN_ID, windowId.data(),
- CAMERA_IMGPROP_WIDTH, viewfinderResolution.width(),
- CAMERA_IMGPROP_HEIGHT, viewfinderResolution.height(),
- CAMERA_IMGPROP_ROTATION, rotationAngle);
-
- if (result != CAMERA_EOK) {
- qWarning() << "Unable to apply video viewfinder settings:" << result;
- return;
- }
-
- const QSize resolution = m_videoEncoderSettings.resolution();
-
- QString videoCodec = m_videoEncoderSettings.codec();
- if (videoCodec.isEmpty())
- videoCodec = QLatin1String("h264");
-
- camera_videocodec_t cameraVideoCodec = CAMERA_VIDEOCODEC_H264;
- if (videoCodec == QLatin1String("none"))
- cameraVideoCodec = CAMERA_VIDEOCODEC_NONE;
- else if (videoCodec == QLatin1String("avc1"))
- cameraVideoCodec = CAMERA_VIDEOCODEC_AVC1;
- else if (videoCodec == QLatin1String("h264"))
- cameraVideoCodec = CAMERA_VIDEOCODEC_H264;
-
- qreal frameRate = m_videoEncoderSettings.frameRate();
- if (frameRate == 0) {
- const QList<qreal> frameRates = supportedFrameRates(QVideoEncoderSettings(), 0);
- if (!frameRates.isEmpty())
- frameRate = frameRates.last();
- }
-
- QString audioCodec = m_audioEncoderSettings.codec();
- if (audioCodec.isEmpty())
- audioCodec = QLatin1String("aac");
-
- camera_audiocodec_t cameraAudioCodec = CAMERA_AUDIOCODEC_AAC;
- if (audioCodec == QLatin1String("none"))
- cameraAudioCodec = CAMERA_AUDIOCODEC_NONE;
- else if (audioCodec == QLatin1String("aac"))
- cameraAudioCodec = CAMERA_AUDIOCODEC_AAC;
- else if (audioCodec == QLatin1String("raw"))
- cameraAudioCodec = CAMERA_AUDIOCODEC_RAW;
-
- result = camera_set_video_property(m_handle,
- CAMERA_IMGPROP_WIDTH, resolution.width(),
- CAMERA_IMGPROP_HEIGHT, resolution.height(),
- CAMERA_IMGPROP_ROTATION, rotationAngle,
- CAMERA_IMGPROP_VIDEOCODEC, cameraVideoCodec,
- CAMERA_IMGPROP_AUDIOCODEC, cameraAudioCodec);
-
- if (result != CAMERA_EOK) {
- qWarning() << "Unable to apply video settings:" << result;
- emit videoError(QMediaRecorder::ResourceError, tr("Unable to apply video settings"));
- }
-}
-
-QList<QSize> BbCameraSession::supportedResolutions(const QVideoEncoderSettings &settings, bool *continuous) const
-{
- Q_UNUSED(settings);
-
- if (continuous)
- *continuous = false;
-
- return supportedResolutions(QCamera::CaptureVideo);
-}
-
-QList<qreal> BbCameraSession::supportedFrameRates(const QVideoEncoderSettings &settings, bool *continuous) const
-{
- Q_UNUSED(settings);
-
- if (m_handle == CAMERA_HANDLE_INVALID)
- return QList<qreal>();
-
- int supported = 0;
- double rates[20];
- bool maxmin = false;
-
- /**
- * Since in current version of the BB10 platform the video viewfinder encodes the video frames, we use
- * the values as returned by camera_get_video_vf_framerates().
- */
- const camera_error_t result = camera_get_video_vf_framerates(m_handle, 20, &supported, rates, &maxmin);
- if (result != CAMERA_EOK) {
- qWarning() << "Unable to retrieve supported viewfinder framerates:" << result;
- return QList<qreal>();
- }
-
- QList<qreal> frameRates;
- for (int i = 0; i < supported; ++i)
- frameRates << rates[i];
-
- if (continuous)
- *continuous = maxmin;
-
- return frameRates;
-}
-
-QVideoEncoderSettings BbCameraSession::videoSettings() const
-{
- return m_videoEncoderSettings;
-}
-
-void BbCameraSession::setVideoSettings(const QVideoEncoderSettings &settings)
-{
- m_videoEncoderSettings = settings;
-}
-
-QAudioEncoderSettings BbCameraSession::audioSettings() const
-{
- return m_audioEncoderSettings;
-}
-
-void BbCameraSession::setAudioSettings(const QAudioEncoderSettings &settings)
-{
- m_audioEncoderSettings = settings;
-}
-
-void BbCameraSession::updateReadyForCapture()
-{
- emit readyForCaptureChanged(isReadyForCapture());
-}
-
-void BbCameraSession::imageCaptured(int requestId, const QImage &rawImage, const QString &fileName)
-{
- QTransform transform;
-
- // subtract out the native rotation
- transform.rotate(m_nativeCameraOrientation);
-
- // subtract out the current device orientation
- if (m_device == cameraIdentifierRear())
- transform.rotate(360 - m_orientationHandler->orientation());
- else
- transform.rotate(m_orientationHandler->orientation());
-
- const QImage image = rawImage.transformed(transform);
-
- // Generate snap preview as downscaled image
- {
- QSize previewSize = image.size();
- int downScaleSteps = 0;
- while (previewSize.width() > 800 && downScaleSteps < 8) {
- previewSize.rwidth() /= 2;
- previewSize.rheight() /= 2;
- downScaleSteps++;
- }
-
- const QImage snapPreview = image.scaled(previewSize);
-
- emit imageCaptured(requestId, snapPreview);
- }
-
- if (/* capture to buffer */ fileName.isEmpty()) {
- QVideoFrame frame(image);
- emit imageAvailable(requestId, frame);
- } else {
- const QString actualFileName = QMediaStorageLocation::generateFileName(fileName, QStandardPaths::PicturesLocation, QLatin1String("jpg"));
- QFile file(actualFileName);
- if (file.open(QFile::WriteOnly)) {
- if (image.save(&file, "jpg")) {
- emit imageSaved(requestId, actualFileName);
- } else {
- emit imageCaptureError(requestId, QImageCapture::OutOfSpaceError, file.errorString());
- }
- } else {
- const QString errorMessage = tr("Could not open destination file:\n%1").arg(actualFileName);
- emit imageCaptureError(requestId, QImageCapture::ResourceError, errorMessage);
- }
- }
-}
-
-void BbCameraSession::handleVideoRecordingPaused()
-{
- //TODO: implement once BB10 API supports pausing a video
-}
-
-void BbCameraSession::handleVideoRecordingResumed()
-{
- if (m_videoRecordingDuration.isValid())
- m_videoRecordingDuration.restart();
-}
-
-void BbCameraSession::deviceOrientationChanged(int angle)
-{
- if (m_handle != CAMERA_HANDLE_INVALID)
- camera_set_device_orientation(m_handle, angle);
-}
-
-void BbCameraSession::handleCameraPowerUp()
-{
- stopViewFinder();
- startViewFinder();
-}
-
-void BbCameraSession::viewfinderFrameGrabbed(const QImage &image)
-{
- QTransform transform;
-
- // subtract out the native rotation
- transform.rotate(m_nativeCameraOrientation);
-
- // subtract out the current device orientation
- if (m_device == cameraIdentifierRear())
- transform.rotate(360 - m_orientationHandler->viewfinderOrientation());
- else
- transform.rotate(m_orientationHandler->viewfinderOrientation());
-
- QImage frame = image.copy().transformed(transform);
-
- QMutexLocker locker(&m_surfaceMutex);
- if (m_surface) {
- if (frame.size() != m_surface->surfaceFormat().frameSize()) {
- m_surface->stop();
- m_surface->start(QVideoFrameFormat(frame.size(), QVideoFrameFormat::Format_ARGB32));
- }
-
- QVideoFrame videoFrame(frame);
-
- m_surface->present(videoFrame);
- }
-}
-
-bool BbCameraSession::openCamera()
-{
- if (m_handle != CAMERA_HANDLE_INVALID) // camera is already open
- return true;
-
- m_status = QCamera::LoadingStatus;
- emit statusChanged(m_status);
-
- camera_unit_t unit = CAMERA_UNIT_REAR;
- if (m_device == cameraIdentifierFront())
- unit = CAMERA_UNIT_FRONT;
- else if (m_device == cameraIdentifierRear())
- unit = CAMERA_UNIT_REAR;
- else if (m_device == cameraIdentifierDesktop())
- unit = CAMERA_UNIT_DESKTOP;
-
- camera_error_t result = camera_open(unit, CAMERA_MODE_RW, &m_handle);
- if (result != CAMERA_EOK) {
- m_handle = CAMERA_HANDLE_INVALID;
- m_status = QCamera::UnloadedStatus;
- emit statusChanged(m_status);
-
- qWarning() << "Unable to open camera:" << result;
- emit error(QCamera::CameraError, tr("Unable to open camera"));
- return false;
- }
-
- result = camera_get_native_orientation(m_handle, &m_nativeCameraOrientation);
- if (result != CAMERA_EOK) {
- qWarning() << "Unable to retrieve native camera orientation:" << result;
- emit error(QCamera::CameraError, tr("Unable to retrieve native camera orientation"));
- return false;
- }
-
- m_previewIsVideo = camera_has_feature(m_handle, CAMERA_FEATURE_PREVIEWISVIDEO);
-
- m_status = QCamera::LoadedStatus;
- emit statusChanged(m_status);
-
- emit cameraOpened();
-
- return true;
-}
-
-void BbCameraSession::closeCamera()
-{
- if (m_handle == CAMERA_HANDLE_INVALID) // camera is closed already
- return;
-
- m_status = QCamera::UnloadingStatus;
- emit statusChanged(m_status);
-
- const camera_error_t result = camera_close(m_handle);
- if (result != CAMERA_EOK) {
- m_status = QCamera::LoadedStatus;
- emit statusChanged(m_status);
-
- qWarning() << "Unable to close camera:" << result;
- emit error(QCamera::CameraError, tr("Unable to close camera"));
- return;
- }
-
- m_handle = CAMERA_HANDLE_INVALID;
-
- m_status = QCamera::UnloadedStatus;
- emit statusChanged(m_status);
-}
-
-static void viewFinderStatusCallback(camera_handle_t handle, camera_devstatus_t status, uint16_t value, void *context)
-{
- Q_UNUSED(handle);
-
- if (status == CAMERA_STATUS_FOCUS_CHANGE) {
- BbCameraSession *session = static_cast<BbCameraSession*>(context);
- QMetaObject::invokeMethod(session, "focusStatusChanged", Qt::QueuedConnection, Q_ARG(int, value));
- return;
- } else if (status == CAMERA_STATUS_POWERUP) {
- BbCameraSession *session = static_cast<BbCameraSession*>(context);
- QMetaObject::invokeMethod(session, "handleCameraPowerUp", Qt::QueuedConnection);
- }
-}
-
-bool BbCameraSession::startViewFinder()
-{
- m_status = QCamera::StartingStatus;
- emit statusChanged(m_status);
-
- QSize viewfinderResolution;
- camera_error_t result = CAMERA_EOK;
- if (m_captureMode & QCamera::CaptureStillImage) {
- result = camera_start_photo_viewfinder(m_handle, 0, viewFinderStatusCallback, this);
- viewfinderResolution = currentViewfinderResolution(QCamera::CaptureStillImage);
- } else if (m_captureMode & QCamera::CaptureVideo) {
- result = camera_start_video_viewfinder(m_handle, 0, viewFinderStatusCallback, this);
- viewfinderResolution = currentViewfinderResolution(QCamera::CaptureVideo);
- }
-
- if (result != CAMERA_EOK) {
- qWarning() << "Unable to start viewfinder:" << result;
- return false;
- }
-
- const int angle = m_orientationHandler->viewfinderOrientation();
-
- const QSize rotatedSize = ((angle == 0 || angle == 180) ? viewfinderResolution
- : viewfinderResolution.transposed());
-
- m_surfaceMutex.lock();
- if (m_surface) {
- const bool ok = m_surface->start(QVideoFrameFormat(rotatedSize, QVideoFrameFormat::Format_ARGB32));
- if (!ok)
- qWarning() << "Unable to start camera viewfinder surface";
- }
- m_surfaceMutex.unlock();
-
- m_status = QCamera::ActiveStatus;
- emit statusChanged(m_status);
-
- return true;
-}
-
-void BbCameraSession::stopViewFinder()
-{
- m_windowGrabber->stop();
-
- m_status = QCamera::StoppingStatus;
- emit statusChanged(m_status);
-
- m_surfaceMutex.lock();
- if (m_surface) {
- m_surface->stop();
- }
- m_surfaceMutex.unlock();
-
- camera_error_t result = CAMERA_EOK;
- if (m_captureMode & QCamera::CaptureStillImage)
- result = camera_stop_photo_viewfinder(m_handle);
- else if (m_captureMode & QCamera::CaptureVideo)
- result = camera_stop_video_viewfinder(m_handle);
-
- if (result != CAMERA_EOK) {
- qWarning() << "Unable to stop viewfinder:" << result;
- return;
- }
-
- m_status = QCamera::LoadedStatus;
- emit statusChanged(m_status);
-}
-
-void BbCameraSession::applyConfiguration()
-{
- if (m_captureMode & QCamera::CaptureStillImage) {
- const QList<QSize> photoOutputResolutions = supportedResolutions(QCamera::CaptureStillImage);
-
- if (!m_imageEncoderSettings.resolution().isValid() || !photoOutputResolutions.contains(m_imageEncoderSettings.resolution()))
- m_imageEncoderSettings.setResolution(photoOutputResolutions.first());
-
- const QSize photoResolution = m_imageEncoderSettings.resolution();
- const qreal aspectRatio = static_cast<qreal>(photoResolution.width())/static_cast<qreal>(photoResolution.height());
-
- // apply viewfinder configuration
- QSize viewfinderResolution;
- QList<QSize> sizes = supportedViewfinderResolutions(QCamera::CaptureStillImage);
- std::reverse(sizes.begin(), sizes.end()); // use smallest possible resolution
- for (const QSize &size : qAsConst(sizes)) {
- // search for viewfinder resolution with the same aspect ratio
- if (qFuzzyCompare(aspectRatio, (static_cast<qreal>(size.width())/static_cast<qreal>(size.height())))) {
- viewfinderResolution = size;
- break;
- }
- }
-
- Q_ASSERT(viewfinderResolution.isValid());
-
- const QByteArray windowId = QString().sprintf("qcamera_vf_%p", this).toLatin1();
- m_windowGrabber->setWindowId(windowId);
-
- const QByteArray windowGroupId = m_windowGrabber->windowGroupId();
-
- camera_error_t result = camera_set_photovf_property(m_handle,
- CAMERA_IMGPROP_WIN_GROUPID, windowGroupId.data(),
- CAMERA_IMGPROP_WIN_ID, windowId.data(),
- CAMERA_IMGPROP_WIDTH, viewfinderResolution.width(),
- CAMERA_IMGPROP_HEIGHT, viewfinderResolution.height(),
- CAMERA_IMGPROP_FORMAT, CAMERA_FRAMETYPE_NV12,
- CAMERA_IMGPROP_ROTATION, 360 - m_nativeCameraOrientation);
-
- if (result != CAMERA_EOK) {
- qWarning() << "Unable to apply photo viewfinder settings:" << result;
- return;
- }
-
-
- int jpegQuality = 100;
- switch (m_imageEncoderSettings.quality()) {
- case QMediaRecorder::VeryLowQuality:
- jpegQuality = 20;
- break;
- case QMediaRecorder::LowQuality:
- jpegQuality = 40;
- break;
- case QMediaRecorder::NormalQuality:
- jpegQuality = 60;
- break;
- case QMediaRecorder::HighQuality:
- jpegQuality = 80;
- break;
- case QMediaRecorder::VeryHighQuality:
- jpegQuality = 100;
- break;
- }
-
- // apply photo configuration
- result = camera_set_photo_property(m_handle,
- CAMERA_IMGPROP_WIDTH, photoResolution.width(),
- CAMERA_IMGPROP_HEIGHT, photoResolution.height(),
- CAMERA_IMGPROP_JPEGQFACTOR, jpegQuality,
- CAMERA_IMGPROP_ROTATION, 360 - m_nativeCameraOrientation);
-
- if (result != CAMERA_EOK) {
- qWarning() << "Unable to apply photo settings:" << result;
- return;
- }
-
- } else if (m_captureMode & QCamera::CaptureVideo) {
- applyVideoSettings();
- }
-
- startViewFinder();
-}
-
-static void videoRecordingStatusCallback(camera_handle_t handle, camera_devstatus_t status, uint16_t value, void *context)
-{
- Q_UNUSED(handle);
- Q_UNUSED(value);
-
- if (status == CAMERA_STATUS_VIDEO_PAUSE) {
- BbCameraSession *session = static_cast<BbCameraSession*>(context);
- QMetaObject::invokeMethod(session, "handleVideoRecordingPaused", Qt::QueuedConnection);
- } else if (status == CAMERA_STATUS_VIDEO_RESUME) {
- BbCameraSession *session = static_cast<BbCameraSession*>(context);
- QMetaObject::invokeMethod(session, "handleVideoRecordingResumed", Qt::QueuedConnection);
- }
-}
-
-void BbCameraSession::startVideoRecording(const QUrl &outputLocation)
-{
- if (m_videoState == QMediaRecorder::RecordingState)
- return;
-
- m_videoRecordingDuration.invalidate();
-
- auto videoOutputLocation = QMediaStorageLocation::generateFileName(outputLocation.toLocalFile(), QStandardPaths::MoviesLocation, QLatin1String("mp4"));
-
- emit actualLocationChanged(videoOutputLocation);
-
- const camera_error_t result = camera_start_video(m_handle, QFile::encodeName(videoOutputLocation), 0, videoRecordingStatusCallback, this);
- if (result != CAMERA_EOK) {
- emit videoError(QMediaRecorder::ResourceError,
- QMediaRecorderPrivate::msgFailedStartRecording());
- } else {
- m_videoState = QMediaRecorder::RecordingState;
- }
- emit videoStateChanged(m_videoState);
-}
-
-void BbCameraSession::stopVideoRecording()
-{
- if (m_videoState == QMediaRecorder::StoppedState)
- return;
-
- const camera_error_t result = camera_stop_video(m_handle);
- if (result != CAMERA_EOK) {
- emit videoError(QMediaRecorder::ResourceError, tr("Unable to stop video recording"));
- }
-
- m_videoRecordingDuration.invalidate();
- m_videoState = QMediaRecorder::StoppedState;
- emit videoStateChanged(m_videoState);
-}
-
-bool BbCameraSession::isCaptureModeSupported(camera_handle_t handle, QCamera::CaptureModes mode) const
-{
- if (mode & QCamera::CaptureStillImage)
- return camera_has_feature(handle, CAMERA_FEATURE_PHOTO);
-
- if (mode & QCamera::CaptureVideo)
- return camera_has_feature(handle, CAMERA_FEATURE_VIDEO);
-
- return false;
-}
-
-QList<QSize> BbCameraSession::supportedResolutions(QCamera::CaptureMode mode) const
-{
- Q_ASSERT(m_handle != CAMERA_HANDLE_INVALID);
-
- QList<QSize> list;
-
- camera_error_t result = CAMERA_EOK;
- camera_res_t resolutions[20];
- unsigned int supported = 0;
-
- if (mode == QCamera::CaptureStillImage)
- result = camera_get_photo_output_resolutions(m_handle, CAMERA_FRAMETYPE_JPEG, 20, &supported, resolutions);
- else if (mode == QCamera::CaptureVideo)
- result = camera_get_video_output_resolutions(m_handle, 20, &supported, resolutions);
-
- if (result != CAMERA_EOK)
- return list;
-
- for (unsigned int i = 0; i < supported; ++i)
- list << QSize(resolutions[i].width, resolutions[i].height);
-
- return list;
-}
-
-QList<QSize> BbCameraSession::supportedViewfinderResolutions(QCamera::CaptureMode mode) const
-{
- Q_ASSERT(m_handle != CAMERA_HANDLE_INVALID);
-
- QList<QSize> list;
-
- camera_error_t result = CAMERA_EOK;
- camera_res_t resolutions[20];
- unsigned int supported = 0;
-
- if (mode == QCamera::CaptureStillImage)
- result = camera_get_photo_vf_resolutions(m_handle, 20, &supported, resolutions);
- else if (mode == QCamera::CaptureVideo)
- result = camera_get_video_vf_resolutions(m_handle, 20, &supported, resolutions);
-
- if (result != CAMERA_EOK)
- return list;
-
- for (unsigned int i = 0; i < supported; ++i)
- list << QSize(resolutions[i].width, resolutions[i].height);
-
- return list;
-}
-
-QSize BbCameraSession::currentViewfinderResolution(QCamera::CaptureMode mode) const
-{
- Q_ASSERT(m_handle != CAMERA_HANDLE_INVALID);
-
- camera_error_t result = CAMERA_EOK;
- int width = 0;
- int height = 0;
-
- if (mode == QCamera::CaptureStillImage)
- result = camera_get_photovf_property(m_handle, CAMERA_IMGPROP_WIDTH, &width,
- CAMERA_IMGPROP_HEIGHT, &height);
- else if (mode == QCamera::CaptureVideo)
- result = camera_get_videovf_property(m_handle, CAMERA_IMGPROP_WIDTH, &width,
- CAMERA_IMGPROP_HEIGHT, &height);
-
- if (result != CAMERA_EOK)
- return QSize();
-
- return QSize(width, height);
-}
-
-QT_END_NAMESPACE