CameraHal: Add Exif support to video snapshot
Use jhead library to insert Exif to jpeg stream
returned from libjpeg.
Change-Id: Ia6398180b7ef3c1b3ddcb35e489527289565fef5
Signed-off-by: Tyler Luu <tluu@ti.com>
diff --git a/camera/Encoder_libjpeg.cpp b/camera/Encoder_libjpeg.cpp
index dfdd934..99650cc 100644
--- a/camera/Encoder_libjpeg.cpp
+++ b/camera/Encoder_libjpeg.cpp
@@ -41,8 +41,21 @@
#include "jerror.h"
}
-namespace android {
+#define ARRAY_SIZE(array) (sizeof((array)) / sizeof((array)[0]))
+namespace android {
+struct string_pair {
+ const char* string1;
+ const char* string2;
+};
+
+static string_pair degress_to_exif_lut [] = {
+ // degrees, exif_orientation
+ {"0", "1"},
+ {"90", "6"},
+ {"180", "3"},
+ {"270", "8"},
+};
struct libjpeg_destination_mgr : jpeg_destination_mgr {
libjpeg_destination_mgr(uint8_t* input, int size);
@@ -101,6 +114,86 @@
}
}
+/* public static functions */
+const char* ExifElementsTable::degreesToExifOrientation(const char* degrees) {
+ for (int i = 0; i < ARRAY_SIZE(degress_to_exif_lut); i++) {
+ if (!strcmp(degrees, degress_to_exif_lut[i].string1)) {
+ return degress_to_exif_lut[i].string2;
+ }
+ }
+ return NULL;
+}
+
+void ExifElementsTable::insertExifToJpeg(unsigned char* jpeg, size_t jpeg_size) {
+ ReadMode_t read_mode = (ReadMode_t)(READ_METADATA | READ_IMAGE);
+
+ ResetJpgfile();
+ if (ReadJpegSectionsFromBuffer(jpeg, jpeg_size, read_mode)) {
+ jpeg_opened = true;
+ create_EXIF(table, exif_tag_count, gps_tag_count);
+ }
+}
+
+void ExifElementsTable::saveJpeg(unsigned char* jpeg, size_t jpeg_size) {
+ if (jpeg_opened) {
+ WriteJpegToBuffer(jpeg, jpeg_size);
+ DiscardData();
+ jpeg_opened = false;
+ }
+}
+
+/* public functions */
+ExifElementsTable::~ExifElementsTable() {
+ int num_elements = gps_tag_count + exif_tag_count;
+
+ for (int i = 0; i < num_elements; i++) {
+ if (table[i].Value) {
+ free(table[i].Value);
+ }
+ }
+
+ if (jpeg_opened) {
+ DiscardData();
+ }
+}
+
+status_t ExifElementsTable::insertElement(const char* tag, const char* value) {
+ int value_length = 0;
+ status_t ret = NO_ERROR;
+
+ if (!value || !tag) {
+ return -EINVAL;
+ }
+
+ if (position >= MAX_EXIF_TAGS_SUPPORTED) {
+ CAMHAL_LOGEA("Max number of EXIF elements already inserted");
+ return NO_MEMORY;
+ }
+
+ value_length = strlen(value);
+
+ if (IsGpsTag(tag)) {
+ table[position].GpsTag = TRUE;
+ table[position].Tag = GpsTagNameToValue(tag);
+ gps_tag_count++;
+ } else {
+ table[position].GpsTag = FALSE;
+ table[position].Tag = TagNameToValue(tag);
+ exif_tag_count++;
+ }
+
+ table[position].DataLength = 0;
+ table[position].Value = (char*) malloc(sizeof(char) * (value_length + 1));
+
+ if (table[position].Value) {
+ strncpy(table[position].Value, value, value_length);
+ table[position].DataLength = value_length + 1;
+ }
+
+ position++;
+ return ret;
+}
+
/* private member functions */
size_t Encoder_libjpeg::encode() {
jpeg_compress_struct cinfo;