summaryrefslogtreecommitdiffstats
path: root/examples/multimedia/camera/camera.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/multimedia/camera/camera.cpp')
-rw-r--r--examples/multimedia/camera/camera.cpp421
1 files changed, 421 insertions, 0 deletions
diff --git a/examples/multimedia/camera/camera.cpp b/examples/multimedia/camera/camera.cpp
new file mode 100644
index 000000000..c5aa19e2d
--- /dev/null
+++ b/examples/multimedia/camera/camera.cpp
@@ -0,0 +1,421 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "camera.h"
+#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
+# include "ui_camera_mobile.h"
+#else
+# include "ui_camera.h"
+#endif
+
+#include "imagesettings.h"
+#include "metadatadialog.h"
+#include "videosettings.h"
+
+#include <QAudioDevice>
+#include <QAudioInput>
+#include <QCameraDevice>
+#include <QMediaDevices>
+#include <QMediaFormat>
+#include <QMediaMetaData>
+#include <QMediaRecorder>
+#include <QVideoWidget>
+
+#include <QLineEdit>
+#include <QMessageBox>
+
+#include <QAction>
+#include <QActionGroup>
+#include <QImage>
+#include <QKeyEvent>
+#include <QPalette>
+
+#include <QDir>
+#include <QTimer>
+
+#if QT_CONFIG(permissions)
+ #include <QPermission>
+#endif
+
+Camera::Camera() : ui(new Ui::Camera)
+{
+ ui->setupUi(this);
+ // disable all buttons by default
+ updateCameraActive(false);
+ readyForCapture(false);
+ ui->recordButton->setEnabled(false);
+ ui->pauseButton->setEnabled(false);
+ ui->stopButton->setEnabled(false);
+ ui->metaDataButton->setEnabled(false);
+
+ // try to actually initialize camera & mic
+ init();
+}
+
+void Camera::init()
+{
+#if QT_CONFIG(permissions)
+ // camera
+ QCameraPermission cameraPermission;
+ switch (qApp->checkPermission(cameraPermission)) {
+ case Qt::PermissionStatus::Undetermined:
+ qApp->requestPermission(cameraPermission, this, &Camera::init);
+ return;
+ case Qt::PermissionStatus::Denied:
+ qWarning("Camera permission is not granted!");
+ return;
+ case Qt::PermissionStatus::Granted:
+ break;
+ }
+ // microphone
+ QMicrophonePermission microphonePermission;
+ switch (qApp->checkPermission(microphonePermission)) {
+ case Qt::PermissionStatus::Undetermined:
+ qApp->requestPermission(microphonePermission, this, &Camera::init);
+ return;
+ case Qt::PermissionStatus::Denied:
+ qWarning("Microphone permission is not granted!");
+ return;
+ case Qt::PermissionStatus::Granted:
+ break;
+ }
+#endif
+
+ m_audioInput.reset(new QAudioInput);
+ m_captureSession.setAudioInput(m_audioInput.get());
+
+ // Camera devices:
+
+ videoDevicesGroup = new QActionGroup(this);
+ videoDevicesGroup->setExclusive(true);
+ updateCameras();
+ connect(&m_devices, &QMediaDevices::videoInputsChanged, this, &Camera::updateCameras);
+
+ connect(videoDevicesGroup, &QActionGroup::triggered, this, &Camera::updateCameraDevice);
+ connect(ui->captureWidget, &QTabWidget::currentChanged, this, &Camera::updateCaptureMode);
+
+ connect(ui->metaDataButton, &QPushButton::clicked, this, &Camera::showMetaDataDialog);
+ connect(ui->exposureCompensation, &QAbstractSlider::valueChanged, this,
+ &Camera::setExposureCompensation);
+
+ setCamera(QMediaDevices::defaultVideoInput());
+}
+
+void Camera::setCamera(const QCameraDevice &cameraDevice)
+{
+ m_camera.reset(new QCamera(cameraDevice));
+ m_captureSession.setCamera(m_camera.data());
+
+ connect(m_camera.data(), &QCamera::activeChanged, this, &Camera::updateCameraActive);
+ connect(m_camera.data(), &QCamera::errorOccurred, this, &Camera::displayCameraError);
+
+ if (!m_mediaRecorder) {
+ m_mediaRecorder.reset(new QMediaRecorder);
+ m_captureSession.setRecorder(m_mediaRecorder.data());
+ connect(m_mediaRecorder.data(), &QMediaRecorder::recorderStateChanged, this,
+ &Camera::updateRecorderState);
+ connect(m_mediaRecorder.data(), &QMediaRecorder::durationChanged, this,
+ &Camera::updateRecordTime);
+ connect(m_mediaRecorder.data(), &QMediaRecorder::errorChanged, this,
+ &Camera::displayRecorderError);
+ }
+
+ if (!m_imageCapture) {
+ m_imageCapture.reset(new QImageCapture);
+ m_captureSession.setImageCapture(m_imageCapture.get());
+ connect(m_imageCapture.get(), &QImageCapture::readyForCaptureChanged, this,
+ &Camera::readyForCapture);
+ connect(m_imageCapture.get(), &QImageCapture::imageCaptured, this,
+ &Camera::processCapturedImage);
+ connect(m_imageCapture.get(), &QImageCapture::imageSaved, this, &Camera::imageSaved);
+ connect(m_imageCapture.get(), &QImageCapture::errorOccurred, this,
+ &Camera::displayCaptureError);
+ }
+
+ m_captureSession.setVideoOutput(ui->viewfinder);
+
+ updateCameraActive(m_camera->isActive());
+ updateRecorderState(m_mediaRecorder->recorderState());
+ readyForCapture(m_imageCapture->isReadyForCapture());
+
+ updateCaptureMode();
+
+ m_camera->start();
+}
+
+void Camera::keyPressEvent(QKeyEvent *event)
+{
+ if (event->isAutoRepeat())
+ return;
+
+ switch (event->key()) {
+ case Qt::Key_CameraFocus:
+ displayViewfinder();
+ event->accept();
+ break;
+ case Qt::Key_Camera:
+ if (m_doImageCapture) {
+ takeImage();
+ } else {
+ if (m_mediaRecorder->recorderState() == QMediaRecorder::RecordingState)
+ stop();
+ else
+ record();
+ }
+ event->accept();
+ break;
+ default:
+ QMainWindow::keyPressEvent(event);
+ }
+}
+
+void Camera::updateRecordTime()
+{
+ QString str = tr("Recorded %1 sec").arg(m_mediaRecorder->duration() / 1000);
+ ui->statusbar->showMessage(str);
+}
+
+void Camera::processCapturedImage(int requestId, const QImage &img)
+{
+ Q_UNUSED(requestId);
+ QImage scaledImage =
+ img.scaled(ui->viewfinder->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
+
+ ui->lastImagePreviewLabel->setPixmap(QPixmap::fromImage(scaledImage));
+
+ // Display captured image for 4 seconds.
+ displayCapturedImage();
+ QTimer::singleShot(4000, this, &Camera::displayViewfinder);
+}
+
+void Camera::configureCaptureSettings()
+{
+ if (m_doImageCapture)
+ configureImageSettings();
+ else
+ configureVideoSettings();
+}
+
+void Camera::configureVideoSettings()
+{
+ VideoSettings settingsDialog(m_mediaRecorder.data());
+
+ if (settingsDialog.exec())
+ settingsDialog.applySettings();
+}
+
+void Camera::configureImageSettings()
+{
+ ImageSettings settingsDialog(m_imageCapture.get());
+
+ if (settingsDialog.exec() == QDialog::Accepted)
+ settingsDialog.applyImageSettings();
+}
+
+void Camera::record()
+{
+ m_mediaRecorder->record();
+ updateRecordTime();
+}
+
+void Camera::pause()
+{
+ m_mediaRecorder->pause();
+}
+
+void Camera::stop()
+{
+ m_mediaRecorder->stop();
+}
+
+void Camera::setMuted(bool muted)
+{
+ m_captureSession.audioInput()->setMuted(muted);
+}
+
+void Camera::takeImage()
+{
+ m_isCapturingImage = true;
+ m_imageCapture->captureToFile();
+}
+
+void Camera::displayCaptureError(int id, const QImageCapture::Error error,
+ const QString &errorString)
+{
+ Q_UNUSED(id);
+ Q_UNUSED(error);
+ QMessageBox::warning(this, tr("Image Capture Error"), errorString);
+ m_isCapturingImage = false;
+}
+
+void Camera::startCamera()
+{
+ m_camera->start();
+}
+
+void Camera::stopCamera()
+{
+ m_camera->stop();
+}
+
+void Camera::updateCaptureMode()
+{
+ int tabIndex = ui->captureWidget->currentIndex();
+ m_doImageCapture = (tabIndex == 0);
+}
+
+void Camera::updateCameraActive(bool active)
+{
+ if (active) {
+ ui->actionStartCamera->setEnabled(false);
+ ui->actionStopCamera->setEnabled(true);
+ ui->captureWidget->setEnabled(true);
+ ui->actionSettings->setEnabled(true);
+ } else {
+ ui->actionStartCamera->setEnabled(true);
+ ui->actionStopCamera->setEnabled(false);
+ ui->captureWidget->setEnabled(false);
+ ui->actionSettings->setEnabled(false);
+ }
+}
+
+void Camera::updateRecorderState(QMediaRecorder::RecorderState state)
+{
+ switch (state) {
+ case QMediaRecorder::StoppedState:
+ ui->recordButton->setEnabled(true);
+ ui->pauseButton->setEnabled(true);
+ ui->stopButton->setEnabled(false);
+ ui->metaDataButton->setEnabled(true);
+ break;
+ case QMediaRecorder::PausedState:
+ ui->recordButton->setEnabled(true);
+ ui->pauseButton->setEnabled(false);
+ ui->stopButton->setEnabled(true);
+ ui->metaDataButton->setEnabled(false);
+ break;
+ case QMediaRecorder::RecordingState:
+ ui->recordButton->setEnabled(false);
+ ui->pauseButton->setEnabled(true);
+ ui->stopButton->setEnabled(true);
+ ui->metaDataButton->setEnabled(false);
+ break;
+ }
+}
+
+void Camera::setExposureCompensation(int index)
+{
+ m_camera->setExposureCompensation(index * 0.5);
+}
+
+void Camera::displayRecorderError()
+{
+ if (m_mediaRecorder->error() != QMediaRecorder::NoError)
+ QMessageBox::warning(this, tr("Capture Error"), m_mediaRecorder->errorString());
+}
+
+void Camera::displayCameraError()
+{
+ if (m_camera->error() != QCamera::NoError)
+ QMessageBox::warning(this, tr("Camera Error"), m_camera->errorString());
+}
+
+void Camera::updateCameraDevice(QAction *action)
+{
+ setCamera(qvariant_cast<QCameraDevice>(action->data()));
+}
+
+void Camera::displayViewfinder()
+{
+ ui->stackedWidget->setCurrentIndex(0);
+}
+
+void Camera::displayCapturedImage()
+{
+ ui->stackedWidget->setCurrentIndex(1);
+}
+
+void Camera::readyForCapture(bool ready)
+{
+ ui->takeImageButton->setEnabled(ready);
+}
+
+void Camera::imageSaved(int id, const QString &fileName)
+{
+ Q_UNUSED(id);
+ ui->statusbar->showMessage(tr("Captured \"%1\"").arg(QDir::toNativeSeparators(fileName)));
+
+ m_isCapturingImage = false;
+ if (m_applicationExiting)
+ close();
+}
+
+void Camera::closeEvent(QCloseEvent *event)
+{
+ if (m_isCapturingImage) {
+ setEnabled(false);
+ m_applicationExiting = true;
+ event->ignore();
+ } else {
+ event->accept();
+ }
+}
+
+void Camera::updateCameras()
+{
+ ui->menuDevices->clear();
+ const QList<QCameraDevice> availableCameras = QMediaDevices::videoInputs();
+ for (const QCameraDevice &cameraDevice : availableCameras) {
+ QAction *videoDeviceAction = new QAction(cameraDevice.description(), videoDevicesGroup);
+ videoDeviceAction->setCheckable(true);
+ videoDeviceAction->setData(QVariant::fromValue(cameraDevice));
+ if (cameraDevice == QMediaDevices::defaultVideoInput())
+ videoDeviceAction->setChecked(true);
+
+ ui->menuDevices->addAction(videoDeviceAction);
+ }
+}
+
+void Camera::showMetaDataDialog()
+{
+ if (!m_metaDataDialog)
+ m_metaDataDialog = new MetaDataDialog(this);
+ m_metaDataDialog->setAttribute(Qt::WA_DeleteOnClose, false);
+ if (m_metaDataDialog->exec() == QDialog::Accepted)
+ saveMetaData();
+}
+
+void Camera::saveMetaData()
+{
+ QMediaMetaData data;
+ for (int i = 0; i < QMediaMetaData::NumMetaData; i++) {
+ QString val = m_metaDataDialog->m_metaDataFields[i]->text();
+ if (!val.isEmpty()) {
+ const auto key = static_cast<QMediaMetaData::Key>(i);
+ switch (key) {
+ case QMediaMetaData::CoverArtImage: {
+ QImage coverArt(val);
+ data.insert(key, coverArt);
+ break;
+ }
+ case QMediaMetaData::ThumbnailImage: {
+ QImage thumbnail(val);
+ data.insert(key, thumbnail);
+ break;
+ }
+ case QMediaMetaData::Date: {
+ QDateTime date = QDateTime::fromString(val);
+ data.insert(key, date);
+ break;
+ }
+ case QMediaMetaData::HasHdrContent:
+ break;
+ default:
+ data.insert(key, val);
+ }
+ }
+ }
+ m_mediaRecorder->setMetaData(data);
+}
+
+#include "moc_camera.cpp"