xref: /OK3568_Linux_fs/app/qcamera/qtcamera.cpp.bk (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24**   * Redistributions of source code must retain the above copyright
25**     notice, this list of conditions and the following disclaimer.
26**   * Redistributions in binary form must reproduce the above copyright
27**     notice, this list of conditions and the following disclaimer in
28**     the documentation and/or other materials provided with the
29**     distribution.
30**   * Neither the name of The Qt Company Ltd nor the names of its
31**     contributors may be used to endorse or promote products derived
32**     from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include "qtcamera.h"
52#include <QApplication>
53#include <QMediaService>
54#include <QMediaRecorder>
55#include <QCameraViewfinder>
56#include <QCameraInfo>
57#include <QMediaMetaData>
58
59#include <QMessageBox>
60#include <QPalette>
61#include <QTabWidget>
62#include <QtWidgets>
63#include <QHBoxLayout>
64#include <QVBoxLayout>
65
66
67#define QCAMERA_CAPTURE_MODE "Image Mode"
68#define QCAMERA_VIDEO_MODE "Video Mode"
69#define DIR_USERDATA "/userdata"
70#define DIR_HOME QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
71Q_DECLARE_METATYPE(QCameraInfo)
72
73qtCamera::qtCamera()
74{
75    initlayout();
76    QFileInfo fi(DIR_USERDATA);
77    if(fi.isDir()){
78        locationDir = DIR_USERDATA;
79    }else {
80        QFileInfo fi(DIR_HOME);
81        if(fi.isDir()){
82            locationDir = DIR_HOME;
83        }
84    }
85    imageCnt = videoCnt = 0;
86    setCamera(QCameraInfo::defaultCamera());
87}
88
89void qtCamera::initlayout()
90{
91    QBoxLayout *vLayout = new QVBoxLayout();
92    const QRect availableGeometry = QApplication::desktop()->availableGeometry(this);
93    resize(availableGeometry.width(), availableGeometry.height());
94
95    const QList<QCameraInfo> availableCameras = QCameraInfo::availableCameras();
96    for (const QCameraInfo &cameraInfo : availableCameras) {
97//        qDebug() << cameraInfo.description();
98        QPushButton *camera = getButton();
99        camera->setText(cameraInfo.description());
100        camera->setCheckable(true);
101        if (cameraInfo == QCameraInfo::defaultCamera()){
102            camera->setDefault(true);
103        }else {
104            camera->setDefault(false);
105        }
106        connect(camera, SIGNAL(clicked(bool)), this, SLOT(on_cameraSwitch()));
107        vLayout->addWidget(camera);
108    }
109
110    modeButton = getButton();
111    modeButton->setText(cameraMode);
112    connect(modeButton, SIGNAL(clicked(bool)), this, SLOT(updateCaptureMode()));
113
114    captureButton = getButton();
115    captureButton->setText(tr("Capture"));
116    connect(captureButton, SIGNAL(clicked(bool)), this, SLOT(on_captureClicked()));
117
118    exitButton = getButton();
119    exitButton->setText(tr("Exit"));
120    connect(exitButton, SIGNAL(clicked(bool)), this, SLOT(on_exitClicked()));
121
122    vLayout->addWidget(modeButton);
123    vLayout->addWidget(captureButton);
124    vLayout->addWidget(exitButton);
125    vLayout->setAlignment(Qt::AlignTop);
126
127    viewfinder.setWindowFlag(Qt::FramelessWindowHint);
128    viewfinder.setFixedSize(availableGeometry.width() - 150, availableGeometry.height());
129
130    QBoxLayout *hlayout = new QHBoxLayout;
131    hlayout->setMargin(0);
132    hlayout->addWidget(&viewfinder);
133    hlayout->addLayout(vLayout);
134
135    QWidget *widget = new QWidget;
136    widget->setLayout(hlayout);
137    setCentralWidget(widget);
138//    setWindowState(Qt::WindowMaximized);
139    setWindowFlags(Qt::FramelessWindowHint);
140}
141
142void qtCamera::setCamera(const QCameraInfo &cameraInfo)
143{
144    m_camera.reset(new QCamera(cameraInfo));
145
146    connect(m_camera.data(), &QCamera::stateChanged, this, &qtCamera::updateCameraState);
147    connect(m_camera.data(), QOverload<QCamera::Error>::of(&QCamera::error), this, &qtCamera::displayCameraError);
148
149    m_mediaRecorder.reset(new QMediaRecorder(m_camera.data()));
150    connect(m_mediaRecorder.data(), &QMediaRecorder::stateChanged, this, &qtCamera::updateRecorderState);
151
152    m_imageCapture.reset(new QCameraImageCapture(m_camera.data()));
153
154    connect(m_mediaRecorder.data(), &QMediaRecorder::durationChanged, this, &qtCamera::updateRecordTime);
155    connect(m_mediaRecorder.data(), QOverload<QMediaRecorder::Error>::of(&QMediaRecorder::error),
156            this, &qtCamera::displayRecorderError);
157
158    m_mediaRecorder->setMetaData(QMediaMetaData::Title, QVariant(QLatin1String("Test Title")));
159
160    configureCaptureSettings();
161
162    m_camera->setViewfinder(&viewfinder);
163
164    updateCameraState(m_camera->state());
165    updateRecorderState(m_mediaRecorder->state());
166
167    connect(m_imageCapture.data(), &QCameraImageCapture::imageSaved, this, &qtCamera::imageSaved);
168    connect(m_imageCapture.data(), QOverload<int, QCameraImageCapture::Error, const QString &>::of(&QCameraImageCapture::error),
169            this, &qtCamera::displayCaptureError);
170
171    updateCaptureMode();
172}
173
174void qtCamera::configureCaptureSettings()
175{
176    QSize size(640, 480);
177
178    m_imageSettings.setCodec("jpeg");
179    m_imageSettings.setQuality(QMultimedia::VeryHighQuality);
180    m_imageSettings.setResolution(size);
181    m_imageCapture->setEncodingSettings(m_imageSettings);
182
183    m_audioSettings.setCodec("audio/x-adpcm");
184    m_audioSettings.setChannelCount(2);
185    m_audioSettings.setQuality(QMultimedia::NormalQuality);
186    m_mediaRecorder->setAudioSettings(m_audioSettings);
187
188    m_videoSettings.setCodec("video/x-h264");
189    m_videoSettings.setResolution(size);
190    m_videoSettings.setQuality(QMultimedia::NormalQuality);
191    m_mediaRecorder->setVideoSettings(m_videoSettings);
192
193    m_mediaRecorder->setContainerFormat("video/quicktime");
194
195    if (0) {
196        QList<QSize> supportedResolutions;
197        supportedResolutions = m_imageCapture->supportedResolutions();
198        for (const QSize &resolution : supportedResolutions) {
199             qDebug() << "image resolution: " << resolution.width() << "x" << resolution.height();
200        }
201
202        supportedResolutions = m_mediaRecorder->supportedResolutions();
203        for (const QSize &resolution : supportedResolutions) {
204            qDebug() << "video resolution: " << resolution.width() << "x" << resolution.height();
205        }
206
207        const QStringList supportedAudioCodecs = m_mediaRecorder->supportedAudioCodecs();
208        for (const QString &codecName : supportedAudioCodecs) {
209            QString description = m_mediaRecorder->audioCodecDescription(codecName);
210            qDebug() << "audio codec:" << codecName + ": " + description;
211        }
212
213        const QStringList supportedVideoCodecs = m_mediaRecorder->supportedVideoCodecs();
214        for (const QString &codecName : supportedVideoCodecs) {
215            QString description = m_mediaRecorder->videoCodecDescription(codecName);
216            qDebug() << "video codec:" << codecName + ": " + description;
217        }
218
219        const QStringList formats = m_mediaRecorder->supportedContainers();
220        for (const QString &format : formats) {
221<<<<<<< Updated upstream
222            QString description = m_mediaRecorder->containerDescription(format);
223            qDebug() << "container: " << format << ": " << description;
224        }
225=======
226            qDebug() << format;
227        }
228
229        supportedResolutions = m_mediaRecorder->supportedResolutions();
230        for (const QSize &resolution : supportedResolutions) {
231            if(size.width()<resolution.width() && size.height()<resolution.height())
232                size = resolution;
233        }
234
235        m_audioSettings.setCodec("audio/mpeg");
236        m_audioSettings.setQuality(QMultimedia::VeryHighQuality);
237        m_videoSettings.setCodec("video/x-h264");
238        m_videoSettings.setQuality(QMultimedia::VeryHighQuality);
239        m_videoSettings.setResolution(size);
240        m_mediaRecorder->setAudioSettings(m_audioSettings);
241        m_mediaRecorder->setVideoSettings(m_videoSettings);
242        m_mediaRecorder->setContainerFormat("video/quicktime, variant=(string)iso");
243        break;
244    }
245    default:
246        break;
247>>>>>>> Stashed changes
248    }
249}
250
251QPushButton* qtCamera::getButton()
252{
253    QPushButton *button = new QPushButton;
254    button->setFixedSize(144, 70);
255    return button;
256}
257
258void qtCamera::updateRecordTime()
259{
260    QString str = QString("Recorded %1 sec").arg(m_mediaRecorder->duration()/1000);
261    statusBar()->showMessage(str);
262}
263
264void qtCamera::record()
265{
266    QFileInfo fi;
267    QString lo;
268
269    lo = locationDir + "/" + "VIDEO" + QString::number(videoCnt) + ".mov";
270    fi = QFileInfo(lo);
271
272    while(fi.isFile()){
273        videoCnt++;
274        lo = locationDir + "/" + "VIDEO" + QString::number(videoCnt) + ".mov";
275        fi = QFileInfo(lo);
276    }
277
278    m_mediaRecorder->setOutputLocation(QUrl::fromLocalFile(lo));
279    m_mediaRecorder->record();
280    updateRecordTime();
281}
282
283void qtCamera::stop()
284{
285    m_mediaRecorder->stop();
286}
287
288void qtCamera::takeImage()
289{
290    m_isCapturingImage = true;
291    QFileInfo fi;
292    QString lo;
293
294    lo = locationDir + "/" + "PIC" + QString::number(imageCnt) + ".jpg";
295    fi = QFileInfo(lo);
296
297    while(fi.isFile()){
298        imageCnt++;
299        lo = locationDir + "/" + "PIC" + QString::number(imageCnt) + ".jpg";
300        fi = QFileInfo(lo);
301    }
302
303    m_imageCapture->capture(lo);
304}
305
306void qtCamera::displayCaptureError(int id, const QCameraImageCapture::Error error, const QString &errorString)
307{
308    Q_UNUSED(id);
309    Q_UNUSED(error);
310    QMessageBox::warning(this, tr("Image Capture Error"), errorString);
311    m_isCapturingImage = false;
312}
313
314void qtCamera::updateCaptureMode()
315{
316    QCamera::CaptureModes captureMode;
317    QString capture;
318    if (cameraMode.compare(QCAMERA_CAPTURE_MODE)){
319        captureMode = QCamera::CaptureStillImage ;
320    }else {
321        captureMode = QCamera::CaptureVideo;
322    }
323
324    if (m_camera->isCaptureModeSupported(captureMode)){
325        m_camera->unload();
326        m_camera->setCaptureMode(captureMode);
327        m_camera->start();
328        if(captureMode == QCamera::CaptureStillImage){
329            cameraMode = QString(QCAMERA_CAPTURE_MODE);
330            capture = "Capture";
331        }else {
332            cameraMode = QString(QCAMERA_VIDEO_MODE);
333            capture = "Record";
334        }
335        modeButton->setText(cameraMode);
336        captureButton->setText(capture);
337    }
338}
339
340void qtCamera::updateCameraState(QCamera::State state)
341{
342    switch (state) {
343    case QCamera::ActiveState:
344        break;
345    case QCamera::UnloadedState:
346    case QCamera::LoadedState:
347        break;
348    }
349}
350
351void qtCamera::updateRecorderState(QMediaRecorder::State state)
352{
353    switch (state) {
354    case QMediaRecorder::StoppedState:
355        captureButton->setText(tr("Record"));
356        break;
357    case QMediaRecorder::PausedState:
358        break;
359    case QMediaRecorder::RecordingState:
360        captureButton->setText(tr("Recording"));
361        break;
362    }
363}
364
365void qtCamera::displayRecorderError()
366{
367    QMessageBox::warning(this, tr("Capture Error"), m_mediaRecorder->errorString());
368}
369
370void qtCamera::displayCameraError()
371{
372    QMessageBox::warning(this, tr("Camera Error"), m_camera->errorString());
373}
374
375void qtCamera::imageSaved(int id, const QString &fileName)
376{
377    Q_UNUSED(id);
378    statusBar()->showMessage(tr("Captured \"%1\"").arg(QDir::toNativeSeparators(fileName)));
379    statusBar()->show();
380    m_isCapturingImage = false;
381    if (m_applicationExiting)
382        close();
383}
384
385void qtCamera::closeEvent(QCloseEvent *event)
386{
387    if (m_isCapturingImage) {
388        setEnabled(false);
389        m_applicationExiting = true;
390        event->ignore();
391    } else {
392        event->accept();
393    }
394}
395
396void qtCamera::on_cameraSwitch()
397{
398    QList<QPushButton *> buttons = centralWidget()->findChildren<QPushButton *>();
399    for(auto *but: buttons){
400        if(but->isChecked()){
401            for(auto *button: buttons){
402                if(button->isDefault())
403                    button->setDefault(false);
404            }
405            but->setDefault(true);
406            but->setChecked(false);
407            qDebug() << "switch to " + but->text();
408            const QList<QCameraInfo> availableCameras = QCameraInfo::availableCameras();
409            for (const QCameraInfo &cameraInfo : availableCameras) {
410                if(! but->text().compare(cameraInfo.description())){
411                    qDebug() << cameraInfo.description();
412                    setCamera(cameraInfo);
413                }
414            }
415            break;
416        }
417    }
418}
419
420void qtCamera::on_captureClicked()
421{
422    if (m_camera->captureMode() == QCamera::CaptureStillImage) {
423        takeImage();
424    } else {
425        if (m_mediaRecorder->state() == QMediaRecorder::RecordingState)
426            stop();
427        else
428            record();
429    }
430}
431
432void qtCamera::on_exitClicked()
433{
434        qApp->exit(0);
435}
436