diff options
-rw-r--r-- | camera/Encoder_libjpeg.cpp | 10 | ||||
-rwxr-xr-x | camera/OMXCameraAdapter/OMXCameraAdapter.cpp | 60 | ||||
-rw-r--r-- | camera/OMXCameraAdapter/OMXCapture.cpp | 14 | ||||
-rwxr-xr-x | camera/OMXCameraAdapter/OMXExif.cpp | 128 | ||||
-rw-r--r-- | camera/OMXCameraAdapter/OMXFD.cpp | 23 | ||||
-rwxr-xr-x | camera/inc/Encoder_libjpeg.h | 16 | ||||
-rw-r--r-- | camera/inc/OMXCameraAdapter/OMXCameraAdapter.h | 6 |
7 files changed, 220 insertions, 37 deletions
diff --git a/camera/Encoder_libjpeg.cpp b/camera/Encoder_libjpeg.cpp index 0240fb0..40b237b 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 01d37ea..c5dff6c 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 9ba438c..43d0725 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 9744cf4..32bfd7d 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 38c7a6e..938ccf6 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 e3e9ac5..e4dfc0f 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 463032a..981e22d 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 °, 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; |