summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Moskal <bartlomiej.moskal@qt.io>2023-08-10 09:12:58 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-08-16 09:40:30 +0000
commit786dd2dfcbb272626c83b6c669c098cde1387d7a (patch)
tree2c5da4a9a2cfa4905f486ce671f1fcf21c79b8ea
parent7a9a05ab06235b0c71faaa966530a7de5228962c (diff)
Android: add Exif data to photos on ffmpeg-backend
For FFMpeg-backend on Android, YUV_420_888 format is used. YUV_420_888 is a RAW frame that does not contain any Exif data. Data cannot be taken directly from the picture, but some data can be extracted from CaptureResult. This commit includes adding some Exif data to the photo taken on FFmmpeg-backend. Task-number: QTBUG-113020 Change-Id: Ic331d653b78eacc17929b9980fd977435774756a Reviewed-by: Artem Dyomin <artem.dyomin@qt.io> (cherry picked from commit 0f6c9b3d6cd9cd9155c832ad32d47525806e1b0b) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/android/jar/CMakeLists.txt1
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/multimedia/QtCamera2.java11
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/multimedia/QtExifDataHandler.java52
-rw-r--r--src/plugins/multimedia/ffmpeg/qandroidcamera.cpp5
-rw-r--r--src/plugins/multimedia/ffmpeg/qandroidcamera_p.h1
-rw-r--r--src/plugins/multimedia/ffmpeg/qandroidimagecapture.cpp9
-rw-r--r--src/plugins/multimedia/ffmpeg/qandroidimagecapture_p.h3
7 files changed, 82 insertions, 0 deletions
diff --git a/src/android/jar/CMakeLists.txt b/src/android/jar/CMakeLists.txt
index e2ee117ce..01e0e5a08 100644
--- a/src/android/jar/CMakeLists.txt
+++ b/src/android/jar/CMakeLists.txt
@@ -7,6 +7,7 @@ set(java_sources
src/org/qtproject/qt/android/multimedia/QtAndroidMediaPlayer.java
src/org/qtproject/qt/android/multimedia/QtCameraListener.java
src/org/qtproject/qt/android/multimedia/QtCamera2.java
+ src/org/qtproject/qt/android/multimedia/QtExifDataHandler.java
src/org/qtproject/qt/android/multimedia/QtAudioDeviceManager.java
src/org/qtproject/qt/android/multimedia/QtVideoDeviceManager.java
src/org/qtproject/qt/android/multimedia/QtMediaRecorderListener.java
diff --git a/src/android/jar/src/org/qtproject/qt/android/multimedia/QtCamera2.java b/src/android/jar/src/org/qtproject/qt/android/multimedia/QtCamera2.java
index 5c46e486c..a3f472f48 100644
--- a/src/android/jar/src/org/qtproject/qt/android/multimedia/QtCamera2.java
+++ b/src/android/jar/src/org/qtproject/qt/android/multimedia/QtCamera2.java
@@ -3,6 +3,7 @@
package org.qtproject.qt.android.multimedia;
import org.qtproject.qt.android.multimedia.QtVideoDeviceManager;
+import org.qtproject.qt.android.multimedia.QtExifDataHandler;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
@@ -59,6 +60,7 @@ public class QtCamera2 {
private int mFlashMode = CaptureRequest.CONTROL_AE_MODE_ON;
private int mTorchMode = CameraMetadata.FLASH_MODE_OFF;
private int mAFMode = CaptureRequest.CONTROL_AF_MODE_OFF;
+ private QtExifDataHandler mExifDataHandler = null;
native void onCameraOpened(String cameraId);
native void onCameraDisconnect(String cameraId);
@@ -350,6 +352,7 @@ public class QtCamera2 {
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
TotalCaptureResult result) {
try {
+ mExifDataHandler = new QtExifDataHandler(result);
// Reset the focus/flash and go back to the normal state of preview.
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
CameraMetadata.CONTROL_AF_TRIGGER_IDLE);
@@ -386,6 +389,14 @@ public class QtCamera2 {
}
}
+ public void saveExifToFile(String path)
+ {
+ if (mExifDataHandler != null)
+ mExifDataHandler.save(path);
+ else
+ Log.e("QtCamera2", "No Exif data that could be saved to " + path);
+ }
+
public void zoomTo(float factor)
{
synchronized (mStartMutex) {
diff --git a/src/android/jar/src/org/qtproject/qt/android/multimedia/QtExifDataHandler.java b/src/android/jar/src/org/qtproject/qt/android/multimedia/QtExifDataHandler.java
new file mode 100644
index 000000000..4ea40e738
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/multimedia/QtExifDataHandler.java
@@ -0,0 +1,52 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+package org.qtproject.qt.android.multimedia;
+
+import android.hardware.camera2.CaptureResult;
+import android.media.ExifInterface;
+import android.os.Build;
+import android.util.Log;
+
+import java.io.IOException;
+
+public class QtExifDataHandler {
+
+ private int mFlashFired = 0;
+ private Long mExposureTime = 0L;
+ private float mFocalLength = 0;
+ private static String mModel = Build.MANUFACTURER + " " + Build.MODEL;
+
+ public QtExifDataHandler(CaptureResult r)
+ {
+ if (r.get(CaptureResult.FLASH_STATE) == CaptureResult.FLASH_STATE_FIRED)
+ mFlashFired = 1;
+
+ mExposureTime = r.get(CaptureResult.SENSOR_EXPOSURE_TIME)/1000000000;
+ mFocalLength = r.get(CaptureResult.LENS_FOCAL_LENGTH);
+ }
+
+ public void save(String path)
+ {
+ ExifInterface exif;
+ try {
+ exif = new ExifInterface(path);
+ } catch ( IOException e ) {
+ Log.e("QtExifDataHandler", "Cannot open file: " + path + "\n" + e);
+ return;
+ }
+ exif.setAttribute(ExifInterface.TAG_FLASH, String.valueOf(mFlashFired));
+
+ if (mExposureTime != null)
+ exif.setAttribute(ExifInterface.TAG_EXPOSURE_TIME, String.valueOf(mExposureTime));
+
+ exif.setAttribute(ExifInterface.TAG_FOCAL_LENGTH, String.valueOf(mFocalLength));
+
+ exif.setAttribute(ExifInterface.TAG_MODEL, mModel);
+
+ try {
+ exif.saveAttributes();
+ } catch ( IOException e ) {
+ Log.e("QtExifDataHandler", "Cannot save file: " + path + "\n" + e);
+ }
+ }
+}
diff --git a/src/plugins/multimedia/ffmpeg/qandroidcamera.cpp b/src/plugins/multimedia/ffmpeg/qandroidcamera.cpp
index 0e5feae6c..3caa43d52 100644
--- a/src/plugins/multimedia/ffmpeg/qandroidcamera.cpp
+++ b/src/plugins/multimedia/ffmpeg/qandroidcamera.cpp
@@ -529,6 +529,11 @@ void QAndroidCamera::capture()
m_jniCamera.callMethod<void>("takePhoto");
}
+void QAndroidCamera::updateExif(const QString &filename)
+{
+ m_jniCamera.callMethod<void>("saveExifToFile", QJniObject::fromString(filename).object<jstring>());
+}
+
void QAndroidCamera::onCaptureSessionFailed(int reason, long frameNumber)
{
Q_UNUSED(frameNumber);
diff --git a/src/plugins/multimedia/ffmpeg/qandroidcamera_p.h b/src/plugins/multimedia/ffmpeg/qandroidcamera_p.h
index 901a24786..98be84807 100644
--- a/src/plugins/multimedia/ffmpeg/qandroidcamera_p.h
+++ b/src/plugins/multimedia/ffmpeg/qandroidcamera_p.h
@@ -48,6 +48,7 @@ public:
static bool registerNativeMethods();
void capture();
+ void updateExif(const QString &filename);
public slots:
void onApplicationStateChanged();
void onCameraOpened();
diff --git a/src/plugins/multimedia/ffmpeg/qandroidimagecapture.cpp b/src/plugins/multimedia/ffmpeg/qandroidimagecapture.cpp
index 9265b088d..ed0f2de9d 100644
--- a/src/plugins/multimedia/ffmpeg/qandroidimagecapture.cpp
+++ b/src/plugins/multimedia/ffmpeg/qandroidimagecapture.cpp
@@ -9,6 +9,7 @@ QT_BEGIN_NAMESPACE
QAndroidImageCapture::QAndroidImageCapture(QImageCapture *parent)
: QFFmpegImageCapture(parent)
{
+ connect(this, &QPlatformImageCapture::imageSaved, this, &QAndroidImageCapture::updateExif);
}
QAndroidImageCapture::~QAndroidImageCapture()
@@ -35,3 +36,11 @@ void QAndroidImageCapture::setupVideoSourceConnections()
else
QFFmpegImageCapture::setupVideoSourceConnections();
}
+
+void QAndroidImageCapture::updateExif(int id, const QString &filename)
+{
+ Q_UNUSED(id);
+ auto androidCamera = qobject_cast<QAndroidCamera *>(videoSource());
+ if (androidCamera)
+ androidCamera->updateExif(filename);
+}
diff --git a/src/plugins/multimedia/ffmpeg/qandroidimagecapture_p.h b/src/plugins/multimedia/ffmpeg/qandroidimagecapture_p.h
index ad9a9568b..a88807f13 100644
--- a/src/plugins/multimedia/ffmpeg/qandroidimagecapture_p.h
+++ b/src/plugins/multimedia/ffmpeg/qandroidimagecapture_p.h
@@ -29,6 +29,9 @@ public:
protected:
void setupVideoSourceConnections() override;
int doCapture(const QString &fileName) override;
+
+private slots:
+ void updateExif(int id, const QString &filename);
};
QT_END_NAMESPACE