Merge lp:~uriboni/qtubuntu-camera/performance-improvements into lp:qtubuntu-camera/staging
- performance-improvements
- Merge into staging
Status: | Merged |
---|---|
Approved by: | Florian Boucault |
Approved revision: | 192 |
Merged at revision: | 178 |
Proposed branch: | lp:~uriboni/qtubuntu-camera/performance-improvements |
Merge into: | lp:qtubuntu-camera/staging |
Diff against target: |
1254 lines (+315/-618) 17 files modified
aalCamera.pro (+0/-1) src/aalimagecapturecontrol.cpp (+63/-133) src/aalimagecapturecontrol.h (+8/-4) src/storagemanager.cpp (+173/-1) src/storagemanager.h (+29/-5) unittests/aalcamerafocuscontrol/aalcamerafocuscontrol.pro (+3/-1) unittests/aalcamerafocuscontrol/aalimagecapturecontrol.cpp (+10/-8) unittests/aalimagecapturecontrol/aalcameraservice.cpp (+0/-99) unittests/aalimagecapturecontrol/aalimagecapturecontrol.pro (+0/-31) unittests/aalimagecapturecontrol/aalimageencodercontrol.cpp (+0/-125) unittests/aalimagecapturecontrol/aalvideorenderercontrol.cpp (+0/-84) unittests/aalimagecapturecontrol/storagemanager.cpp (+0/-50) unittests/aalimagecapturecontrol/tst_aalimagecapturecontrol.cpp (+0/-74) unittests/storagemanager/storagemanager.pro (+5/-0) unittests/storagemanager/tst_storagemanager.cpp (+22/-0) unittests/stubs/storagemanager_stub.cpp (+2/-1) unittests/unittests.pro (+0/-1) |
To merge this branch: | bzr merge lp:~uriboni/qtubuntu-camera/performance-improvements |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Ubuntu Phablet Team | Pending | ||
Review via email: mp+285075@code.launchpad.net |
Commit message
Performance improvements to minimize the time necessary between when pressing the shutter button and being able to capture the next pitcure. Remove sliding out the preview as a part of this.
Description of the change
Performance improvements to minimize the time necessary between when pressing the shutter button and being able to capture the next pitcure. Remove sliding out the preview as a part of this.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:184
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:190
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Florian Boucault (fboucault) wrote : | # |
Attempt to merge into lp:qtubuntu-camera/staging failed due to conflicts:
text conflict in src/aalimagecap
text conflict in src/aalimagecap
deleting parent in unittests/
unversioned parent in unittests/
contents conflict in unittests/
- 192. By Ugo Riboni
-
Remove debug
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:192
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'aalCamera.pro' |
2 | --- aalCamera.pro 2015-11-12 10:32:24 +0000 |
3 | +++ aalCamera.pro 2016-02-11 15:33:06 +0000 |
4 | @@ -5,5 +5,4 @@ |
5 | SUBDIRS += \ |
6 | src \ |
7 | unittests |
8 | - |
9 | OTHER_FILES += .qmake.conf |
10 | |
11 | === modified file 'src/aalimagecapturecontrol.cpp' |
12 | --- src/aalimagecapturecontrol.cpp 2016-01-11 15:10:38 +0000 |
13 | +++ src/aalimagecapturecontrol.cpp 2016-02-11 15:33:06 +0000 |
14 | @@ -19,13 +19,14 @@ |
15 | #include "aalimageencodercontrol.h" |
16 | #include "aalmetadatawritercontrol.h" |
17 | #include "aalvideorenderercontrol.h" |
18 | +#include "aalviewfindersettingscontrol.h" |
19 | #include "storagemanager.h" |
20 | |
21 | #include <hybris/camera/camera_compatibility_layer.h> |
22 | #include <hybris/camera/camera_compatibility_layer_capabilities.h> |
23 | -#include <exiv2/exiv2.hpp> |
24 | |
25 | #include <QDir> |
26 | +#include <QObject> |
27 | #include <QFile> |
28 | #include <QFileInfo> |
29 | #include <QMediaPlayer> |
30 | @@ -34,8 +35,7 @@ |
31 | #include <QGuiApplication> |
32 | #include <QScreen> |
33 | #include <QSettings> |
34 | - |
35 | -#include <cmath> |
36 | +#include <QtConcurrent/QtConcurrent> |
37 | |
38 | AalImageCaptureControl::AalImageCaptureControl(AalCameraService *service, QObject *parent) |
39 | : QCameraImageCaptureControl(parent), |
40 | @@ -43,7 +43,7 @@ |
41 | m_cameraControl(service->cameraControl()), |
42 | m_lastRequestId(0), |
43 | m_ready(false), |
44 | - m_pendingCaptureFile(), |
45 | + m_targetFileName(), |
46 | m_captureCancelled(false), |
47 | m_screenAspectRatio(0.0), |
48 | m_audioPlayer(new QMediaPlayer(this)) |
49 | @@ -55,6 +55,9 @@ |
50 | #else |
51 | m_audioPlayer->setAudioRole(QAudio::NotificationRole); |
52 | #endif |
53 | + |
54 | + QObject::connect(&m_storageManager, &StorageManager::previewReady, |
55 | + this, &AalImageCaptureControl::imageCaptured); |
56 | } |
57 | |
58 | AalImageCaptureControl::~AalImageCaptureControl() |
59 | @@ -76,58 +79,24 @@ |
60 | return m_lastRequestId; |
61 | } |
62 | |
63 | + m_targetFileName = fileName; |
64 | m_captureCancelled = false; |
65 | - QFileInfo fi(fileName); |
66 | - if (fileName.isEmpty() || fi.isDir()) { |
67 | - m_pendingCaptureFile = m_storageManager.nextPhotoFileName(fileName); |
68 | - } else { |
69 | - m_pendingCaptureFile = fileName; |
70 | - } |
71 | - bool diskOk = m_storageManager.checkDirectory(m_pendingCaptureFile); |
72 | - if (!diskOk) { |
73 | - emit error(m_lastRequestId, QCameraImageCapture::ResourceError, |
74 | - QString("Won't be able to save file %1 to disk").arg(m_pendingCaptureFile)); |
75 | - return m_lastRequestId; |
76 | - } |
77 | |
78 | AalMetaDataWriterControl* metadataControl = m_service->metadataWriterControl(); |
79 | - |
80 | int rotation = metadataControl->correctedOrientation(); |
81 | android_camera_set_rotation(m_service->androidControl(), rotation); |
82 | |
83 | - QStringList availableMetadata = metadataControl->availableMetaData(); |
84 | - if (availableMetadata.contains("GPSLatitude") && |
85 | - availableMetadata.contains("GPSLongitude") && |
86 | - availableMetadata.contains("GPSTimeStamp")) { |
87 | - float latitude = metadataControl->metaData("GPSLatitude").toFloat(); |
88 | - float longitude = metadataControl->metaData("GPSLongitude").toFloat(); |
89 | - float altitude = 0.0f; |
90 | - if (availableMetadata.contains("GPSAltitude")) { |
91 | - altitude = metadataControl->metaData("GPSAltitude").toFloat(); |
92 | - } |
93 | - QDateTime timestamp = metadataControl->metaData("GPSTimeStamp").toDateTime(); |
94 | - QString processingMethod = metadataControl->metaData("GPSProcessingMethod").toString(); |
95 | - android_camera_set_location(m_service->androidControl(), |
96 | - &latitude, &longitude, &altitude, |
97 | - timestamp.toTime_t(), |
98 | - processingMethod.toLocal8Bit().constData()); |
99 | - } |
100 | - |
101 | android_camera_take_snapshot(m_service->androidControl()); |
102 | |
103 | m_service->updateCaptureReady(); |
104 | |
105 | - m_service->videoOutputControl()->createPreview(); |
106 | - |
107 | - m_service->metadataWriterControl()->clearAllMetaData(); |
108 | - |
109 | return m_lastRequestId; |
110 | } |
111 | |
112 | void AalImageCaptureControl::cancelCapture() |
113 | { |
114 | m_captureCancelled = true; |
115 | - m_pendingCaptureFile.clear(); |
116 | + m_targetFileName.clear(); |
117 | } |
118 | |
119 | void AalImageCaptureControl::shutterCB(void *context) |
120 | @@ -140,7 +109,14 @@ |
121 | void AalImageCaptureControl::saveJpegCB(void *data, uint32_t data_size, void *context) |
122 | { |
123 | Q_UNUSED(context); |
124 | - AalCameraService::instance()->imageCaptureControl()->saveJpeg(data, data_size); |
125 | + |
126 | + // Copy the data buffer so that it is safe to pass it off to another thread, |
127 | + // since it will be destroyed once this function returns |
128 | + QByteArray dataCopy((const char*)data, data_size); |
129 | + |
130 | + QMetaObject::invokeMethod(AalCameraService::instance()->imageCaptureControl(), |
131 | + "saveJpeg", Qt::QueuedConnection, |
132 | + Q_ARG(QByteArray, dataCopy)); |
133 | } |
134 | |
135 | void AalImageCaptureControl::init(CameraControl *control, CameraControlListener *listener) |
136 | @@ -153,12 +129,6 @@ |
137 | connect(m_service->videoOutputControl(), SIGNAL(previewReady()), this, SLOT(onPreviewReady())); |
138 | } |
139 | |
140 | -void AalImageCaptureControl::onPreviewReady() |
141 | -{ |
142 | - // The preview image was fully captured, notify the UI layer |
143 | - Q_EMIT imageCaptured(m_lastRequestId, m_service->videoOutputControl()->preview()); |
144 | -} |
145 | - |
146 | void AalImageCaptureControl::setReady(bool ready) |
147 | { |
148 | if (m_ready != ready) { |
149 | @@ -169,7 +139,7 @@ |
150 | |
151 | bool AalImageCaptureControl::isCaptureRunning() const |
152 | { |
153 | - return !m_pendingCaptureFile.isNull(); |
154 | + return !m_targetFileName.isEmpty(); |
155 | } |
156 | |
157 | void AalImageCaptureControl::shutter() |
158 | @@ -181,96 +151,56 @@ |
159 | Q_EMIT imageExposed(m_lastRequestId); |
160 | } |
161 | |
162 | -bool AalImageCaptureControl::updateJpegMetadata(void* data, uint32_t dataSize, QTemporaryFile* destination) |
163 | -{ |
164 | - if (data == 0 || destination == 0) return false; |
165 | - |
166 | - Exiv2::Image::AutoPtr image; |
167 | - try { |
168 | - image = Exiv2::ImageFactory::open(static_cast<Exiv2::byte*>(data), dataSize); |
169 | - if (!image.get()) { |
170 | - return false; |
171 | - } |
172 | - } catch(const Exiv2::AnyError&) { |
173 | - return false; |
174 | - } |
175 | - |
176 | - try { |
177 | - image->readMetadata(); |
178 | - Exiv2::ExifData ed = image->exifData(); |
179 | - const QString now = QDateTime::currentDateTime().toString("yyyy:MM:dd HH:mm:ss"); |
180 | - ed["Exif.Photo.DateTimeOriginal"].setValue(now.toStdString()); |
181 | - ed["Exif.Photo.DateTimeDigitized"].setValue(now.toStdString()); |
182 | - image->setExifData(ed); |
183 | - image->writeMetadata(); |
184 | - } catch(const Exiv2::AnyError&) { |
185 | - return false; |
186 | - } |
187 | - |
188 | - if (!destination->open()) { |
189 | - return false; |
190 | - } |
191 | - |
192 | - try { |
193 | - Exiv2::BasicIo& io = image->io(); |
194 | - char* modifiedMetadata = reinterpret_cast<char*>(io.mmap()); |
195 | - const long size = io.size(); |
196 | - const qint64 writtenSize = destination->write(modifiedMetadata, size); |
197 | - io.munmap(); |
198 | - destination->close(); |
199 | - return (writtenSize == size); |
200 | - |
201 | - } catch(const Exiv2::AnyError&) { |
202 | - destination->close(); |
203 | - return false; |
204 | - } |
205 | -} |
206 | - |
207 | -void AalImageCaptureControl::saveJpeg(void *data, uint32_t dataSize) |
208 | +void AalImageCaptureControl::saveJpeg(const QByteArray& data) |
209 | { |
210 | if (m_captureCancelled) { |
211 | m_captureCancelled = false; |
212 | return; |
213 | } |
214 | |
215 | - if (m_pendingCaptureFile.isNull() || !m_service->androidControl()) |
216 | - return; |
217 | - |
218 | - QTemporaryFile file; |
219 | - if (!updateJpegMetadata(data, dataSize, &file)) { |
220 | - qWarning() << "Failed to update EXIF timestamps. Picture will be saved as UTC timezone."; |
221 | - if (!file.open()) { |
222 | - emit error(m_lastRequestId, QCameraImageCapture::ResourceError, |
223 | - QString("Could not open temprary file %1").arg(file.fileName())); |
224 | - m_pendingCaptureFile.clear(); |
225 | - m_service->updateCaptureReady(); |
226 | - return; |
227 | - } |
228 | - |
229 | - const qint64 writtenSize = file.write(static_cast<const char*>(data), dataSize); |
230 | - file.close(); |
231 | - if (writtenSize != dataSize) { |
232 | - emit error(m_lastRequestId, QCameraImageCapture::ResourceError, |
233 | - QString("Could not write file %1").arg(file.fileName())); |
234 | - m_pendingCaptureFile.clear(); |
235 | - m_service->updateCaptureReady(); |
236 | - return; |
237 | - } |
238 | - } |
239 | - |
240 | - QFile finalFile(file.fileName()); |
241 | - bool ok = finalFile.rename(m_pendingCaptureFile); |
242 | - if (!ok) { |
243 | - emit error(m_lastRequestId, QCameraImageCapture::ResourceError, |
244 | - QString("Could not save image to %1").arg(m_pendingCaptureFile)); |
245 | - m_pendingCaptureFile.clear(); |
246 | - m_service->updateCaptureReady(); |
247 | - return; |
248 | - } |
249 | - |
250 | - Q_EMIT imageSaved(m_lastRequestId, m_pendingCaptureFile); |
251 | - m_pendingCaptureFile.clear(); |
252 | - |
253 | - android_camera_start_preview(m_service->androidControl()); |
254 | + // Copy the metadata so that we can clear its container |
255 | + QVariantMap metadata; |
256 | + AalMetaDataWriterControl* metadataControl = m_service->metadataWriterControl(); |
257 | + Q_FOREACH(QString key, metadataControl->availableMetaData()) { |
258 | + metadata.insert(key, metadataControl->metaData(key)); |
259 | + } |
260 | + m_service->metadataWriterControl()->clearAllMetaData(); |
261 | + |
262 | + QString fileName = m_targetFileName; |
263 | + m_targetFileName.clear(); |
264 | + |
265 | + AalViewfinderSettingsControl* viewfinder = m_service->viewfinderControl(); |
266 | + QSize resolution = viewfinder->viewfinderParameter(QCameraViewfinderSettingsControl::Resolution).toSize(); |
267 | + |
268 | + // Restart the viewfinder and notify that the camera is ready to capture again |
269 | + if (m_service->androidControl()) { |
270 | + android_camera_start_preview(m_service->androidControl()); |
271 | + } |
272 | m_service->updateCaptureReady(); |
273 | + |
274 | + DiskWriteWatcher* watcher = new DiskWriteWatcher(this); |
275 | + QObject::connect(watcher, &QFutureWatcher<QString>::finished, this, &AalImageCaptureControl::onImageFileSaved); |
276 | + m_pendingSaveOperations.insert(watcher, m_lastRequestId); |
277 | + |
278 | + QFuture<SaveToDiskResult> future = QtConcurrent::run(&m_storageManager, &StorageManager::saveJpegImage, |
279 | + data, metadata, fileName, resolution, m_lastRequestId); |
280 | + watcher->setFuture(future); |
281 | +} |
282 | + |
283 | +void AalImageCaptureControl::onImageFileSaved() |
284 | +{ |
285 | + DiskWriteWatcher* watcher = static_cast<DiskWriteWatcher*>(sender()); |
286 | + |
287 | + if (m_pendingSaveOperations.contains(watcher)) { |
288 | + int requestID = m_pendingSaveOperations.take(watcher); |
289 | + |
290 | + SaveToDiskResult result = watcher->result(); |
291 | + delete watcher; |
292 | + |
293 | + if (result.success) { |
294 | + Q_EMIT imageSaved(requestID, result.fileName); |
295 | + } else { |
296 | + Q_EMIT error(requestID, QCameraImageCapture::ResourceError, result.errorMessage); |
297 | + } |
298 | + } |
299 | } |
300 | |
301 | === modified file 'src/aalimagecapturecontrol.h' |
302 | --- src/aalimagecapturecontrol.h 2016-01-11 15:10:38 +0000 |
303 | +++ src/aalimagecapturecontrol.h 2016-02-11 15:33:06 +0000 |
304 | @@ -20,7 +20,7 @@ |
305 | #include <QCameraImageCaptureControl> |
306 | #include <QSettings> |
307 | #include <QString> |
308 | -#include <QTemporaryFile> |
309 | +#include <QFutureWatcher> |
310 | #include <storagemanager.h> |
311 | |
312 | #include <stdint.h> |
313 | @@ -31,6 +31,8 @@ |
314 | class CameraControlListener; |
315 | class QMediaPlayer; |
316 | |
317 | +typedef QFutureWatcher<SaveToDiskResult> DiskWriteWatcher; |
318 | + |
319 | class AalImageCaptureControl : public QCameraImageCaptureControl |
320 | { |
321 | Q_OBJECT |
322 | @@ -55,13 +57,13 @@ |
323 | |
324 | public Q_SLOTS: |
325 | void init(CameraControl *control, CameraControlListener *listener); |
326 | - void onPreviewReady(); |
327 | + void onImageFileSaved(); |
328 | |
329 | private Q_SLOTS: |
330 | void shutter(); |
331 | + void saveJpeg(const QByteArray& data); |
332 | |
333 | private: |
334 | - void saveJpeg(void* data, uint32_t dataSize); |
335 | bool updateJpegMetadata(void* data, uint32_t dataSize, QTemporaryFile* destination); |
336 | |
337 | AalCameraService *m_service; |
338 | @@ -69,7 +71,7 @@ |
339 | int m_lastRequestId; |
340 | StorageManager m_storageManager; |
341 | bool m_ready; |
342 | - QString m_pendingCaptureFile; |
343 | + QString m_targetFileName; |
344 | bool m_captureCancelled; |
345 | float m_screenAspectRatio; |
346 | /// Maintains a list of highest priority aspect ratio to lowest, for the |
347 | @@ -78,6 +80,8 @@ |
348 | QString m_galleryPath; |
349 | QMediaPlayer *m_audioPlayer; |
350 | QSettings m_settings; |
351 | + |
352 | + QMap<DiskWriteWatcher*, int> m_pendingSaveOperations; |
353 | }; |
354 | |
355 | #endif |
356 | |
357 | === modified file 'src/storagemanager.cpp' |
358 | --- src/storagemanager.cpp 2014-09-10 19:48:00 +0000 |
359 | +++ src/storagemanager.cpp 2016-02-11 15:33:06 +0000 |
360 | @@ -15,12 +15,18 @@ |
361 | */ |
362 | |
363 | #include "storagemanager.h" |
364 | + |
365 | #include <QDateTime> |
366 | #include <QDebug> |
367 | #include <QDir> |
368 | #include <QFileInfo> |
369 | #include <QStandardPaths> |
370 | #include <QCoreApplication> |
371 | +#include <QBuffer> |
372 | +#include <QImageReader> |
373 | + |
374 | +#include <exiv2/exiv2.hpp> |
375 | +#include <cmath> |
376 | |
377 | const QLatin1String photoBase = QLatin1String("image"); |
378 | const QLatin1String videoBase = QLatin1String("video"); |
379 | @@ -28,7 +34,7 @@ |
380 | const QLatin1String videoExtension = QLatin1String("mp4"); |
381 | const QLatin1String dateFormat = QLatin1String("yyyyMMdd_HHmmsszzz"); |
382 | |
383 | -StorageManager::StorageManager() |
384 | +StorageManager::StorageManager(QObject* parent) : QObject(parent) |
385 | { |
386 | } |
387 | |
388 | @@ -87,3 +93,169 @@ |
389 | .arg(date) |
390 | .arg(extension); |
391 | } |
392 | + |
393 | +bool StorageManager::updateJpegMetadata(QByteArray data, QVariantMap metadata, QTemporaryFile* destination) |
394 | +{ |
395 | + if (data.isEmpty() || destination == 0) return false; |
396 | + |
397 | + Exiv2::Image::AutoPtr image; |
398 | + try { |
399 | + image = Exiv2::ImageFactory::open(static_cast<const Exiv2::byte*>((const unsigned char*)data.constData()), data.size()); |
400 | + if (!image.get()) { |
401 | + return false; |
402 | + } |
403 | + } catch(const Exiv2::AnyError&) { |
404 | + return false; |
405 | + } |
406 | + |
407 | + try { |
408 | + image->readMetadata(); |
409 | + Exiv2::ExifData ed = image->exifData(); |
410 | + const QString now = QDateTime::currentDateTime().toString("yyyy:MM:dd HH:mm:ss"); |
411 | + ed["Exif.Photo.DateTimeOriginal"].setValue(now.toStdString()); |
412 | + ed["Exif.Photo.DateTimeDigitized"].setValue(now.toStdString()); |
413 | + |
414 | + if (metadata.contains("GPSLatitude") && |
415 | + metadata.contains("GPSLongitude") && |
416 | + metadata.contains("GPSTimeStamp")) { |
417 | + |
418 | + // Write all GPS metadata according to version 2.2 of the EXIF spec, |
419 | + // which is what Android did. See: http://www.exiv2.org/Exif2-2.PDF |
420 | + const char version[4] = {2, 2, 0, 0}; |
421 | + Exiv2::DataValue versionValue(Exiv2::unsignedByte); |
422 | + versionValue.read((const Exiv2::byte*)version, 4); |
423 | + ed.add(Exiv2::ExifKey("Exif.GPSInfo.GPSVersionID"), &versionValue); |
424 | + |
425 | + // According to the spec, the GPS processing method is a buffer of type Undefined, which |
426 | + // does not need to be zero terminated. It should be prepended by an 8 byte, zero padded |
427 | + // string specifying the encoding. |
428 | + const char methodHeader[8] = {'A', 'S', 'C', 'I', 'I', 0, 0, 0}; |
429 | + QByteArray method = metadata.value("GPSProcessingMethod").toString().toLatin1(); |
430 | + method.prepend(methodHeader, 8); |
431 | + Exiv2::DataValue methodValue(Exiv2::undefined); |
432 | + methodValue.read((const Exiv2::byte*)method.constData(), method.size()); |
433 | + ed.add(Exiv2::ExifKey("Exif.GPSInfo.GPSProcessingMethod"), &methodValue); |
434 | + |
435 | + double latitude = metadata.value("GPSLatitude").toDouble(); |
436 | + ed["Exif.GPSInfo.GPSLatitude"] = decimalToExifRational(latitude).toStdString(); |
437 | + ed["Exif.GPSInfo.GPSLatitudeRef"] = (latitude < 0 ) ? "S" : "N"; |
438 | + |
439 | + double longitude = metadata.value("GPSLongitude").toDouble(); |
440 | + ed["Exif.GPSInfo.GPSLongitude"] = decimalToExifRational(longitude).toStdString(); |
441 | + ed["Exif.GPSInfo.GPSLongitudeRef"] = (longitude < 0 ) ? "W" : "E"; |
442 | + |
443 | + if (metadata.contains("GPSAltitude")) { |
444 | + // Assume altitude precision to the meter |
445 | + unsigned int altitude = floor(metadata.value("GPSAltitude").toDouble()); |
446 | + Exiv2::URationalValue::AutoPtr altitudeValue(new Exiv2::URationalValue); |
447 | + altitudeValue->value_.push_back(std::make_pair(altitude,1)); |
448 | + ed.add(Exiv2::ExifKey("Exif.GPSInfo.GPSAltitude"), altitudeValue.get()); |
449 | + |
450 | + // Byte field of lenght 1. Value of 0 means the reference is sea level. |
451 | + const char reference = 0; |
452 | + Exiv2::DataValue referenceValue(Exiv2::unsignedByte); |
453 | + referenceValue.read((const Exiv2::byte*) &reference, 1); |
454 | + ed.add(Exiv2::ExifKey("Exif.GPSInfo.GPSAltitudeRef"), &referenceValue); |
455 | + } |
456 | + |
457 | + QDateTime stamp = metadata.value("GPSTimeStamp").toDateTime(); |
458 | + ed["Exif.GPSInfo.GPSTimeStamp"] = stamp.toString("HH/1 mm/1 ss/1").toStdString(); |
459 | + ed["Exif.GPSInfo.GPSDateStamp"] = stamp.toString("yyyy:MM:dd").toStdString(); |
460 | + } |
461 | + |
462 | + image->setExifData(ed); |
463 | + image->writeMetadata(); |
464 | + } catch(const Exiv2::AnyError&) { |
465 | + return false; |
466 | + } |
467 | + |
468 | + if (!destination->open()) { |
469 | + return false; |
470 | + } |
471 | + |
472 | + try { |
473 | + Exiv2::BasicIo& io = image->io(); |
474 | + char* modifiedMetadata = reinterpret_cast<char*>(io.mmap()); |
475 | + const long size = io.size(); |
476 | + const qint64 writtenSize = destination->write(modifiedMetadata, size); |
477 | + io.munmap(); |
478 | + destination->close(); |
479 | + return (writtenSize == size); |
480 | + |
481 | + } catch(const Exiv2::AnyError&) { |
482 | + destination->close(); |
483 | + return false; |
484 | + } |
485 | +} |
486 | + |
487 | +SaveToDiskResult StorageManager::saveJpegImage(QByteArray data, QVariantMap metadata, QString fileName, |
488 | + QSize previewResolution, int captureID) |
489 | +{ |
490 | + SaveToDiskResult result; |
491 | + |
492 | + QString captureFile; |
493 | + QFileInfo fi(fileName); |
494 | + if (fileName.isEmpty() || fi.isDir()) { |
495 | + captureFile = nextPhotoFileName(fileName); |
496 | + } else { |
497 | + captureFile = fileName; |
498 | + } |
499 | + result.fileName = captureFile; |
500 | + |
501 | + bool diskOk = checkDirectory(captureFile); |
502 | + if (!diskOk) { |
503 | + result.errorMessage = QString("Won't be able to save file %1 to disk").arg(captureFile); |
504 | + return result; |
505 | + } |
506 | + |
507 | + QBuffer buffer(&data); |
508 | + QImageReader reader(&buffer, "jpg"); |
509 | + |
510 | + QSize scaledSize = reader.size(); // fast, as it does not decode the JPEG |
511 | + scaledSize.scale(previewResolution, Qt::KeepAspectRatio); |
512 | + reader.setScaledSize(scaledSize); |
513 | + reader.setQuality(25); |
514 | + QImage image = reader.read(); |
515 | + Q_EMIT previewReady(captureID, image); |
516 | + |
517 | + QTemporaryFile file; |
518 | + if (!updateJpegMetadata(data, metadata, &file)) { |
519 | + qWarning() << "Failed to update EXIF timestamps. Picture will be saved as UTC timezone."; |
520 | + if (!file.open()) { |
521 | + result.errorMessage = QString("Could not open temprary file %1").arg(file.fileName()); |
522 | + return result; |
523 | + } |
524 | + |
525 | + const qint64 writtenSize = file.write(data); |
526 | + file.close(); |
527 | + if (writtenSize != data.size()) { |
528 | + result.errorMessage = QString("Could not write file %1").arg(fileName); |
529 | + return result; |
530 | + } |
531 | + } |
532 | + |
533 | + QFile finalFile(file.fileName()); |
534 | + bool ok = finalFile.rename(captureFile); |
535 | + if (!ok) { |
536 | + result.errorMessage = QString("Could not save image to %1").arg(fileName); |
537 | + return result; |
538 | + } |
539 | + |
540 | + result.success = true; |
541 | + return result; |
542 | +} |
543 | + |
544 | +QString StorageManager::decimalToExifRational(double decimal) |
545 | +{ |
546 | + decimal = fabs(decimal); |
547 | + unsigned int degrees = floor(decimal); |
548 | + unsigned int minutes = floor((decimal - degrees) * 60); |
549 | + double seconds = (decimal - degrees - minutes / 60) * 3600; |
550 | + seconds = floor(seconds * 100); |
551 | + |
552 | + return QString("%1/1 %2/1 %3/100").arg(degrees).arg(minutes).arg(seconds); |
553 | +} |
554 | + |
555 | +SaveToDiskResult::SaveToDiskResult() : success(false) |
556 | +{ |
557 | +} |
558 | |
559 | === modified file 'src/storagemanager.h' |
560 | --- src/storagemanager.h 2014-09-10 19:48:00 +0000 |
561 | +++ src/storagemanager.h 2016-02-11 15:33:06 +0000 |
562 | @@ -18,19 +18,43 @@ |
563 | #define STORAGEMANAGER_H |
564 | |
565 | #include <QString> |
566 | - |
567 | -class StorageManager |
568 | -{ |
569 | -public: |
570 | - StorageManager(); |
571 | +#include <QVariantMap> |
572 | +#include <QByteArray> |
573 | +#include <QTemporaryFile> |
574 | +#include <QImage> |
575 | + |
576 | +class SaveToDiskResult |
577 | +{ |
578 | +public: |
579 | + SaveToDiskResult(); |
580 | + bool success; |
581 | + QString fileName; |
582 | + QString errorMessage; |
583 | +}; |
584 | + |
585 | +class StorageManager : public QObject |
586 | +{ |
587 | + Q_OBJECT |
588 | + |
589 | +public: |
590 | + explicit StorageManager(QObject* parent = 0); |
591 | |
592 | QString nextPhotoFileName(const QString &directoy = QString()); |
593 | QString nextVideoFileName(const QString &directoy = QString()); |
594 | |
595 | bool checkDirectory(const QString &path) const; |
596 | |
597 | + SaveToDiskResult saveJpegImage(QByteArray data, QVariantMap metadata, |
598 | + QString fileName, QSize previewResolution, |
599 | + int captureID); |
600 | + |
601 | +Q_SIGNALS: |
602 | + void previewReady(int captureID, QImage image); |
603 | + |
604 | private: |
605 | QString fileNameGenerator(const QString &base, const QString &extension); |
606 | + bool updateJpegMetadata(QByteArray data, QVariantMap metadata, QTemporaryFile* destination); |
607 | + QString decimalToExifRational(double decimal); |
608 | |
609 | QString m_directory; |
610 | }; |
611 | |
612 | === modified file 'unittests/aalcamerafocuscontrol/aalcamerafocuscontrol.pro' |
613 | --- unittests/aalcamerafocuscontrol/aalcamerafocuscontrol.pro 2014-01-16 14:20:08 +0000 |
614 | +++ unittests/aalcamerafocuscontrol/aalcamerafocuscontrol.pro 2016-02-11 15:33:06 +0000 |
615 | @@ -10,10 +10,12 @@ |
616 | |
617 | HEADERS += ../../src/aalcamerafocuscontrol.h \ |
618 | ../../src/aalcameraservice.h \ |
619 | - ../../src/aalimagecapturecontrol.h |
620 | + ../../src/aalimagecapturecontrol.h \ |
621 | + ../../src/storagemanager.h |
622 | |
623 | SOURCES += tst_aalcamerafocuscontrol.cpp \ |
624 | ../../src/aalcamerafocuscontrol.cpp \ |
625 | + storagemanager.cpp \ |
626 | aalcameraservice.cpp \ |
627 | aalimagecapturecontrol.cpp |
628 | |
629 | |
630 | === modified file 'unittests/aalcamerafocuscontrol/aalimagecapturecontrol.cpp' |
631 | --- unittests/aalcamerafocuscontrol/aalimagecapturecontrol.cpp 2013-06-05 16:11:12 +0000 |
632 | +++ unittests/aalcamerafocuscontrol/aalimagecapturecontrol.cpp 2016-02-11 15:33:06 +0000 |
633 | @@ -19,10 +19,6 @@ |
634 | #include <hybris/camera/camera_compatibility_layer.h> |
635 | #include <hybris/camera/camera_compatibility_layer_capabilities.h> |
636 | |
637 | -StorageManager::StorageManager() |
638 | -{ |
639 | -} |
640 | - |
641 | AalImageCaptureControl::AalImageCaptureControl(AalCameraService *service, QObject *parent) |
642 | : QCameraImageCaptureControl(parent) |
643 | { |
644 | @@ -54,10 +50,6 @@ |
645 | Q_UNUSED(listener); |
646 | } |
647 | |
648 | -void AalImageCaptureControl::onPreviewReady() |
649 | -{ |
650 | -} |
651 | - |
652 | void AalImageCaptureControl::setReady(bool ready) |
653 | { |
654 | Q_UNUSED(ready); |
655 | @@ -66,3 +58,13 @@ |
656 | void AalImageCaptureControl::shutter() |
657 | { |
658 | } |
659 | + |
660 | +void AalImageCaptureControl::onImageFileSaved() |
661 | +{ |
662 | +} |
663 | + |
664 | +void AalImageCaptureControl::saveJpeg(const QByteArray& data) |
665 | +{ |
666 | + Q_UNUSED(data); |
667 | +} |
668 | + |
669 | |
670 | === removed directory 'unittests/aalimagecapturecontrol' |
671 | === removed file 'unittests/aalimagecapturecontrol/aalcameraservice.cpp' |
672 | --- unittests/aalimagecapturecontrol/aalcameraservice.cpp 2015-12-07 15:16:51 +0000 |
673 | +++ unittests/aalimagecapturecontrol/aalcameraservice.cpp 1970-01-01 00:00:00 +0000 |
674 | @@ -1,99 +0,0 @@ |
675 | -/* |
676 | - * Copyright (C) 2013 Canonical, Ltd. |
677 | - * |
678 | - * This program is free software; you can redistribute it and/or modify |
679 | - * it under the terms of the GNU Lesser General Public License as published by |
680 | - * the Free Software Foundation; version 3. |
681 | - * |
682 | - * This program is distributed in the hope that it will be useful, |
683 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
684 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
685 | - * GNU Lesser General Public License for more details. |
686 | - * |
687 | - * You should have received a copy of the GNU Lesser General Public License |
688 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
689 | - */ |
690 | - |
691 | -#include "aalcameraservice.h" |
692 | - |
693 | -AalCameraService *AalCameraService::m_service = 0; |
694 | - |
695 | -AalCameraService::AalCameraService(QObject *parent) : |
696 | - QMediaService(parent), |
697 | - m_androidControl(0), |
698 | - m_androidListener(0) |
699 | -{ |
700 | -} |
701 | - |
702 | -AalCameraService::~AalCameraService() |
703 | -{ |
704 | -} |
705 | - |
706 | -QMediaControl *AalCameraService::requestControl(const char *name) |
707 | -{ |
708 | - Q_UNUSED(name); |
709 | - return 0; |
710 | -} |
711 | - |
712 | -void AalCameraService::releaseControl(QMediaControl *control) |
713 | -{ |
714 | - Q_UNUSED(control); |
715 | -} |
716 | - |
717 | -CameraControl *AalCameraService::androidControl() |
718 | -{ |
719 | - return m_androidControl; |
720 | -} |
721 | - |
722 | -bool AalCameraService::connectCamera() |
723 | -{ |
724 | - return true; |
725 | -} |
726 | - |
727 | -void AalCameraService::disconnectCamera() |
728 | -{ |
729 | -} |
730 | - |
731 | -void AalCameraService::startPreview() |
732 | -{ |
733 | -} |
734 | - |
735 | -void AalCameraService::stopPreview() |
736 | -{ |
737 | -} |
738 | - |
739 | -bool AalCameraService::isPreviewStarted() const |
740 | -{ |
741 | - return true; |
742 | -} |
743 | - |
744 | -void AalCameraService::onApplicationStateChanged() |
745 | -{ |
746 | -} |
747 | - |
748 | -void AalCameraService::initControls(CameraControl *camControl, CameraControlListener *listener) |
749 | -{ |
750 | - Q_UNUSED(camControl); |
751 | - Q_UNUSED(listener); |
752 | -} |
753 | - |
754 | -bool AalCameraService::isCameraActive() const |
755 | -{ |
756 | - return true; |
757 | -} |
758 | - |
759 | -bool AalCameraService::isBackCameraUsed() const |
760 | -{ |
761 | - return true; |
762 | -} |
763 | - |
764 | -void AalCameraService::updateCaptureReady() |
765 | -{ |
766 | -} |
767 | - |
768 | -QSize AalCameraService::selectSizeWithAspectRatio(const QList<QSize> &sizes, float targetAspectRatio) const |
769 | -{ |
770 | - Q_UNUSED(sizes); |
771 | - Q_UNUSED(targetAspectRatio); |
772 | - return QSize(); |
773 | -} |
774 | |
775 | === removed file 'unittests/aalimagecapturecontrol/aalimagecapturecontrol.pro' |
776 | --- unittests/aalimagecapturecontrol/aalimagecapturecontrol.pro 2014-09-23 18:12:45 +0000 |
777 | +++ unittests/aalimagecapturecontrol/aalimagecapturecontrol.pro 1970-01-01 00:00:00 +0000 |
778 | @@ -1,31 +0,0 @@ |
779 | -include(../../coverage.pri) |
780 | - |
781 | -TARGET = tst_aalimagecapturecontrol |
782 | - |
783 | -QT += testlib multimedia opengl |
784 | - |
785 | -LIBS += -L../mocks/aal -laal |
786 | -INCLUDEPATH += ../../src |
787 | -INCLUDEPATH += ../mocks/aal |
788 | - |
789 | -CONFIG += link_pkgconfig |
790 | -PKGCONFIG += exiv2 |
791 | - |
792 | -HEADERS += ../../src/aalimagecapturecontrol.h \ |
793 | - ../../src/aalcameraservice.h \ |
794 | - ../../src/aalimageencodercontrol.h \ |
795 | - ../../src/aalmetadatawritercontrol.h \ |
796 | - ../../src/aalvideorenderercontrol.h \ |
797 | - ../../src/storagemanager.h |
798 | - |
799 | -SOURCES += tst_aalimagecapturecontrol.cpp \ |
800 | - ../../src/aalimagecapturecontrol.cpp \ |
801 | - aalcameraservice.cpp \ |
802 | - aalimageencodercontrol.cpp \ |
803 | - ../stubs/aalmetadatawritercontrol_stub.cpp \ |
804 | - aalvideorenderercontrol.cpp \ |
805 | - storagemanager.cpp |
806 | - |
807 | -check.depends = $${TARGET} |
808 | -check.commands = ./$${TARGET} |
809 | -QMAKE_EXTRA_TARGETS += check |
810 | |
811 | === removed file 'unittests/aalimagecapturecontrol/aalimageencodercontrol.cpp' |
812 | --- unittests/aalimagecapturecontrol/aalimageencodercontrol.cpp 2015-10-14 21:22:46 +0000 |
813 | +++ unittests/aalimagecapturecontrol/aalimageencodercontrol.cpp 1970-01-01 00:00:00 +0000 |
814 | @@ -1,125 +0,0 @@ |
815 | -/* |
816 | - * Copyright (C) 2013-2014 Canonical, Ltd. |
817 | - * |
818 | - * This program is free software; you can redistribute it and/or modify |
819 | - * it under the terms of the GNU Lesser General Public License as published by |
820 | - * the Free Software Foundation; version 3. |
821 | - * |
822 | - * This program is distributed in the hope that it will be useful, |
823 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
824 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
825 | - * GNU Lesser General Public License for more details. |
826 | - * |
827 | - * You should have received a copy of the GNU Lesser General Public License |
828 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
829 | - */ |
830 | - |
831 | -#include <QImageEncoderControl> |
832 | -#include <QList> |
833 | -#include <QString> |
834 | -#include <QStringList> |
835 | - |
836 | -#include <QDebug> |
837 | - |
838 | -#include "aalimageencodercontrol.h" |
839 | - |
840 | -AalImageEncoderControl::AalImageEncoderControl(AalCameraService *service, QObject *parent) |
841 | - : QImageEncoderControl(parent), |
842 | - m_service(service), |
843 | - m_currentSize() |
844 | -{ |
845 | -} |
846 | - |
847 | -AalImageEncoderControl::~AalImageEncoderControl() |
848 | -{ |
849 | -} |
850 | - |
851 | -QString AalImageEncoderControl::imageCodecDescription(const QString &codec) const |
852 | -{ |
853 | - Q_UNUSED(codec); |
854 | - return QString(); |
855 | -} |
856 | - |
857 | -QImageEncoderSettings AalImageEncoderControl::imageSettings() const |
858 | -{ |
859 | - return QImageEncoderSettings(); |
860 | -} |
861 | - |
862 | -void AalImageEncoderControl::setImageSettings(const QImageEncoderSettings &settings) |
863 | -{ |
864 | - Q_UNUSED(settings); |
865 | -} |
866 | - |
867 | -QStringList AalImageEncoderControl::supportedImageCodecs() const |
868 | -{ |
869 | - return QStringList(); |
870 | -} |
871 | - |
872 | -QList<QSize> AalImageEncoderControl::supportedResolutions(const QImageEncoderSettings &settings, bool *continuous) const |
873 | -{ |
874 | - Q_UNUSED(settings); |
875 | - Q_UNUSED(continuous); |
876 | - |
877 | - return QList<QSize>(); |
878 | -} |
879 | - |
880 | -QList<QSize> AalImageEncoderControl::supportedThumbnailResolutions(const QImageEncoderSettings &settings, bool *continuous) const |
881 | -{ |
882 | - Q_UNUSED(settings); |
883 | - Q_UNUSED(continuous); |
884 | - |
885 | - return QList<QSize>(); |
886 | -} |
887 | - |
888 | -void AalImageEncoderControl::init(CameraControl *control) |
889 | -{ |
890 | - Q_UNUSED(control); |
891 | -} |
892 | - |
893 | -bool AalImageEncoderControl::setSize(const QSize &size) |
894 | -{ |
895 | - Q_UNUSED(size); |
896 | - return true; |
897 | -} |
898 | - |
899 | -void AalImageEncoderControl::resetAllSettings() |
900 | -{ |
901 | -} |
902 | - |
903 | -void AalImageEncoderControl::getPictureSizeCb(void *ctx, int width, int height) |
904 | -{ |
905 | - Q_UNUSED(ctx); |
906 | - Q_UNUSED(width); |
907 | - Q_UNUSED(height); |
908 | -} |
909 | - |
910 | -void AalImageEncoderControl::getPictureSize(int width, int height) |
911 | -{ |
912 | - Q_UNUSED(width); |
913 | - Q_UNUSED(height); |
914 | -} |
915 | - |
916 | -void AalImageEncoderControl::getThumbnailSizeCb(void *ctx, int width, int height) |
917 | -{ |
918 | - Q_UNUSED(ctx); |
919 | - Q_UNUSED(width); |
920 | - Q_UNUSED(height); |
921 | -} |
922 | - |
923 | -void AalImageEncoderControl::getThumbnailSize(int width, int height) |
924 | -{ |
925 | - Q_UNUSED(width); |
926 | - Q_UNUSED(height); |
927 | -} |
928 | - |
929 | -QMultimedia::EncodingQuality AalImageEncoderControl::jpegQualityToQtEncodingQuality(int jpegQuality) |
930 | -{ |
931 | - Q_UNUSED(jpegQuality) |
932 | - return QMultimedia::NormalQuality; |
933 | -} |
934 | - |
935 | -int AalImageEncoderControl::qtEncodingQualityToJpegQuality(QMultimedia::EncodingQuality quality) |
936 | -{ |
937 | - Q_UNUSED(quality) |
938 | - return 100; |
939 | -} |
940 | |
941 | === removed file 'unittests/aalimagecapturecontrol/aalvideorenderercontrol.cpp' |
942 | --- unittests/aalimagecapturecontrol/aalvideorenderercontrol.cpp 2015-12-07 15:16:51 +0000 |
943 | +++ unittests/aalimagecapturecontrol/aalvideorenderercontrol.cpp 1970-01-01 00:00:00 +0000 |
944 | @@ -1,84 +0,0 @@ |
945 | -/* |
946 | - * Copyright (C) 2013 Canonical, Ltd. |
947 | - * |
948 | - * This program is free software; you can redistribute it and/or modify |
949 | - * it under the terms of the GNU Lesser General Public License as published by |
950 | - * the Free Software Foundation; version 3. |
951 | - * |
952 | - * This program is distributed in the hope that it will be useful, |
953 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
954 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
955 | - * GNU Lesser General Public License for more details. |
956 | - * |
957 | - * You should have received a copy of the GNU Lesser General Public License |
958 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
959 | - */ |
960 | - |
961 | -#include "aalvideorenderercontrol.h" |
962 | -#include "aalcameraservice.h" |
963 | - |
964 | - |
965 | -AalVideoRendererControl::AalVideoRendererControl(AalCameraService *service, QObject *parent) |
966 | - : QVideoRendererControl(parent) |
967 | - , m_surface(0), |
968 | - m_service(service), |
969 | - m_viewFinderRunning(false), |
970 | - m_textureId(0) |
971 | -{ |
972 | -} |
973 | - |
974 | -AalVideoRendererControl::~AalVideoRendererControl() |
975 | -{ |
976 | -} |
977 | - |
978 | -QAbstractVideoSurface *AalVideoRendererControl::surface() const |
979 | -{ |
980 | - return m_surface; |
981 | -} |
982 | - |
983 | -void AalVideoRendererControl::setSurface(QAbstractVideoSurface *surface) |
984 | -{ |
985 | - Q_UNUSED(surface); |
986 | -} |
987 | - |
988 | -void AalVideoRendererControl::init(CameraControl *control, CameraControlListener *listener) |
989 | -{ |
990 | - Q_UNUSED(control); |
991 | - Q_UNUSED(listener); |
992 | -} |
993 | - |
994 | -void AalVideoRendererControl::startPreview() |
995 | -{ |
996 | -} |
997 | - |
998 | -void AalVideoRendererControl::stopPreview() |
999 | -{ |
1000 | -} |
1001 | - |
1002 | -bool AalVideoRendererControl::isPreviewStarted() const |
1003 | -{ |
1004 | - return true; |
1005 | -} |
1006 | - |
1007 | -void AalVideoRendererControl::updateViewfinderFrame() |
1008 | -{ |
1009 | -} |
1010 | - |
1011 | -void AalVideoRendererControl::onTextureCreated(unsigned int textureID) |
1012 | -{ |
1013 | - Q_UNUSED(textureID); |
1014 | -} |
1015 | - |
1016 | -void AalVideoRendererControl::onSnapshotTaken(QImage snapshotImage) |
1017 | -{ |
1018 | - Q_UNUSED(snapshotImage); |
1019 | -} |
1020 | - |
1021 | -const QImage &AalVideoRendererControl::preview() const |
1022 | -{ |
1023 | - return m_preview; |
1024 | -} |
1025 | - |
1026 | -void AalVideoRendererControl::createPreview() |
1027 | -{ |
1028 | -} |
1029 | |
1030 | === removed file 'unittests/aalimagecapturecontrol/storagemanager.cpp' |
1031 | --- unittests/aalimagecapturecontrol/storagemanager.cpp 2014-09-10 19:48:00 +0000 |
1032 | +++ unittests/aalimagecapturecontrol/storagemanager.cpp 1970-01-01 00:00:00 +0000 |
1033 | @@ -1,50 +0,0 @@ |
1034 | -/* |
1035 | - * Copyright (C) 2013 Canonical, Ltd. |
1036 | - * |
1037 | - * This program is free software; you can redistribute it and/or modify |
1038 | - * it under the terms of the GNU Lesser General Public License as published by |
1039 | - * the Free Software Foundation; version 3. |
1040 | - * |
1041 | - * This program is distributed in the hope that it will be useful, |
1042 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1043 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1044 | - * GNU Lesser General Public License for more details. |
1045 | - * |
1046 | - * You should have received a copy of the GNU Lesser General Public License |
1047 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1048 | - */ |
1049 | - |
1050 | -#include <QDebug> |
1051 | -#include <QString> |
1052 | - |
1053 | -#include "storagemanager.h" |
1054 | - |
1055 | -StorageManager::StorageManager() |
1056 | -{ |
1057 | -} |
1058 | - |
1059 | -QString StorageManager::nextPhotoFileName(const QString &directory) |
1060 | -{ |
1061 | - Q_UNUSED(directory); |
1062 | - return QString(); |
1063 | -} |
1064 | - |
1065 | -QString StorageManager::nextVideoFileName(const QString &directory) |
1066 | -{ |
1067 | - Q_UNUSED(directory); |
1068 | - return QString(); |
1069 | -} |
1070 | - |
1071 | -bool StorageManager::checkDirectory(const QString &path) const |
1072 | -{ |
1073 | - Q_UNUSED(path); |
1074 | - return true; |
1075 | -} |
1076 | - |
1077 | -QString StorageManager::fileNameGenerator(const QString &base, |
1078 | - const QString& extension) |
1079 | -{ |
1080 | - Q_UNUSED(base); |
1081 | - Q_UNUSED(extension); |
1082 | - return QString(); |
1083 | -} |
1084 | |
1085 | === removed file 'unittests/aalimagecapturecontrol/tst_aalimagecapturecontrol.cpp' |
1086 | --- unittests/aalimagecapturecontrol/tst_aalimagecapturecontrol.cpp 2015-10-14 21:22:46 +0000 |
1087 | +++ unittests/aalimagecapturecontrol/tst_aalimagecapturecontrol.cpp 1970-01-01 00:00:00 +0000 |
1088 | @@ -1,74 +0,0 @@ |
1089 | -/* |
1090 | - * Copyright (C) 2013 Canonical, Ltd. |
1091 | - * |
1092 | - * This program is free software; you can redistribute it and/or modify |
1093 | - * it under the terms of the GNU Lesser General Public License as published by |
1094 | - * the Free Software Foundation; version 3. |
1095 | - * |
1096 | - * This program is distributed in the hope that it will be useful, |
1097 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1098 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1099 | - * GNU Lesser General Public License for more details. |
1100 | - * |
1101 | - * You should have received a copy of the GNU Lesser General Public License |
1102 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1103 | - */ |
1104 | - |
1105 | -#include <QtTest/QtTest> |
1106 | -#include <cmath> |
1107 | - |
1108 | -#include "aalcameraservice.h" |
1109 | -#include "data_validjpeg.h" |
1110 | -#include "data_noexifjpeg.h" |
1111 | - |
1112 | -#define private public |
1113 | -#include "aalimagecapturecontrol.h" |
1114 | - |
1115 | -class tst_AalImageCaptureControl : public QObject |
1116 | -{ |
1117 | - Q_OBJECT |
1118 | -private slots: |
1119 | - void initTestCase(); |
1120 | - void cleanupTestCase(); |
1121 | - |
1122 | - void updateEXIF(); |
1123 | - |
1124 | -private: |
1125 | - AalImageCaptureControl *m_icControl; |
1126 | - AalCameraService *m_service; |
1127 | - |
1128 | - friend class AalImageCaptureControl; |
1129 | -}; |
1130 | - |
1131 | -void tst_AalImageCaptureControl::initTestCase() |
1132 | -{ |
1133 | - m_service = new AalCameraService(); |
1134 | - m_icControl = new AalImageCaptureControl(m_service); |
1135 | -} |
1136 | - |
1137 | -void tst_AalImageCaptureControl::cleanupTestCase() |
1138 | -{ |
1139 | - delete m_icControl; |
1140 | - delete m_service; |
1141 | -} |
1142 | - |
1143 | -void tst_AalImageCaptureControl::updateEXIF() |
1144 | -{ |
1145 | - bool result; |
1146 | - QTemporaryFile tmp; |
1147 | - char *invalidJPEG = "INVALID_IMAGE"; |
1148 | - result = m_icControl->updateJpegMetadata(0, 0, &tmp); |
1149 | - QCOMPARE(result, false); |
1150 | - result = m_icControl->updateJpegMetadata(invalidJPEG, strlen(invalidJPEG), 0); |
1151 | - QCOMPARE(result, false); |
1152 | - result = m_icControl->updateJpegMetadata(invalidJPEG, strlen(invalidJPEG), &tmp); |
1153 | - QCOMPARE(result, false); |
1154 | - result = m_icControl->updateJpegMetadata(data_validjpeg, data_validjpeg_len, &tmp); |
1155 | - QCOMPARE(result, true); |
1156 | - result = m_icControl->updateJpegMetadata(data_noexifjpeg, data_noexifjpeg_len, &tmp); |
1157 | - QCOMPARE(result, true); |
1158 | -} |
1159 | - |
1160 | -QTEST_GUILESS_MAIN(tst_AalImageCaptureControl) |
1161 | - |
1162 | -#include "tst_aalimagecapturecontrol.moc" |
1163 | |
1164 | === renamed file 'unittests/aalimagecapturecontrol/data_noexifjpeg.h' => 'unittests/storagemanager/data_noexifjpeg.h' |
1165 | === renamed file 'unittests/aalimagecapturecontrol/data_validjpeg.h' => 'unittests/storagemanager/data_validjpeg.h' |
1166 | === modified file 'unittests/storagemanager/storagemanager.pro' |
1167 | --- unittests/storagemanager/storagemanager.pro 2013-06-13 19:13:27 +0000 |
1168 | +++ unittests/storagemanager/storagemanager.pro 2016-02-11 15:33:06 +0000 |
1169 | @@ -4,6 +4,11 @@ |
1170 | |
1171 | QT += testlib |
1172 | |
1173 | +CONFIG += link_pkgconfig |
1174 | +PKGCONFIG += exiv2 |
1175 | + |
1176 | +HEADERS += ../../src/storagemanager.h |
1177 | + |
1178 | SOURCES += tst_storagemanager.cpp \ |
1179 | ../../src/storagemanager.cpp |
1180 | |
1181 | |
1182 | === modified file 'unittests/storagemanager/tst_storagemanager.cpp' |
1183 | --- unittests/storagemanager/tst_storagemanager.cpp 2014-09-10 19:48:00 +0000 |
1184 | +++ unittests/storagemanager/tst_storagemanager.cpp 2016-02-11 15:33:06 +0000 |
1185 | @@ -22,6 +22,8 @@ |
1186 | |
1187 | #define private public |
1188 | #include "storagemanager.h" |
1189 | +#include "data_validjpeg.h" |
1190 | +#include "data_noexifjpeg.h" |
1191 | |
1192 | const QLatin1String testPath("/tmp/aalCameraStorageManagerUnitTestDirectory0192837465/"); |
1193 | |
1194 | @@ -34,6 +36,7 @@ |
1195 | void checkDirectory(); |
1196 | void fileNameGenerator_data(); |
1197 | void fileNameGenerator(); |
1198 | + void updateEXIF(); |
1199 | |
1200 | private: |
1201 | void removeTestDirectory(); |
1202 | @@ -112,6 +115,25 @@ |
1203 | dir.rmdir(testPath); |
1204 | } |
1205 | |
1206 | +void tst_StorageManager::updateEXIF() |
1207 | +{ |
1208 | + StorageManager storage; |
1209 | + bool result; |
1210 | + QTemporaryFile tmp; |
1211 | + QVariantMap metadata; |
1212 | + QByteArray invalidJPEG("INVALID_IMAGE"); |
1213 | + result = storage.updateJpegMetadata(invalidJPEG, metadata, &tmp); |
1214 | + QCOMPARE(result, false); |
1215 | + result = storage.updateJpegMetadata(invalidJPEG, metadata, 0); |
1216 | + QCOMPARE(result, false); |
1217 | + result = storage.updateJpegMetadata(invalidJPEG, metadata, &tmp); |
1218 | + QCOMPARE(result, false); |
1219 | + result = storage.updateJpegMetadata(QByteArray((char*)data_validjpeg, data_validjpeg_len), metadata, &tmp); |
1220 | + QCOMPARE(result, true); |
1221 | + result = storage.updateJpegMetadata(QByteArray((char*)data_noexifjpeg, data_noexifjpeg_len), metadata, &tmp); |
1222 | + QCOMPARE(result, true); |
1223 | +} |
1224 | + |
1225 | QTEST_GUILESS_MAIN(tst_StorageManager); |
1226 | |
1227 | #include "tst_storagemanager.moc" |
1228 | |
1229 | === modified file 'unittests/stubs/storagemanager_stub.cpp' |
1230 | --- unittests/stubs/storagemanager_stub.cpp 2014-09-10 19:48:00 +0000 |
1231 | +++ unittests/stubs/storagemanager_stub.cpp 2016-02-11 15:33:06 +0000 |
1232 | @@ -19,8 +19,9 @@ |
1233 | |
1234 | #include "storagemanager.h" |
1235 | |
1236 | -StorageManager::StorageManager() |
1237 | +StorageManager::StorageManager(QObject* parent) |
1238 | { |
1239 | + Q_UNUSED(parent); |
1240 | } |
1241 | |
1242 | QString StorageManager::nextPhotoFileName(const QString &directory) |
1243 | |
1244 | === modified file 'unittests/unittests.pro' |
1245 | --- unittests/unittests.pro 2014-07-14 16:18:14 +0000 |
1246 | +++ unittests/unittests.pro 2016-02-11 15:33:06 +0000 |
1247 | @@ -7,7 +7,6 @@ |
1248 | aalcameraflashcontrol \ |
1249 | aalcamerafocuscontrol \ |
1250 | aalcamerazoomcontrol \ |
1251 | - aalimagecapturecontrol \ |
1252 | aalmediarecordercontrol \ |
1253 | aalvideodeviceselectorcontrol \ |
1254 | aalviewfindersettingscontrol \ |
PASSED: Continuous integration, rev:182 jenkins. qa.ubuntu. com/job/ qtubuntu- camera- staging- ci/15/ jenkins. qa.ubuntu. com/job/ qtubuntu- camera- staging- vivid-amd64- ci/14 jenkins. qa.ubuntu. com/job/ qtubuntu- camera- staging- vivid-amd64- ci/14/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ qtubuntu- camera- staging- vivid-armhf- ci/15 jenkins. qa.ubuntu. com/job/ qtubuntu- camera- staging- vivid-armhf- ci/15/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ qtubuntu- camera- staging- vivid-i386- ci/14 jenkins. qa.ubuntu. com/job/ qtubuntu- camera- staging- vivid-i386- ci/14/artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/qtubuntu- camera- staging- ci/15/rebuild
http://