summaryrefslogtreecommitdiff
path: root/camera
diff options
context:
space:
mode:
authorTyler Luu <tluu@ti.com>2011-10-18 19:52:30 -0500
committerIliyan Malchev <malchev@google.com>2011-11-22 09:30:52 -0800
commitef73bec8a83a2fd7fbb072d009382c64eb2da0ee (patch)
tree4d667494f2c4f399343824e34f970bea973fa4ed /camera
parent7bf511bf46760898e1429f38754821fff6287585 (diff)
downloadomap4xxx-omapzoom-ef73bec8a83a2fd7fbb072d009382c64eb2da0ee.tar.gz
CameraHal: Add more Exif data for video snapshot
Fixes b/5582076. Requires changes to Ducati and external/jhead. 1. Add API to get and set ancillary data metadata so we can use the values to fill in Exif data. 2. Add support for additional tags. Change-Id: I537e683839c59e92a4a20ff62653b6d46e303f53 Signed-off-by: Tyler Luu <tluu@ti.com> Signed-off-by: Iliyan Malchev <malchev@google.com>
Diffstat (limited to 'camera')
-rw-r--r--camera/Encoder_libjpeg.cpp10
-rwxr-xr-xcamera/OMXCameraAdapter/OMXCameraAdapter.cpp60
-rw-r--r--camera/OMXCameraAdapter/OMXCapture.cpp14
-rwxr-xr-xcamera/OMXCameraAdapter/OMXExif.cpp128
-rw-r--r--camera/OMXCameraAdapter/OMXFD.cpp23
-rwxr-xr-xcamera/inc/Encoder_libjpeg.h16
-rw-r--r--camera/inc/OMXCameraAdapter/OMXCameraAdapter.h6
7 files changed, 220 insertions, 37 deletions
diff --git a/camera/Encoder_libjpeg.cpp b/camera/Encoder_libjpeg.cpp
index 0240fb0d..40b237b8 100644
--- a/camera/Encoder_libjpeg.cpp
+++ b/camera/Encoder_libjpeg.cpp
@@ -44,6 +44,7 @@ extern "C" {
}
#define ARRAY_SIZE(array) (sizeof((array)) / sizeof((array)[0]))
+#define MIN(x,y) ((x < y) ? x : y)
namespace android {
struct string_pair {
@@ -305,7 +306,7 @@ ExifElementsTable::~ExifElementsTable() {
}
status_t ExifElementsTable::insertElement(const char* tag, const char* value) {
- int value_length = 0;
+ unsigned int value_length = 0;
status_t ret = NO_ERROR;
if (!value || !tag) {
@@ -331,6 +332,13 @@ status_t ExifElementsTable::insertElement(const char* tag, const char* value) {
table[position].GpsTag = FALSE;
table[position].Tag = TagNameToValue(tag);
exif_tag_count++;
+
+ // jhead isn't taking datetime tag...this is a WA
+ if (strcmp(tag, TAG_DATETIME) == 0) {
+ ImageInfo.numDateTimeTags = 1;
+ memcpy(ImageInfo.DateTime, value,
+ MIN(ARRAY_SIZE(ImageInfo.DateTime), value_length + 1));
+ }
}
table[position].DataLength = 0;
diff --git a/camera/OMXCameraAdapter/OMXCameraAdapter.cpp b/camera/OMXCameraAdapter/OMXCameraAdapter.cpp
index 01d37eac..c5dff6ca 100755
--- a/camera/OMXCameraAdapter/OMXCameraAdapter.cpp
+++ b/camera/OMXCameraAdapter/OMXCameraAdapter.cpp
@@ -1757,7 +1757,6 @@ status_t OMXCameraAdapter::startPreview()
OMX_ERRORTYPE eError = OMX_ErrorNone;
OMXCameraPortParameters *mPreviewData = NULL;
OMXCameraPortParameters *measurementData = NULL;
- OMX_CONFIG_EXTRADATATYPE extraDataControl;
LOG_FUNCTION_NAME;
@@ -1869,15 +1868,7 @@ status_t OMXCameraAdapter::startPreview()
// whether the preview frame is a snapshot
if ( OMX_ErrorNone == eError)
{
- OMX_INIT_STRUCT_PTR (&extraDataControl, OMX_CONFIG_EXTRADATATYPE);
- extraDataControl.nPortIndex = OMX_ALL;
- extraDataControl.eExtraDataType = OMX_AncillaryData;
- extraDataControl.bEnable = OMX_TRUE;
-
- eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
- ( OMX_INDEXTYPE ) OMX_IndexConfigOtherExtraDataControl,
- &extraDataControl);
- GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
+ ret = setExtraData(true, OMX_ALL, OMX_AncillaryData);
}
@@ -2918,7 +2909,7 @@ OMX_ERRORTYPE OMXCameraAdapter::OMXCameraAdapterFillBufferDone(OMX_IN OMX_HANDLE
CameraFrame cameraFrame;
OMX_TI_PLATFORMPRIVATE *platformPrivate;
OMX_OTHER_EXTRADATATYPE *extraData;
- OMX_TI_ANCILLARYDATATYPE *ancillaryData;
+ OMX_TI_ANCILLARYDATATYPE *ancillaryData = NULL;
bool snapshotFrame = false;
res1 = res2 = NO_ERROR;
@@ -2951,7 +2942,6 @@ OMX_ERRORTYPE OMXCameraAdapter::OMXCameraAdapterFillBufferDone(OMX_IN OMX_HANDLE
}
recalculateFPS();
-
{
Mutex::Autolock lock(mFaceDetectionLock);
if ( mFaceDetectionRunning && !mFaceDetectionPaused ) {
@@ -2977,6 +2967,16 @@ OMX_ERRORTYPE OMXCameraAdapter::OMXCameraAdapterFillBufferDone(OMX_IN OMX_HANDLE
{
typeOfFrame = CameraFrame::SNAPSHOT_FRAME;
mask = (unsigned int)CameraFrame::SNAPSHOT_FRAME;
+
+ // video snapshot gets ancillary data and wb info from last snapshot frame
+ mCaptureAncillaryData = ancillaryData;
+ mWhiteBalanceData = NULL;
+ extraData = getExtradata((OMX_OTHER_EXTRADATATYPE*) platformPrivate->pMetaDataBuffer,
+ (OMX_EXTRADATATYPE) OMX_WhiteBalance);
+ if ( NULL != extraData )
+ {
+ mWhiteBalanceData = (OMX_TI_WHITEBALANCERESULTTYPE*) extraData->data;
+ }
}
else
{
@@ -3063,7 +3063,7 @@ OMX_ERRORTYPE OMXCameraAdapter::OMXCameraAdapterFillBufferDone(OMX_IN OMX_HANDLE
// populate exif data and pass to subscribers via quirk
// subscriber is in charge of freeing exif data
ExifElementsTable* exif = new ExifElementsTable();
- setupEXIF_libjpeg(exif);
+ setupEXIF_libjpeg(exif, mCaptureAncillaryData, mWhiteBalanceData);
cameraFrame.mQuirks |= CameraFrame::HAS_EXIF_DATA;
cameraFrame.mCookie2 = (void*) exif;
}
@@ -3380,6 +3380,40 @@ bool OMXCameraAdapter::OMXCallbackHandler::Handler()
return false;
}
+status_t OMXCameraAdapter::setExtraData(bool enable, OMX_U32 nPortIndex, OMX_EXT_EXTRADATATYPE eType) {
+ status_t ret = NO_ERROR;
+ OMX_ERRORTYPE eError = OMX_ErrorNone;
+ OMX_CONFIG_EXTRADATATYPE extraDataControl;
+
+ LOG_FUNCTION_NAME;
+
+ if (OMX_StateInvalid == mComponentState) {
+ CAMHAL_LOGEA("OMX component is in invalid state");
+ return -EINVAL;
+ }
+
+ OMX_INIT_STRUCT_PTR (&extraDataControl, OMX_CONFIG_EXTRADATATYPE);
+
+ extraDataControl.nPortIndex = nPortIndex;
+ extraDataControl.eExtraDataType = eType;
+ extraDataControl.eCameraView = OMX_2D;
+
+ if (enable) {
+ extraDataControl.bEnable = OMX_TRUE;
+ } else {
+ extraDataControl.bEnable = OMX_FALSE;
+ }
+
+ eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
+ (OMX_INDEXTYPE) OMX_IndexConfigOtherExtraDataControl,
+ &extraDataControl);
+
+ LOG_FUNCTION_NAME_EXIT;
+
+ return (ret | ErrorUtils::omxToAndroidError(eError));
+}
+
+
OMX_OTHER_EXTRADATATYPE *OMXCameraAdapter::getExtradata(OMX_OTHER_EXTRADATATYPE *extraData, OMX_EXTRADATATYPE type)
{
if ( NULL != extraData )
diff --git a/camera/OMXCameraAdapter/OMXCapture.cpp b/camera/OMXCameraAdapter/OMXCapture.cpp
index 9ba438cc..43d07253 100644
--- a/camera/OMXCameraAdapter/OMXCapture.cpp
+++ b/camera/OMXCameraAdapter/OMXCapture.cpp
@@ -775,6 +775,12 @@ status_t OMXCameraAdapter::startImageCapture()
}
}
+ // need to enable wb data for video snapshot to fill in exif data
+ if ((ret == NO_ERROR) && (mCapMode == VIDEO_MODE)) {
+ // video snapshot uses wb data from snapshot frame
+ ret = setExtraData(true, mCameraAdapterParameters.mPrevPortIndex, OMX_WhiteBalance);
+ }
+
//OMX shutter callback events are only available in hq mode
if ( (HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode))
{
@@ -866,6 +872,7 @@ status_t OMXCameraAdapter::startImageCapture()
EXIT:
CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
+ setExtraData(false, mCameraAdapterParameters.mPrevPortIndex, OMX_WhiteBalance);
mWaitingForSnapshot = false;
mCaptureSignalled = false;
performCleanupAfterError();
@@ -945,6 +952,13 @@ status_t OMXCameraAdapter::stopImageCapture()
goto EXIT;
}
}
+
+ // had to enable wb data for video snapshot to fill in exif data
+ // now that we are done...disable
+ if ((ret == NO_ERROR) && (mCapMode == VIDEO_MODE)) {
+ ret = setExtraData(false, mCameraAdapterParameters.mPrevPortIndex, OMX_WhiteBalance);
+ }
+
CAMHAL_LOGDB("Capture set - 0x%x", eError);
mCaptureSignalled = true; //set this to true if we exited because of timeout
diff --git a/camera/OMXCameraAdapter/OMXExif.cpp b/camera/OMXCameraAdapter/OMXExif.cpp
index 9744cf4e..32bfd7d4 100755
--- a/camera/OMXCameraAdapter/OMXExif.cpp
+++ b/camera/OMXCameraAdapter/OMXExif.cpp
@@ -497,7 +497,9 @@ status_t OMXCameraAdapter::setupEXIF()
return ret;
}
-status_t OMXCameraAdapter::setupEXIF_libjpeg(ExifElementsTable* exifTable)
+status_t OMXCameraAdapter::setupEXIF_libjpeg(ExifElementsTable* exifTable,
+ OMX_TI_ANCILLARYDATATYPE* pAncillaryData,
+ OMX_TI_WHITEBALANCERESULTTYPE* pWhiteBalanceData)
{
status_t ret = NO_ERROR;
OMX_ERRORTYPE eError = OMX_ErrorNone;
@@ -544,7 +546,6 @@ status_t OMXCameraAdapter::setupEXIF_libjpeg(ExifElementsTable* exifTable)
pTime->tm_hour,
pTime->tm_min,
pTime->tm_sec );
-
ret = exifTable->insertElement(TAG_DATETIME, temp_value);
}
}
@@ -658,6 +659,129 @@ status_t OMXCameraAdapter::setupEXIF_libjpeg(ExifElementsTable* exifTable)
}
}
+ // fill in short and ushort tags
+ if (NO_ERROR == ret) {
+ char temp_value[2];
+ temp_value[1] = '\0';
+
+ // AWB
+ if (mParameters3A.WhiteBallance == OMX_WhiteBalControlAuto) {
+ temp_value[0] = '0';
+ } else {
+ temp_value[0] = '1';
+ }
+ exifTable->insertElement(TAG_WHITEBALANCE, temp_value);
+
+ // MeteringMode
+ // TODO(XXX): only supporting this metering mode at the moment, may change in future
+ temp_value[0] = '2';
+ exifTable->insertElement(TAG_METERING_MODE, temp_value);
+
+ // ExposureProgram
+ // TODO(XXX): only supporting this exposure program at the moment, may change in future
+ temp_value[0] = '3';
+ exifTable->insertElement(TAG_EXPOSURE_PROGRAM, temp_value);
+
+ // ColorSpace
+ temp_value[0] = '1';
+ exifTable->insertElement(TAG_COLOR_SPACE, temp_value);
+
+ temp_value[0] = '2';
+ exifTable->insertElement(TAG_SENSING_METHOD, temp_value);
+
+ temp_value[0] = '1';
+ exifTable->insertElement(TAG_CUSTOM_RENDERED, temp_value);
+ }
+
+ if (pAncillaryData && (NO_ERROR == ret)) {
+ unsigned int numerator = 0, denominator = 0;
+ char temp_value[256];
+ unsigned int temp_num = 0;
+
+ // DigitalZoomRatio
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%u/%u",
+ pAncillaryData->nDigitalZoomFactor, 1024);
+ exifTable->insertElement(TAG_DIGITALZOOMRATIO, temp_value);
+
+ // ExposureTime
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%u/%u",
+ pAncillaryData->nExposureTime, 1000000);
+ exifTable->insertElement(TAG_EXPOSURETIME, temp_value);
+
+ // ApertureValue and FNumber
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%u/%u",
+ pAncillaryData->nApertureValue, 100);
+ exifTable->insertElement(TAG_FNUMBER, temp_value);
+ exifTable->insertElement(TAG_APERTURE, temp_value);
+
+ // ISO
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%u,0,0",
+ pAncillaryData->nCurrentISO);
+ exifTable->insertElement(TAG_ISO_EQUIVALENT, temp_value);
+
+ // ShutterSpeed
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%f",
+ log(pAncillaryData->nExposureTime) / log(2));
+ ExifElementsTable::stringToRational(temp_value, &numerator, &denominator);
+ snprintf(temp_value, sizeof(temp_value)/sizeof(char), "%u/%u", numerator, denominator);
+ exifTable->insertElement(TAG_SHUTTERSPEED, temp_value);
+
+ // Flash
+ if (mParameters3A.FlashMode == OMX_IMAGE_FlashControlAuto) {
+ if(pAncillaryData->nFlashStatus) temp_num = 0x19; // Flash fired, auto mode
+ else temp_num = 0x18; // Flash did not fire, auto mode
+ } else if (mParameters3A.FlashMode == OMX_IMAGE_FlashControlOn) {
+ if(pAncillaryData->nFlashStatus) temp_num = 0x9; // Flash fired, compulsory flash mode
+ else temp_num = 0x10; // Flash did not fire, compulsory flash mode
+ } else if(pAncillaryData->nFlashStatus) {
+ temp_num = 0x1; // Flash fired
+ } else {
+ temp_num = 0x0; // Flash did not fire
+ }
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%u", temp_num);
+ exifTable->insertElement(TAG_FLASH, temp_value);
+
+ if (pWhiteBalanceData) {
+ unsigned int lightsource = 0;
+ unsigned int colourtemp = pWhiteBalanceData->nColorTemperature;
+ bool flash_fired = (temp_num & 0x1); // value from flash above
+
+ // stole this from framework/tools_library/src/tools_sys_exif_tags.c
+ if( colourtemp <= 3200 ) {
+ lightsource = 3; // Tungsten
+ } else if( colourtemp > 3200 && colourtemp <= 4800 ) {
+ lightsource = 2; // Fluorescent
+ } else if( colourtemp > 4800 && colourtemp <= 5500 ) {
+ lightsource = 1; // Daylight
+ } else if( colourtemp > 5500 && colourtemp <= 6500 ) {
+ lightsource = 9; // Fine weather
+ } else if( colourtemp > 6500 ) {
+ lightsource = 10; // Cloudy weather
+ }
+
+ if(flash_fired) {
+ lightsource = 4; // Flash
+ }
+
+ snprintf(temp_value,
+ sizeof(temp_value)/sizeof(char),
+ "%u", lightsource);
+ exifTable->insertElement(TAG_LIGHT_SOURCE, temp_value);
+ }
+ }
+
LOG_FUNCTION_NAME_EXIT;
return ret;
diff --git a/camera/OMXCameraAdapter/OMXFD.cpp b/camera/OMXCameraAdapter/OMXFD.cpp
index 38c7a6ec..938ccf64 100644
--- a/camera/OMXCameraAdapter/OMXFD.cpp
+++ b/camera/OMXCameraAdapter/OMXFD.cpp
@@ -125,7 +125,6 @@ status_t OMXCameraAdapter::setFaceDetection(bool enable, OMX_U32 orientation)
{
status_t ret = NO_ERROR;
OMX_ERRORTYPE eError = OMX_ErrorNone;
- OMX_CONFIG_EXTRADATATYPE extraDataControl;
OMX_CONFIG_OBJDETECTIONTYPE objDetection;
LOG_FUNCTION_NAME;
@@ -170,27 +169,11 @@ status_t OMXCameraAdapter::setFaceDetection(bool enable, OMX_U32 orientation)
if ( NO_ERROR == ret )
{
- OMX_INIT_STRUCT_PTR (&extraDataControl, OMX_CONFIG_EXTRADATATYPE);
- extraDataControl.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
- extraDataControl.eExtraDataType = OMX_FaceDetection;
- extraDataControl.eCameraView = OMX_2D;
- if ( enable )
- {
- extraDataControl.bEnable = OMX_TRUE;
- }
- else
- {
- extraDataControl.bEnable = OMX_FALSE;
- }
+ ret = setExtraData(enable, mCameraAdapterParameters.mPrevPortIndex, OMX_FaceDetection);
- eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
- ( OMX_INDEXTYPE ) OMX_IndexConfigOtherExtraDataControl,
- &extraDataControl);
- if ( OMX_ErrorNone != eError )
+ if ( NO_ERROR != ret )
{
- CAMHAL_LOGEB("Error while configuring face detection extra data 0x%x",
- eError);
- ret = -1;
+ CAMHAL_LOGEA("Error while configuring face detection extra data");
}
else
{
diff --git a/camera/inc/Encoder_libjpeg.h b/camera/inc/Encoder_libjpeg.h
index e3e9ac55..e4dfc0f2 100755
--- a/camera/inc/Encoder_libjpeg.h
+++ b/camera/inc/Encoder_libjpeg.h
@@ -43,6 +43,7 @@ typedef void (*encoder_libjpeg_callback_t) (void* main_jpeg,
void* cookie2,
void* cookie3);
+// these have to match strings defined in external/jhead/exif.c
static const char TAG_MODEL[] = "Model";
static const char TAG_MAKE[] = "Make";
static const char TAG_FOCALLENGTH[] = "FocalLength";
@@ -61,6 +62,21 @@ 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";
+static const char TAG_FLASH[] = "Flash";
+static const char TAG_DIGITALZOOMRATIO[] = "DigitalZoomRatio";
+static const char TAG_EXPOSURETIME[] = "ExposureTime";
+static const char TAG_APERTURE[] = "ApertureValue";
+static const char TAG_ISO_EQUIVALENT[] = "ISOSpeedRatings";
+static const char TAG_WHITEBALANCE[] = "WhiteBalance";
+static const char TAG_LIGHT_SOURCE[] = "LightSource";
+static const char TAG_METERING_MODE[] = "MeteringMode";
+static const char TAG_EXPOSURE_PROGRAM[] = "ExposureProgram";
+static const char TAG_COLOR_SPACE[] = "ColorSpace";
+static const char TAG_CPRS_BITS_PER_PIXEL[] = "CompressedBitsPerPixel";
+static const char TAG_FNUMBER[] = "FNumber";
+static const char TAG_SHUTTERSPEED[] = "ShutterSpeedValue";
+static const char TAG_SENSING_METHOD[] = "SensingMethod";
+static const char TAG_CUSTOM_RENDERED[] = "CustomRendered";
class ExifElementsTable {
public:
diff --git a/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h b/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h
index 463032a2..981e22dd 100644
--- a/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h
+++ b/camera/inc/OMXCameraAdapter/OMXCameraAdapter.h
@@ -446,7 +446,8 @@ 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*);
+ status_t setupEXIF_libjpeg(ExifElementsTable*, OMX_TI_ANCILLARYDATATYPE*,
+ OMX_TI_WHITEBALANCERESULTTYPE*);
//Focus functionality
status_t doAutoFocus();
@@ -640,6 +641,7 @@ private:
status_t setAutoConvergence(OMX_TI_AUTOCONVERGENCEMODETYPE pACMode, OMX_S32 pManualConverence);
status_t getAutoConvergence(OMX_TI_AUTOCONVERGENCEMODETYPE *pACMode, OMX_S32 *pManualConverence);
+ status_t setExtraData(bool enable, OMX_U32, OMX_EXT_EXTRADATATYPE);
OMX_OTHER_EXTRADATATYPE *getExtradata(OMX_OTHER_EXTRADATATYPE *extraData, OMX_EXTRADATATYPE type);
class CommandHandler : public Thread {
@@ -873,6 +875,8 @@ private:
int mSnapshotCount;
bool mCaptureConfigured;
unsigned int mPendingCaptureSettings;
+ OMX_TI_ANCILLARYDATATYPE* mCaptureAncillaryData;
+ OMX_TI_WHITEBALANCERESULTTYPE* mWhiteBalanceData;
//Temporal bracketing management data
mutable Mutex mBracketingLock;