xref: /OK3568_Linux_fs/app/forlinx/forlinx_qt/qcamera/qtcamera.cpp (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 #define FONT_SIZE 12
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)
Q_DECLARE_METATYPE(QCameraInfo)71 Q_DECLARE_METATYPE(QCameraInfo)
72 
73 qtCamera::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 
initlayout()89 void qtCamera::initlayout()
90 {
91     QBoxLayout *vLayout = new QVBoxLayout();
92     const QRect availableGeometry = QApplication::desktop()->availableGeometry(this);
93     QFont font;
94     font.setPixelSize(FONT_SIZE);
95     resize(availableGeometry.width(), availableGeometry.height());
96 
97     const QList<QCameraInfo> availableCameras = QCameraInfo::availableCameras();
98     for (const QCameraInfo &cameraInfo : availableCameras) {
99         qDebug() << cameraInfo.description();
100 		if ((cameraInfo.description().contains("rkisp_selfpath",Qt::CaseSensitive))
101 				|| (cameraInfo.description().contains("rawwr",Qt::CaseSensitive)))
102 			continue;
103         QPushButton *camera = getButton();
104         camera->setText(cameraInfo.description());
105         camera->setFont(font);
106         camera->setCheckable(true);
107         if (cameraInfo == QCameraInfo::defaultCamera()){
108             camera->setDefault(true);
109         }else {
110             camera->setDefault(false);
111         }
112         connect(camera, SIGNAL(clicked(bool)), this, SLOT(on_cameraSwitch()));
113         vLayout->addWidget(camera);
114     }
115 
116     modeButton = getButton();
117     modeButton->setText(QString(QCAMERA_CAPTURE_MODE));
118     modeButton->setFont(font);
119     connect(modeButton, SIGNAL(clicked(bool)), this, SLOT(updateCaptureMode()));
120 
121     captureButton = getButton();
122     captureButton->setText(tr("Capture"));
123     captureButton->setFont(font);
124     connect(captureButton, SIGNAL(clicked(bool)), this, SLOT(on_captureClicked()));
125 
126     exitButton = getButton();
127     exitButton->setText(tr("Exit"));
128     exitButton->setFont(font);
129     connect(exitButton, SIGNAL(clicked(bool)), this, SLOT(on_exitClicked()));
130 
131     vLayout->addWidget(modeButton);
132     vLayout->addWidget(captureButton);
133     vLayout->addWidget(exitButton);
134     vLayout->setAlignment(Qt::AlignTop);
135 
136     viewfinder.setWindowFlag(Qt::FramelessWindowHint);
137     //viewfinder.setFixedSize(availableGeometry.width() - 150, availableGeometry.height());
138 
139     QBoxLayout *hlayout = new QHBoxLayout;
140     hlayout->setMargin(0);
141     hlayout->addWidget(&viewfinder);
142     hlayout->addLayout(vLayout);
143 
144     QWidget *widget = new QWidget;
145     widget->setLayout(hlayout);
146     setCentralWidget(widget);
147     //setWindowState(Qt::WindowMaximized);
148     setWindowFlags(Qt::FramelessWindowHint);
149 }
150 
setCamera(const QCameraInfo & cameraInfo)151 void qtCamera::setCamera(const QCameraInfo &cameraInfo)
152 {
153     m_camera.reset(new QCamera(cameraInfo));
154 
155     connect(m_camera.data(), &QCamera::stateChanged, this, &qtCamera::updateCameraState);
156     connect(m_camera.data(), QOverload<QCamera::Error>::of(&QCamera::error), this, &qtCamera::displayCameraError);
157 
158     m_mediaRecorder.reset(new QMediaRecorder(m_camera.data()));
159     connect(m_mediaRecorder.data(), &QMediaRecorder::stateChanged, this, &qtCamera::updateRecorderState);
160 
161     m_imageCapture.reset(new QCameraImageCapture(m_camera.data()));
162 
163     connect(m_mediaRecorder.data(), &QMediaRecorder::durationChanged, this, &qtCamera::updateRecordTime);
164     connect(m_mediaRecorder.data(), QOverload<QMediaRecorder::Error>::of(&QMediaRecorder::error),
165             this, &qtCamera::displayRecorderError);
166 
167     m_mediaRecorder->setMetaData(QMediaMetaData::Title, QVariant(QLatin1String("Test Title")));
168 
169     configureCaptureSettings();
170 
171     m_camera->setViewfinder(&viewfinder);
172 
173     updateCameraState(m_camera->state());
174     updateRecorderState(m_mediaRecorder->state());
175 
176     connect(m_imageCapture.data(), &QCameraImageCapture::imageSaved, this, &qtCamera::imageSaved);
177     connect(m_imageCapture.data(), QOverload<int, QCameraImageCapture::Error, const QString &>::of(&QCameraImageCapture::error),
178             this, &qtCamera::displayCaptureError);
179 
180     updateCaptureMode();
181 }
182 
configureCaptureSettings()183 void qtCamera::configureCaptureSettings()
184 {
185     QSize size(640, 480);
186 
187     m_imageSettings.setCodec("jpeg");
188     m_imageSettings.setQuality(QMultimedia::VeryHighQuality);
189     m_imageSettings.setResolution(size);
190     m_imageCapture->setEncodingSettings(m_imageSettings);
191 
192     m_audioSettings.setCodec("audio/x-adpcm");
193     m_audioSettings.setChannelCount(2);
194     m_audioSettings.setQuality(QMultimedia::NormalQuality);
195     m_mediaRecorder->setAudioSettings(m_audioSettings);
196 
197 	m_videoSettings.setCodec("video/x-h264");
198 
199     m_videoSettings.setResolution(size);
200     m_videoSettings.setQuality(QMultimedia::NormalQuality);
201     m_mediaRecorder->setVideoSettings(m_videoSettings);
202 
203     m_mediaRecorder->setContainerFormat("video/quicktime");
204 
205     if (0) {
206         QList<QSize> supportedResolutions;
207         supportedResolutions = m_imageCapture->supportedResolutions();
208         for (const QSize &resolution : supportedResolutions) {
209              qDebug() << "image resolution: " << resolution.width() << "x" << resolution.height();
210         }
211 
212         supportedResolutions = m_mediaRecorder->supportedResolutions();
213         for (const QSize &resolution : supportedResolutions) {
214             qDebug() << "video resolution: " << resolution.width() << "x" << resolution.height();
215         }
216 
217         const QStringList supportedAudioCodecs = m_mediaRecorder->supportedAudioCodecs();
218         for (const QString &codecName : supportedAudioCodecs) {
219             QString description = m_mediaRecorder->audioCodecDescription(codecName);
220             qDebug() << "audio codec:" << codecName + ": " + description;
221         }
222 
223         const QStringList supportedVideoCodecs = m_mediaRecorder->supportedVideoCodecs();
224         for (const QString &codecName : supportedVideoCodecs) {
225             QString description = m_mediaRecorder->videoCodecDescription(codecName);
226             qDebug() << "video codec:" << codecName + ": " + description;
227         }
228 
229         const QStringList formats = m_mediaRecorder->supportedContainers();
230         for (const QString &format : formats) {
231             QString description = m_mediaRecorder->containerDescription(format);
232             qDebug() << "container: " << format << ": " << description;
233         }
234     }
235 }
236 
getButton()237 QPushButton* qtCamera::getButton()
238 {
239     QPushButton *button = new QPushButton;
240     button->setFixedSize(144, 70);
241     return button;
242 }
243 
updateRecordTime()244 void qtCamera::updateRecordTime()
245 {
246     quint32 dura_smal;
247     quint64 duration;
248 
249     dura_smal = m_mediaRecorder->duration() % 1000;
250     duration = m_mediaRecorder->duration() / 1000;
251     if (dura_smal >= 500)
252         duration += 1;
253 
254     QString str = QString("Recorded %1 sec").arg(duration);
255     statusBar()->showMessage(str);
256 }
257 
record()258 void qtCamera::record()
259 {
260     QFileInfo fi;
261     QString lo;
262 
263     lo = locationDir + "/" + "VIDEO" + QString::number(videoCnt) + ".mov";
264     fi = QFileInfo(lo);
265 
266     while(fi.isFile()){
267         videoCnt++;
268         lo = locationDir + "/" + "VIDEO" + QString::number(videoCnt) + ".mov";
269         fi = QFileInfo(lo);
270     }
271 
272     m_mediaRecorder->setOutputLocation(QUrl::fromLocalFile(lo));
273     m_mediaRecorder->record();
274     updateRecordTime();
275 }
276 
stop()277 void qtCamera::stop()
278 {
279     m_mediaRecorder->stop();
280 }
281 
takeImage()282 void qtCamera::takeImage()
283 {
284     m_isCapturingImage = true;
285     QFileInfo fi;
286     QString lo;
287 
288     lo = locationDir + "/" + "PIC" + QString::number(imageCnt) + ".jpg";
289     fi = QFileInfo(lo);
290 
291     while(fi.isFile()){
292         imageCnt++;
293         lo = locationDir + "/" + "PIC" + QString::number(imageCnt) + ".jpg";
294         fi = QFileInfo(lo);
295     }
296 
297     m_imageCapture->capture(lo);
298 }
299 
displayCaptureError(int id,const QCameraImageCapture::Error error,const QString & errorString)300 void qtCamera::displayCaptureError(int id, const QCameraImageCapture::Error error, const QString &errorString)
301 {
302     Q_UNUSED(id);
303     Q_UNUSED(error);
304     QMessageBox::warning(this, tr("Image Capture Error"), errorString);
305     m_isCapturingImage = false;
306 }
307 
updateCaptureMode()308 void qtCamera::updateCaptureMode()
309 {
310     QCamera::CaptureModes captureMode;
311     QString capture;
312     if (cameraMode.compare(QCAMERA_CAPTURE_MODE)){
313         captureMode = QCamera::CaptureStillImage ;
314     }else {
315         captureMode = QCamera::CaptureVideo;
316     }
317 
318     if (m_camera->isCaptureModeSupported(captureMode)){
319         m_camera->unload();
320         m_camera->setCaptureMode(captureMode);
321         m_camera->start();
322         if(captureMode == QCamera::CaptureStillImage){
323             cameraMode = QString(QCAMERA_CAPTURE_MODE);
324             capture = "Capture";
325         }else {
326             cameraMode = QString(QCAMERA_VIDEO_MODE);
327             capture = "Record";
328         }
329         modeButton->setText(cameraMode);
330         captureButton->setText(capture);
331     }
332 }
333 
updateCameraState(QCamera::State state)334 void qtCamera::updateCameraState(QCamera::State state)
335 {
336     switch (state) {
337     case QCamera::ActiveState:
338         break;
339     case QCamera::UnloadedState:
340     case QCamera::LoadedState:
341         break;
342     }
343 }
344 
updateRecorderState(QMediaRecorder::State state)345 void qtCamera::updateRecorderState(QMediaRecorder::State state)
346 {
347     switch (state) {
348     case QMediaRecorder::StoppedState:
349         captureButton->setText(tr("Record"));
350         break;
351     case QMediaRecorder::PausedState:
352         break;
353     case QMediaRecorder::RecordingState:
354         captureButton->setText(tr("Recording"));
355         break;
356     }
357 }
358 
displayRecorderError()359 void qtCamera::displayRecorderError()
360 {
361     QMessageBox::warning(this, tr("Capture Error"), m_mediaRecorder->errorString());
362 }
363 
displayCameraError()364 void qtCamera::displayCameraError()
365 {
366     QMessageBox::warning(this, tr("Camera Error"), m_camera->errorString());
367 }
368 
imageSaved(int id,const QString & fileName)369 void qtCamera::imageSaved(int id, const QString &fileName)
370 {
371     Q_UNUSED(id);
372     statusBar()->showMessage(tr("Captured \"%1\"").arg(QDir::toNativeSeparators(fileName)));
373     statusBar()->show();
374     m_isCapturingImage = false;
375     if (m_applicationExiting)
376         close();
377 }
378 
closeEvent(QCloseEvent * event)379 void qtCamera::closeEvent(QCloseEvent *event)
380 {
381     if (m_isCapturingImage) {
382         setEnabled(false);
383         m_applicationExiting = true;
384         event->ignore();
385     } else {
386         event->accept();
387     }
388 }
389 
on_cameraSwitch()390 void qtCamera::on_cameraSwitch()
391 {
392     QList<QPushButton *> buttons = centralWidget()->findChildren<QPushButton *>();
393     for(auto *bt: buttons){
394         if(bt->isChecked()){
395             for(auto *button: buttons){
396                 if(button->isDefault())
397                     button->setDefault(false);
398             }
399             bt->setDefault(true);
400             bt->setChecked(false);
401             qDebug() << "switch to " + bt->text();
402             const QList<QCameraInfo> availableCameras = QCameraInfo::availableCameras();
403             for (const QCameraInfo &cameraInfo : availableCameras) {
404                 if(! bt->text().compare(cameraInfo.description())){
405                     qDebug() << cameraInfo.description();
406 					if ((cameraInfo.description().contains("rkisp_selfpath",Qt::CaseSensitive))
407 							|| (cameraInfo.description().contains("rawwr",Qt::CaseSensitive)))
408 						continue;
409 
410                     setCamera(cameraInfo);
411                 }
412             }
413             break;
414         }
415     }
416 }
417 
on_captureClicked()418 void qtCamera::on_captureClicked()
419 {
420     if (m_camera->captureMode() == QCamera::CaptureStillImage) {
421         if(m_imageCapture->isReadyForCapture())
422             takeImage();
423     } else if(m_camera->captureMode() == QCamera::CaptureVideo){
424         if (m_mediaRecorder->state() == QMediaRecorder::RecordingState)
425             stop();
426         else
427             record();
428     }
429 }
430 
on_exitClicked()431 void qtCamera::on_exitClicked()
432 {
433         qApp->exit(0);
434 }
435 
436