summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTyler Luu <tluu@ti.com>2011-09-07 22:19:09 -0500
committerIliyan Malchev <malchev@google.com>2011-09-12 16:15:48 -0700
commit36e9bdd56757ff8048e08f6e52f234480c44f122 (patch)
tree5eccf8d64f6fd808fc2d1a6ed8f590cdc49607ef
parent6b5eaf29c3d17a24731bf9271bd0d199d433813e (diff)
downloadomap4xxx-omapzoom-36e9bdd56757ff8048e08f6e52f234480c44f122.tar.gz
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>
-rw-r--r--camera/Android.mk6
-rw-r--r--camera/AppCallbackNotifier.cpp45
-rw-r--r--camera/Encoder_libjpeg.cpp93
-rw-r--r--camera/OMXCameraAdapter/OMX3A.cpp3
-rw-r--r--camera/OMXCameraAdapter/OMXCameraAdapter.cpp7
-rw-r--r--camera/OMXCameraAdapter/OMXExif.cpp158
-rw-r--r--camera/inc/CameraHal.h6
-rw-r--r--camera/inc/Encoder_libjpeg.h43
-rw-r--r--camera/inc/OMXCameraAdapter/OMXCameraAdapter.h2
9 files changed, 351 insertions, 12 deletions
diff --git a/camera/Android.mk b/camera/Android.mk
index d9f2b043..e6b1b0d5 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -65,7 +65,8 @@ LOCAL_C_INCLUDES += \
hardware/ti/omap4xxx/domx/mm_osal/inc \
frameworks/base/include/media/stagefright \
frameworks/base/include/media/stagefright/openmax \
- external/jpeg
+ external/jpeg \
+ external/jhead
LOCAL_SHARED_LIBRARIES:= \
libui \
@@ -79,7 +80,8 @@ LOCAL_SHARED_LIBRARIES:= \
libgui \
libdomx \
libion \
- libjpeg
+ libjpeg \
+ libexif
LOCAL_CFLAGS := -fno-short-enums -DCOPY_IMAGE_BUFFER
diff --git a/camera/AppCallbackNotifier.cpp b/camera/AppCallbackNotifier.cpp
index 9ff79460..4302988d 100644
--- a/camera/AppCallbackNotifier.cpp
+++ b/camera/AppCallbackNotifier.cpp
@@ -41,13 +41,13 @@ void AppCallbackNotifierEncoderCallback(size_t jpeg_size,
{
if (cookie1) {
AppCallbackNotifier* cb = (AppCallbackNotifier*) cookie1;
- cb->EncoderDoneCb(jpeg_size, src, type, cookie2);
+ cb->EncoderDoneCb(jpeg_size, src, type, cookie2, cookie3);
}
}
/*--------------------NotificationHandler Class STARTS here-----------------------------*/
-void AppCallbackNotifier::EncoderDoneCb(size_t jpeg_size, uint8_t* src, CameraFrame::FrameType type, void* cookie1)
+void AppCallbackNotifier::EncoderDoneCb(size_t jpeg_size, uint8_t* src, CameraFrame::FrameType type, void* cookie1, void* cookie2)
{
camera_memory_t* encoded_mem = NULL;
@@ -61,10 +61,30 @@ void AppCallbackNotifier::EncoderDoneCb(size_t jpeg_size, uint8_t* src, CameraFr
// encoded buffer since MemoryHeapBase and MemoryBase are passed as
// one camera_memory_t structure. How fix this?
- camera_memory_t* picture = mRequestMemory(-1, jpeg_size, 1, NULL);
+ camera_memory_t* picture = NULL;
- if(picture && picture->data && encoded_mem && encoded_mem->data) {
- memcpy(picture->data, encoded_mem->data, jpeg_size);
+ if(encoded_mem && encoded_mem->data) {
+ if (cookie2) {
+ ExifElementsTable* exif = (ExifElementsTable*) cookie2;
+ Section_t* exif_section = NULL;
+
+ exif->insertExifToJpeg((unsigned char*) encoded_mem->data, jpeg_size);
+ exif_section = FindSection(M_EXIF);
+
+ if (exif_section) {
+ picture = mRequestMemory(-1, jpeg_size + exif_section->Size, 1, NULL);
+ if (picture && picture->data) {
+ exif->saveJpeg((unsigned char*) picture->data, jpeg_size + exif_section->Size);
+ }
+ }
+ delete exif;
+ cookie2 = NULL;
+ } else {
+ picture = mRequestMemory(-1, jpeg_size, 1, NULL);
+ if (picture && picture->data) {
+ memcpy(picture->data, encoded_mem->data, jpeg_size);
+ }
+ }
}
{
@@ -89,6 +109,10 @@ void AppCallbackNotifier::EncoderDoneCb(size_t jpeg_size, uint8_t* src, CameraFr
picture->release(picture);
}
+ if (cookie2) {
+ delete (ExifElementsTable*) cookie2;
+ }
+
mFrameProvider->returnFrame(src, type);
LOG_FUNCTION_NAME_EXIT;
@@ -629,6 +653,7 @@ void AppCallbackNotifier::notifyFrame()
int encode_quality = 100;
const char* valstr = NULL;
+ void* exif_data = NULL;
camera_memory_t* raw_picture = mRequestMemory(-1, frame->mLength, 1, NULL);
if(raw_picture) {
@@ -643,7 +668,11 @@ void AppCallbackNotifier::notifyFrame()
}
}
- CAMHAL_LOGVB("encoder(%p, %d, %p, %d, %d, %d, %d,%p,%d,%p,%p, %d)",
+ if (CameraFrame::HAS_EXIF_DATA & frame->mQuirks) {
+ exif_data = frame->mCookie2;
+ }
+
+ CAMHAL_LOGVB("encoder(%p, %d, %p, %d, %d, %d, %d,%p,%d,%p,%p,%p)",
(uint8_t*)frame->mBuffer,
frame->mLength,
(uint8_t*)buf,
@@ -655,7 +684,7 @@ void AppCallbackNotifier::notifyFrame()
frame->mFrameType,
this,
raw_picture,
- NULL);
+ exif_data);
sp<Encoder_libjpeg> encoder = new Encoder_libjpeg((uint8_t*)frame->mBuffer,
frame->mLength,
@@ -668,7 +697,7 @@ void AppCallbackNotifier::notifyFrame()
(CameraFrame::FrameType)frame->mFrameType,
this,
raw_picture,
- NULL);
+ exif_data);
encoder->run();
encoder.clear();
diff --git a/camera/Encoder_libjpeg.cpp b/camera/Encoder_libjpeg.cpp
index dfdd9348..99650cc8 100644
--- a/camera/Encoder_libjpeg.cpp
+++ b/camera/Encoder_libjpeg.cpp
@@ -41,8 +41,21 @@ extern "C" {
#include "jerror.h"
}
+#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 @@ static void uyvy_to_yuv(uint8_t* dst, uint32_t* src, int width) {
}
}
+/* 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;
diff --git a/camera/OMXCameraAdapter/OMX3A.cpp b/camera/OMXCameraAdapter/OMX3A.cpp
index 530e8ae4..2466d68e 100644
--- a/camera/OMXCameraAdapter/OMX3A.cpp
+++ b/camera/OMXCameraAdapter/OMX3A.cpp
@@ -29,7 +29,8 @@
#include "OMXCameraAdapter.h"
#include "ErrorUtils.h"
-
+#undef TRUE
+#undef FALSE
#define TRUE "true"
#define FALSE "false"
diff --git a/camera/OMXCameraAdapter/OMXCameraAdapter.cpp b/camera/OMXCameraAdapter/OMXCameraAdapter.cpp
index 79a42d9a..6f604cd6 100644
--- a/camera/OMXCameraAdapter/OMXCameraAdapter.cpp
+++ b/camera/OMXCameraAdapter/OMXCameraAdapter.cpp
@@ -2920,6 +2920,13 @@ OMX_ERRORTYPE OMXCameraAdapter::OMXCameraAdapterFillBufferDone(OMX_IN OMX_HANDLE
// before returning to framework
typeOfFrame = CameraFrame::IMAGE_FRAME;
cameraFrame.mQuirks |= CameraFrame::ENCODE_RAW_YUV422I_TO_JPEG;
+
+ // populate exif data and pass to subscribers via quirk
+ // subscriber is in charge of freeing exif data
+ ExifElementsTable* exif = new ExifElementsTable();
+ setupEXIF_libjpeg(exif);
+ cameraFrame.mQuirks |= CameraFrame::HAS_EXIF_DATA;
+ cameraFrame.mCookie2 = (void*) exif;
}
else
{
diff --git a/camera/OMXCameraAdapter/OMXExif.cpp b/camera/OMXCameraAdapter/OMXExif.cpp
index 64eddc64..5da60ac5 100644
--- a/camera/OMXCameraAdapter/OMXExif.cpp
+++ b/camera/OMXCameraAdapter/OMXExif.cpp
@@ -535,6 +535,164 @@ status_t OMXCameraAdapter::setupEXIF()
return ret;
}
+status_t OMXCameraAdapter::setupEXIF_libjpeg(ExifElementsTable* exifTable)
+{
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ struct timeval sTv;
+ struct tm *pTime;
+ OMXCameraPortParameters * capData = NULL;
+
+ LOG_FUNCTION_NAME;
+
+ capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
+
+ if ((NO_ERROR == ret) && (mEXIFData.mModelValid)) {
+ ret = exifTable->insertElement(TAG_MODEL, mParams.get(TICameraParameters::KEY_EXIF_MODEL));
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mMakeValid)) {
+ ret = exifTable->insertElement(TAG_MAKE, mParams.get(TICameraParameters::KEY_EXIF_MAKE));
+ }
+
+ if ((NO_ERROR == ret)) {
+ ret = exifTable->insertElement(TAG_FOCALLENGTH,
+ mParams.get(CameraParameters::KEY_FOCAL_LENGTH));
+ }
+
+ if ((NO_ERROR == ret)) {
+ int status = gettimeofday (&sTv, NULL);
+ pTime = localtime (&sTv.tv_sec);
+ char temp_value[EXIF_DATE_TIME_SIZE + 1];
+ if ((0 == status) && (NULL != pTime)) {
+ snprintf(temp_value, EXIF_DATE_TIME_SIZE,
+ "%04d:%02d:%02d %02d:%02d:%02d",
+ pTime->tm_year + 1900,
+ pTime->tm_mon + 1,
+ pTime->tm_mday,
+ pTime->tm_hour,
+ pTime->tm_min,
+ pTime->tm_sec );
+
+ ret = exifTable->insertElement(TAG_DATETIME, temp_value);
+ }
+ }
+
+ if ((NO_ERROR == ret)) {
+ char temp_value[5];
+ snprintf(temp_value, sizeof(temp_value)/sizeof(char) - 1, "%lu", capData->mWidth);
+ ret = exifTable->insertElement(TAG_IMAGE_WIDTH, temp_value);
+ }
+
+ if ((NO_ERROR == ret)) {
+ char temp_value[5];
+ snprintf(temp_value, sizeof(temp_value)/sizeof(char) - 1, "%lu", capData->mHeight);
+ ret = exifTable->insertElement(TAG_IMAGE_LENGTH, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLatValid)) {
+ char temp_value[256]; // arbitrarily long string
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char) - 1,
+ "%d/%d,%d/%d,%d/%d",
+ abs(mEXIFData.mGPSData.mLatDeg), 1,
+ abs(mEXIFData.mGPSData.mLatMin), 1,
+ abs(mEXIFData.mGPSData.mLatSec), 1);
+ ret = exifTable->insertElement(TAG_GPS_LAT, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLatValid)) {
+ ret = exifTable->insertElement(TAG_GPS_LAT_REF, mEXIFData.mGPSData.mLatRef);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLongValid)) {
+ char temp_value[256]; // arbitrarily long string
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char) - 1,
+ "%d/%d,%d/%d,%d/%d",
+ abs(mEXIFData.mGPSData.mLongDeg), 1,
+ abs(mEXIFData.mGPSData.mLongMin), 1,
+ abs(mEXIFData.mGPSData.mLongSec), 1);
+ ret = exifTable->insertElement(TAG_GPS_LONG, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLongValid)) {
+ ret = exifTable->insertElement(TAG_GPS_LONG_REF, mEXIFData.mGPSData.mLongRef);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mAltitudeValid)) {
+ char temp_value[256]; // arbitrarily long string
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char) - 1,
+ "%d/%d",
+ abs( mEXIFData.mGPSData.mAltitude), 1);
+ ret = exifTable->insertElement(TAG_GPS_ALT, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mAltitudeValid)) {
+ char temp_value[5];
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char) - 1,
+ "%d", mEXIFData.mGPSData.mAltitudeRef);
+ ret = exifTable->insertElement(TAG_GPS_ALT_REF, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mMapDatumValid)) {
+ ret = exifTable->insertElement(TAG_GPS_MAP_DATUM, mEXIFData.mGPSData.mMapDatum);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mProcMethodValid)) {
+ char temp_value[GPS_PROCESSING_SIZE];
+
+ memcpy(temp_value, EXIFASCIIPrefix, sizeof(EXIFASCIIPrefix));
+ memcpy(temp_value + sizeof(EXIFASCIIPrefix),
+ mEXIFData.mGPSData.mProcMethod,
+ (GPS_PROCESSING_SIZE - sizeof(EXIFASCIIPrefix)));
+
+ ret = exifTable->insertElement(TAG_GPS_PROCESSING_METHOD, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mVersionIdValid)) {
+ char temp_value[256]; // arbitrarily long string
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char) - 1,
+ "%d,%d,%d,%d",
+ mEXIFData.mGPSData.mVersionId[0],
+ mEXIFData.mGPSData.mVersionId[1],
+ mEXIFData.mGPSData.mVersionId[2],
+ mEXIFData.mGPSData.mVersionId[3]);
+ ret = exifTable->insertElement(TAG_GPS_VERSION_ID, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mTimeStampValid)) {
+ char temp_value[256]; // arbitrarily long string
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char) - 1,
+ "%d/%d,%d/%d,%d/%d",
+ mEXIFData.mGPSData.mTimeStampHour, 1,
+ mEXIFData.mGPSData.mTimeStampMin, 1,
+ mEXIFData.mGPSData.mTimeStampSec, 1);
+ ret = exifTable->insertElement(TAG_GPS_TIMESTAMP, temp_value);
+ }
+
+ if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mDatestampValid) ) {
+ ret = exifTable->insertElement(TAG_GPS_DATESTAMP, mEXIFData.mGPSData.mDatestamp);
+ }
+
+ if ((NO_ERROR == ret) && mParams.get(CameraParameters::KEY_ROTATION) ) {
+ const char* exif_orient =
+ ExifElementsTable::degreesToExifOrientation(mParams.get(CameraParameters::KEY_ROTATION));
+
+ if (exif_orient) {
+ ret = exifTable->insertElement(TAG_ORIENTATION, exif_orient);
+ }
+ }
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return ret;
+}
+
status_t OMXCameraAdapter::convertGPSCoord(double coord,
int &deg,
int &min,
diff --git a/camera/inc/CameraHal.h b/camera/inc/CameraHal.h
index 36a3504e..f19aceab 100644
--- a/camera/inc/CameraHal.h
+++ b/camera/inc/CameraHal.h
@@ -238,11 +238,13 @@ class CameraFrame
enum FrameQuirks
{
ENCODE_RAW_YUV422I_TO_JPEG = 0x1 << 0,
+ HAS_EXIF_DATA = 0x1 << 1,
};
//default contrustor
CameraFrame():
mCookie(NULL),
+ mCookie2(NULL),
mBuffer(NULL),
mFrameType(0),
mTimestamp(0),
@@ -257,6 +259,7 @@ class CameraFrame
//copy constructor
CameraFrame(const CameraFrame &frame) :
mCookie(frame.mCookie),
+ mCookie2(frame.mCookie2),
mBuffer(frame.mBuffer),
mFrameType(frame.mFrameType),
mTimestamp(frame.mTimestamp),
@@ -269,6 +272,7 @@ class CameraFrame
mQuirks(frame.mQuirks) {}
void *mCookie;
+ void *mCookie2;
void *mBuffer;
int mFrameType;
nsecs_t mTimestamp;
@@ -540,7 +544,7 @@ public:
status_t useMetaDataBufferMode(bool enable);
- void EncoderDoneCb(size_t jpeg_size, uint8_t* src, CameraFrame::FrameType type, void* cookie1);
+ void EncoderDoneCb(size_t jpeg_size, uint8_t* src, CameraFrame::FrameType type, void* cookie1, void* cookie2);
//Internal class definitions
class NotificationThread : public Thread {
diff --git a/camera/inc/Encoder_libjpeg.h b/camera/inc/Encoder_libjpeg.h
index 24ce6725..8aaae023 100644
--- a/camera/inc/Encoder_libjpeg.h
+++ b/camera/inc/Encoder_libjpeg.h
@@ -27,12 +27,17 @@
#include <utils/threads.h>
#include <utils/RefBase.h>
+extern "C" {
+#include "jhead.h"
+}
namespace android {
/**
* libjpeg encoder class - uses libjpeg to encode yuv
*/
+#define MAX_EXIF_TAGS_SUPPORTED 30
+
typedef void (*encoder_libjpeg_callback_t) (size_t jpeg_size,
uint8_t* src,
CameraFrame::FrameType type,
@@ -40,6 +45,44 @@ typedef void (*encoder_libjpeg_callback_t) (size_t jpeg_size,
void* cookie2,
void* cookie3);
+static const char TAG_MODEL[] = "Model";
+static const char TAG_MAKE[] = "Make";
+static const char TAG_FOCALLENGTH[] = "FocalLength";
+static const char TAG_DATETIME[] = "DateTime";
+static const char TAG_IMAGE_WIDTH[] = "ImageWidth";
+static const char TAG_IMAGE_LENGTH[] = "ImageLength";
+static const char TAG_GPS_LAT[] = "GPSLatitude";
+static const char TAG_GPS_LAT_REF[] = "GPSLatitudeRef";
+static const char TAG_GPS_LONG[] = "GPSLongitude";
+static const char TAG_GPS_LONG_REF[] = "GPSLongitudeRef";
+static const char TAG_GPS_ALT[] = "GPSAltitude";
+static const char TAG_GPS_ALT_REF[] = "GPSAltitudeRef";
+static const char TAG_GPS_MAP_DATUM[] = "GPSMapDatum";
+static const char TAG_GPS_PROCESSING_METHOD[] = "GPSProcessingMethod";
+static const char TAG_GPS_VERSION_ID[] = "GPSVersionID";
+static const char TAG_GPS_TIMESTAMP[] = "GPSTimeStamp";
+static const char TAG_GPS_DATESTAMP[] = "GPSDateStamp";
+static const char TAG_ORIENTATION[] = "Orientation";
+
+class ExifElementsTable {
+ public:
+ ExifElementsTable() :
+ gps_tag_count(0), exif_tag_count(0), position(0),
+ jpeg_opened(false) { }
+ ~ExifElementsTable();
+
+ status_t insertElement(const char* tag, const char* value);
+ void insertExifToJpeg(unsigned char* jpeg, size_t jpeg_size);
+ void saveJpeg(unsigned char* picture, size_t jpeg_size);
+ static const char* degreesToExifOrientation(const char*);
+ private:
+ ExifElement_t table[MAX_EXIF_TAGS_SUPPORTED];
+ unsigned int gps_tag_count;
+ unsigned int exif_tag_count;
+ unsigned int position;
+ bool jpeg_opened;
+};
+
class Encoder_libjpeg : public Thread {
public:
Encoder_libjpeg(uint8_t* src,
diff --git a/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h b/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h
index b7d7f2d5..c01ca026 100644
--- a/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h
+++ b/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h
@@ -34,6 +34,7 @@
#include "General3A_Settings.h"
#include "BaseCameraAdapter.h"
+#include "Encoder_libjpeg.h"
#include "DebugUtils.h"
@@ -425,6 +426,7 @@ private:
BaseCameraAdapter::AdapterState state);
status_t convertGPSCoord(double coord, int &deg, int &min, int &sec, int &secDivisor);
status_t setupEXIF();
+ status_t setupEXIF_libjpeg(ExifElementsTable*);
//Focus functionality
status_t doAutoFocus();