1 /* 2 * Copyright (C) Texas Instruments - http://www.ti.com/ 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * @file OMXExif.cpp 19 * 20 * This file contains functionality for handling EXIF insertion. 21 * 22 */ 23 24 #undef LOG_TAG 25 26 #define LOG_TAG "CameraHAL" 27 28 #include "CameraHal.h" 29 #include "OMXCameraAdapter.h" 30 #include <math.h> 31 32 namespace android { 33 34 status_t OMXCameraAdapter::setParametersEXIF(const CameraParameters ¶ms, 35 BaseCameraAdapter::AdapterState state) 36 { 37 status_t ret = NO_ERROR; 38 const char *valstr = NULL; 39 double gpsPos; 40 41 LOG_FUNCTION_NAME; 42 43 if( ( valstr = params.get(CameraParameters::KEY_GPS_LATITUDE) ) != NULL ) 44 { 45 gpsPos = strtod(valstr, NULL); 46 47 if ( convertGPSCoord(gpsPos, 48 mEXIFData.mGPSData.mLatDeg, 49 mEXIFData.mGPSData.mLatMin, 50 mEXIFData.mGPSData.mLatSec, 51 mEXIFData.mGPSData.mLatSecDiv ) == NO_ERROR ) 52 { 53 54 if ( 0 < gpsPos ) 55 { 56 strncpy(mEXIFData.mGPSData.mLatRef, GPS_NORTH_REF, GPS_REF_SIZE); 57 } 58 else 59 { 60 strncpy(mEXIFData.mGPSData.mLatRef, GPS_SOUTH_REF, GPS_REF_SIZE); 61 } 62 63 mEXIFData.mGPSData.mLatValid = true; 64 } 65 else 66 { 67 mEXIFData.mGPSData.mLatValid = false; 68 } 69 } 70 else 71 { 72 mEXIFData.mGPSData.mLatValid = false; 73 } 74 75 if( ( valstr = params.get(CameraParameters::KEY_GPS_LONGITUDE) ) != NULL ) 76 { 77 gpsPos = strtod(valstr, NULL); 78 79 if ( convertGPSCoord(gpsPos, 80 mEXIFData.mGPSData.mLongDeg, 81 mEXIFData.mGPSData.mLongMin, 82 mEXIFData.mGPSData.mLongSec, 83 mEXIFData.mGPSData.mLongSecDiv) == NO_ERROR ) 84 { 85 86 if ( 0 < gpsPos ) 87 { 88 strncpy(mEXIFData.mGPSData.mLongRef, GPS_EAST_REF, GPS_REF_SIZE); 89 } 90 else 91 { 92 strncpy(mEXIFData.mGPSData.mLongRef, GPS_WEST_REF, GPS_REF_SIZE); 93 } 94 95 mEXIFData.mGPSData.mLongValid= true; 96 } 97 else 98 { 99 mEXIFData.mGPSData.mLongValid = false; 100 } 101 } 102 else 103 { 104 mEXIFData.mGPSData.mLongValid = false; 105 } 106 107 if( ( valstr = params.get(CameraParameters::KEY_GPS_ALTITUDE) ) != NULL ) 108 { 109 gpsPos = strtod(valstr, NULL); 110 mEXIFData.mGPSData.mAltitude = floor(fabs(gpsPos)); 111 if (gpsPos < 0) { 112 mEXIFData.mGPSData.mAltitudeRef = 1; 113 } else { 114 mEXIFData.mGPSData.mAltitudeRef = 0; 115 } 116 mEXIFData.mGPSData.mAltitudeValid = true; 117 } 118 else 119 { 120 mEXIFData.mGPSData.mAltitudeValid= false; 121 } 122 123 if( (valstr = params.get(CameraParameters::KEY_GPS_TIMESTAMP)) != NULL ) 124 { 125 long gpsTimestamp = strtol(valstr, NULL, 10); 126 struct tm *timeinfo = gmtime( ( time_t * ) & (gpsTimestamp) ); 127 if ( NULL != timeinfo ) 128 { 129 mEXIFData.mGPSData.mTimeStampHour = timeinfo->tm_hour; 130 mEXIFData.mGPSData.mTimeStampMin = timeinfo->tm_min; 131 mEXIFData.mGPSData.mTimeStampSec = timeinfo->tm_sec; 132 mEXIFData.mGPSData.mTimeStampValid = true; 133 } 134 else 135 { 136 mEXIFData.mGPSData.mTimeStampValid = false; 137 } 138 } 139 else 140 { 141 mEXIFData.mGPSData.mTimeStampValid = false; 142 } 143 144 if( ( valstr = params.get(CameraParameters::KEY_GPS_TIMESTAMP) ) != NULL ) 145 { 146 long gpsDatestamp = strtol(valstr, NULL, 10); 147 struct tm *timeinfo = gmtime( ( time_t * ) & (gpsDatestamp) ); 148 if ( NULL != timeinfo ) 149 { 150 strftime(mEXIFData.mGPSData.mDatestamp, GPS_DATESTAMP_SIZE, "%Y:%m:%d", timeinfo); 151 mEXIFData.mGPSData.mDatestampValid = true; 152 } 153 else 154 { 155 mEXIFData.mGPSData.mDatestampValid = false; 156 } 157 } 158 else 159 { 160 mEXIFData.mGPSData.mDatestampValid = false; 161 } 162 163 if( ( valstr = params.get(CameraParameters::KEY_GPS_PROCESSING_METHOD) ) != NULL ) 164 { 165 strncpy(mEXIFData.mGPSData.mProcMethod, valstr, GPS_PROCESSING_SIZE-1); 166 mEXIFData.mGPSData.mProcMethodValid = true; 167 } 168 else 169 { 170 mEXIFData.mGPSData.mProcMethodValid = false; 171 } 172 173 if( ( valstr = params.get(TICameraParameters::KEY_GPS_MAPDATUM) ) != NULL ) 174 { 175 strncpy(mEXIFData.mGPSData.mMapDatum, valstr, GPS_MAPDATUM_SIZE-1); 176 mEXIFData.mGPSData.mMapDatumValid = true; 177 } 178 else 179 { 180 mEXIFData.mGPSData.mMapDatumValid = false; 181 } 182 183 if( ( valstr = params.get(TICameraParameters::KEY_GPS_VERSION) ) != NULL ) 184 { 185 strncpy(mEXIFData.mGPSData.mVersionId, valstr, GPS_VERSION_SIZE-1); 186 mEXIFData.mGPSData.mVersionIdValid = true; 187 } 188 else 189 { 190 mEXIFData.mGPSData.mVersionIdValid = false; 191 } 192 193 if( ( valstr = params.get(TICameraParameters::KEY_EXIF_MODEL ) ) != NULL ) 194 { 195 CAMHAL_LOGVB("EXIF Model: %s", valstr); 196 strncpy(mEXIFData.mModel, valstr, EXIF_MODEL_SIZE - 1); 197 mEXIFData.mModelValid= true; 198 } 199 else 200 { 201 mEXIFData.mModelValid= false; 202 } 203 204 if( ( valstr = params.get(TICameraParameters::KEY_EXIF_MAKE ) ) != NULL ) 205 { 206 CAMHAL_LOGVB("EXIF Make: %s", valstr); 207 strncpy(mEXIFData.mMake, valstr, EXIF_MAKE_SIZE - 1); 208 mEXIFData.mMakeValid = true; 209 } 210 else 211 { 212 mEXIFData.mMakeValid= false; 213 } 214 215 216 if( ( valstr = params.get(CameraParameters::KEY_FOCAL_LENGTH) ) != NULL ) { 217 CAMHAL_LOGVB("EXIF Focal length: %s", valstr); 218 ExifElementsTable::stringToRational(valstr, 219 &mEXIFData.mFocalNum, 220 &mEXIFData.mFocalDen); 221 } else { 222 mEXIFData.mFocalNum = 0; 223 mEXIFData.mFocalDen = 0; 224 } 225 226 227 LOG_FUNCTION_NAME_EXIT; 228 229 return ret; 230 } 231 232 status_t OMXCameraAdapter::setupEXIF() 233 { 234 status_t ret = NO_ERROR; 235 OMX_ERRORTYPE eError = OMX_ErrorNone; 236 OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer; 237 OMX_TI_CONFIG_EXIF_TAGS *exifTags; 238 unsigned char *sharedPtr = NULL; 239 struct timeval sTv; 240 struct tm *pTime; 241 OMXCameraPortParameters * capData = NULL; 242 MemoryManager memMgr; 243 OMX_U8** memmgr_buf_array = NULL; 244 int buf_size = 0; 245 246 LOG_FUNCTION_NAME; 247 248 sharedBuffer.pSharedBuff = NULL; 249 capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 250 251 if ( OMX_StateInvalid == mComponentState ) 252 { 253 CAMHAL_LOGEA("OMX component is in invalid state"); 254 ret = -EINVAL; 255 } 256 257 if ( NO_ERROR == ret ) 258 { 259 OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER); 260 sharedBuffer.nPortIndex = mCameraAdapterParameters.mImagePortIndex; 261 262 //We allocate the shared buffer dynamically based on the 263 //requirements of the EXIF tags. The additional buffers will 264 //get stored after the EXIF configuration structure and the pointers 265 //will contain offsets within the shared buffer itself. 266 buf_size = sizeof(OMX_TI_CONFIG_EXIF_TAGS) + 267 ( EXIF_MODEL_SIZE ) + 268 ( EXIF_MAKE_SIZE ) + 269 ( EXIF_DATE_TIME_SIZE ) + 270 ( GPS_MAPDATUM_SIZE ) + 271 ( GPS_PROCESSING_SIZE ); 272 buf_size = ((buf_size+4095)/4096)*4096; 273 sharedBuffer.nSharedBuffSize = buf_size; 274 275 memmgr_buf_array = (OMX_U8 **)memMgr.allocateBuffer(0, 0, NULL, buf_size, 1); 276 sharedBuffer.pSharedBuff = ( OMX_U8 * ) memmgr_buf_array[0]; 277 278 if ( NULL == sharedBuffer.pSharedBuff ) 279 { 280 CAMHAL_LOGEA("No resources to allocate OMX shared buffer"); 281 ret = -1; 282 } 283 284 //Extra data begins right after the EXIF configuration structure. 285 sharedPtr = sharedBuffer.pSharedBuff + sizeof(OMX_TI_CONFIG_EXIF_TAGS); 286 } 287 288 if ( NO_ERROR == ret ) 289 { 290 exifTags = ( OMX_TI_CONFIG_EXIF_TAGS * ) sharedBuffer.pSharedBuff; 291 OMX_INIT_STRUCT_PTR (exifTags, OMX_TI_CONFIG_EXIF_TAGS); 292 exifTags->nPortIndex = mCameraAdapterParameters.mImagePortIndex; 293 294 eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, 295 ( OMX_INDEXTYPE ) OMX_TI_IndexConfigExifTags, 296 &sharedBuffer ); 297 if ( OMX_ErrorNone != eError ) 298 { 299 CAMHAL_LOGEB("Error while retrieving EXIF configuration structure 0x%x", eError); 300 ret = -1; 301 } 302 } 303 304 if ( NO_ERROR == ret ) 305 { 306 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusModel ) && 307 ( mEXIFData.mModelValid ) ) 308 { 309 strncpy(( char * ) sharedPtr, 310 mEXIFData.mModel, 311 EXIF_MODEL_SIZE - 1); 312 313 exifTags->pModelBuff = ( OMX_S8 * ) ( sharedPtr - sharedBuffer.pSharedBuff ); 314 exifTags->ulModelBuffSizeBytes = strlen((char*)sharedPtr) + 1; 315 sharedPtr += EXIF_MODEL_SIZE; 316 exifTags->eStatusModel = OMX_TI_TagUpdated; 317 } 318 319 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusMake) && 320 ( mEXIFData.mMakeValid ) ) 321 { 322 strncpy( ( char * ) sharedPtr, 323 mEXIFData.mMake, 324 EXIF_MAKE_SIZE - 1); 325 326 exifTags->pMakeBuff = ( OMX_S8 * ) ( sharedPtr - sharedBuffer.pSharedBuff ); 327 exifTags->ulMakeBuffSizeBytes = strlen((char*)sharedPtr) + 1; 328 sharedPtr += EXIF_MAKE_SIZE; 329 exifTags->eStatusMake = OMX_TI_TagUpdated; 330 } 331 332 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusFocalLength )) 333 { 334 if (mEXIFData.mFocalNum || mEXIFData.mFocalDen ) { 335 exifTags->ulFocalLength[0] = (OMX_U32) mEXIFData.mFocalNum; 336 exifTags->ulFocalLength[1] = (OMX_U32) mEXIFData.mFocalDen; 337 CAMHAL_LOGVB("exifTags->ulFocalLength = [%u] [%u]", 338 (unsigned int)(exifTags->ulFocalLength[0]), 339 (unsigned int)(exifTags->ulFocalLength[1])); 340 exifTags->eStatusFocalLength = OMX_TI_TagUpdated; 341 } 342 } 343 344 if ( OMX_TI_TagReadWrite == exifTags->eStatusDateTime ) 345 { 346 int status = gettimeofday (&sTv, NULL); 347 pTime = localtime (&sTv.tv_sec); 348 if ( ( 0 == status ) && ( NULL != pTime ) ) 349 { 350 snprintf(( char * ) sharedPtr, EXIF_DATE_TIME_SIZE, 351 "%04d:%02d:%02d %02d:%02d:%02d", 352 pTime->tm_year + 1900, 353 pTime->tm_mon + 1, 354 pTime->tm_mday, 355 pTime->tm_hour, 356 pTime->tm_min, 357 pTime->tm_sec ); 358 } 359 360 exifTags->pDateTimeBuff = ( OMX_S8 * ) ( sharedPtr - sharedBuffer.pSharedBuff ); 361 sharedPtr += EXIF_DATE_TIME_SIZE; 362 exifTags->ulDateTimeBuffSizeBytes = EXIF_DATE_TIME_SIZE; 363 exifTags->eStatusDateTime = OMX_TI_TagUpdated; 364 } 365 366 if ( OMX_TI_TagReadWrite == exifTags->eStatusImageWidth ) 367 { 368 exifTags->ulImageWidth = capData->mWidth; 369 exifTags->eStatusImageWidth = OMX_TI_TagUpdated; 370 } 371 372 if ( OMX_TI_TagReadWrite == exifTags->eStatusImageHeight ) 373 { 374 exifTags->ulImageHeight = capData->mHeight; 375 exifTags->eStatusImageHeight = OMX_TI_TagUpdated; 376 } 377 378 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsLatitude ) && 379 ( mEXIFData.mGPSData.mLatValid ) ) 380 { 381 exifTags->ulGpsLatitude[0] = abs(mEXIFData.mGPSData.mLatDeg); 382 exifTags->ulGpsLatitude[2] = abs(mEXIFData.mGPSData.mLatMin); 383 exifTags->ulGpsLatitude[4] = abs(mEXIFData.mGPSData.mLatSec); 384 exifTags->ulGpsLatitude[1] = 1; 385 exifTags->ulGpsLatitude[3] = 1; 386 exifTags->ulGpsLatitude[5] = abs(mEXIFData.mGPSData.mLatSecDiv); 387 exifTags->eStatusGpsLatitude = OMX_TI_TagUpdated; 388 } 389 390 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpslatitudeRef ) && 391 ( mEXIFData.mGPSData.mLatValid ) ) 392 { 393 exifTags->cGpslatitudeRef[0] = ( OMX_S8 ) mEXIFData.mGPSData.mLatRef[0]; 394 exifTags->cGpslatitudeRef[1] = '\0'; 395 exifTags->eStatusGpslatitudeRef = OMX_TI_TagUpdated; 396 } 397 398 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsLongitude ) && 399 ( mEXIFData.mGPSData.mLongValid ) ) 400 { 401 exifTags->ulGpsLongitude[0] = abs(mEXIFData.mGPSData.mLongDeg); 402 exifTags->ulGpsLongitude[2] = abs(mEXIFData.mGPSData.mLongMin); 403 exifTags->ulGpsLongitude[4] = abs(mEXIFData.mGPSData.mLongSec); 404 exifTags->ulGpsLongitude[1] = 1; 405 exifTags->ulGpsLongitude[3] = 1; 406 exifTags->ulGpsLongitude[5] = abs(mEXIFData.mGPSData.mLongSecDiv); 407 exifTags->eStatusGpsLongitude = OMX_TI_TagUpdated; 408 } 409 410 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsLongitudeRef ) && 411 ( mEXIFData.mGPSData.mLongValid ) ) 412 { 413 exifTags->cGpsLongitudeRef[0] = ( OMX_S8 ) mEXIFData.mGPSData.mLongRef[0]; 414 exifTags->cGpsLongitudeRef[1] = '\0'; 415 exifTags->eStatusGpsLongitudeRef = OMX_TI_TagUpdated; 416 } 417 418 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsAltitude ) && 419 ( mEXIFData.mGPSData.mAltitudeValid) ) 420 { 421 exifTags->ulGpsAltitude[0] = ( OMX_U32 ) mEXIFData.mGPSData.mAltitude; 422 exifTags->ulGpsAltitude[1] = 1; 423 exifTags->eStatusGpsAltitude = OMX_TI_TagUpdated; 424 } 425 426 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsAltitudeRef ) && 427 ( mEXIFData.mGPSData.mAltitudeValid) ) 428 { 429 exifTags->ucGpsAltitudeRef = (OMX_U8) mEXIFData.mGPSData.mAltitudeRef; 430 exifTags->eStatusGpsAltitudeRef = OMX_TI_TagUpdated; 431 } 432 433 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsMapDatum ) && 434 ( mEXIFData.mGPSData.mMapDatumValid ) ) 435 { 436 memcpy(sharedPtr, mEXIFData.mGPSData.mMapDatum, GPS_MAPDATUM_SIZE); 437 438 exifTags->pGpsMapDatumBuff = ( OMX_S8 * ) ( sharedPtr - sharedBuffer.pSharedBuff ); 439 exifTags->ulGpsMapDatumBuffSizeBytes = GPS_MAPDATUM_SIZE; 440 exifTags->eStatusGpsMapDatum = OMX_TI_TagUpdated; 441 sharedPtr += GPS_MAPDATUM_SIZE; 442 } 443 444 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsProcessingMethod ) && 445 ( mEXIFData.mGPSData.mProcMethodValid ) ) 446 { 447 exifTags->pGpsProcessingMethodBuff = ( OMX_S8 * ) ( sharedPtr - sharedBuffer.pSharedBuff ); 448 memcpy(sharedPtr, ExifAsciiPrefix, sizeof(ExifAsciiPrefix)); 449 sharedPtr += sizeof(ExifAsciiPrefix); 450 451 memcpy(sharedPtr, 452 mEXIFData.mGPSData.mProcMethod, 453 ( GPS_PROCESSING_SIZE - sizeof(ExifAsciiPrefix) ) ); 454 exifTags->ulGpsProcessingMethodBuffSizeBytes = GPS_PROCESSING_SIZE; 455 exifTags->eStatusGpsProcessingMethod = OMX_TI_TagUpdated; 456 sharedPtr += GPS_PROCESSING_SIZE; 457 } 458 459 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsVersionId ) && 460 ( mEXIFData.mGPSData.mVersionIdValid ) ) 461 { 462 exifTags->ucGpsVersionId[0] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[0]; 463 exifTags->ucGpsVersionId[1] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[1]; 464 exifTags->ucGpsVersionId[2] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[2]; 465 exifTags->ucGpsVersionId[3] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[3]; 466 exifTags->eStatusGpsVersionId = OMX_TI_TagUpdated; 467 } 468 469 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsTimeStamp ) && 470 ( mEXIFData.mGPSData.mTimeStampValid ) ) 471 { 472 exifTags->ulGpsTimeStamp[0] = mEXIFData.mGPSData.mTimeStampHour; 473 exifTags->ulGpsTimeStamp[2] = mEXIFData.mGPSData.mTimeStampMin; 474 exifTags->ulGpsTimeStamp[4] = mEXIFData.mGPSData.mTimeStampSec; 475 exifTags->ulGpsTimeStamp[1] = 1; 476 exifTags->ulGpsTimeStamp[3] = 1; 477 exifTags->ulGpsTimeStamp[5] = 1; 478 exifTags->eStatusGpsTimeStamp = OMX_TI_TagUpdated; 479 } 480 481 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsDateStamp ) && 482 ( mEXIFData.mGPSData.mDatestampValid ) ) 483 { 484 strncpy( ( char * ) exifTags->cGpsDateStamp, 485 ( char * ) mEXIFData.mGPSData.mDatestamp, 486 GPS_DATESTAMP_SIZE ); 487 exifTags->eStatusGpsDateStamp = OMX_TI_TagUpdated; 488 } 489 490 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 491 ( OMX_INDEXTYPE ) OMX_TI_IndexConfigExifTags, 492 &sharedBuffer ); 493 494 if ( OMX_ErrorNone != eError ) 495 { 496 CAMHAL_LOGEB("Error while setting EXIF configuration 0x%x", eError); 497 ret = -1; 498 } 499 } 500 501 if ( NULL != memmgr_buf_array ) 502 { 503 memMgr.freeBuffer(memmgr_buf_array); 504 } 505 506 LOG_FUNCTION_NAME_EXIT; 507 508 return ret; 509 } 510 511 status_t OMXCameraAdapter::setupEXIF_libjpeg(ExifElementsTable* exifTable, 512 OMX_TI_ANCILLARYDATATYPE* pAncillaryData, 513 OMX_TI_WHITEBALANCERESULTTYPE* pWhiteBalanceData) 514 { 515 status_t ret = NO_ERROR; 516 OMX_ERRORTYPE eError = OMX_ErrorNone; 517 struct timeval sTv; 518 struct tm *pTime; 519 OMXCameraPortParameters * capData = NULL; 520 521 LOG_FUNCTION_NAME; 522 523 capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 524 525 if ((NO_ERROR == ret) && (mEXIFData.mModelValid)) { 526 ret = exifTable->insertElement(TAG_MODEL, mEXIFData.mModel); 527 } 528 529 if ((NO_ERROR == ret) && (mEXIFData.mMakeValid)) { 530 ret = exifTable->insertElement(TAG_MAKE, mEXIFData.mMake); 531 } 532 533 if ((NO_ERROR == ret)) { 534 if (mEXIFData.mFocalNum || mEXIFData.mFocalDen) { 535 char temp_value[256]; // arbitrarily long string 536 snprintf(temp_value, 537 sizeof(temp_value)/sizeof(char), 538 "%u/%u", 539 mEXIFData.mFocalNum, 540 mEXIFData.mFocalDen); 541 ret = exifTable->insertElement(TAG_FOCALLENGTH, temp_value); 542 543 } 544 } 545 546 if ((NO_ERROR == ret)) { 547 int status = gettimeofday (&sTv, NULL); 548 pTime = localtime (&sTv.tv_sec); 549 char temp_value[EXIF_DATE_TIME_SIZE + 1]; 550 if ((0 == status) && (NULL != pTime)) { 551 snprintf(temp_value, EXIF_DATE_TIME_SIZE, 552 "%04d:%02d:%02d %02d:%02d:%02d", 553 pTime->tm_year + 1900, 554 pTime->tm_mon + 1, 555 pTime->tm_mday, 556 pTime->tm_hour, 557 pTime->tm_min, 558 pTime->tm_sec ); 559 ret = exifTable->insertElement(TAG_DATETIME, temp_value); 560 } 561 } 562 563 if ((NO_ERROR == ret)) { 564 char temp_value[5]; 565 snprintf(temp_value, sizeof(temp_value)/sizeof(char), "%lu", capData->mWidth); 566 ret = exifTable->insertElement(TAG_IMAGE_WIDTH, temp_value); 567 } 568 569 if ((NO_ERROR == ret)) { 570 char temp_value[5]; 571 snprintf(temp_value, sizeof(temp_value)/sizeof(char), "%lu", capData->mHeight); 572 ret = exifTable->insertElement(TAG_IMAGE_LENGTH, temp_value); 573 } 574 575 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLatValid)) { 576 char temp_value[256]; // arbitrarily long string 577 snprintf(temp_value, 578 sizeof(temp_value)/sizeof(char) - 1, 579 "%d/%d,%d/%d,%d/%d", 580 abs(mEXIFData.mGPSData.mLatDeg), 1, 581 abs(mEXIFData.mGPSData.mLatMin), 1, 582 abs(mEXIFData.mGPSData.mLatSec), abs(mEXIFData.mGPSData.mLatSecDiv)); 583 ret = exifTable->insertElement(TAG_GPS_LAT, temp_value); 584 } 585 586 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLatValid)) { 587 ret = exifTable->insertElement(TAG_GPS_LAT_REF, mEXIFData.mGPSData.mLatRef); 588 } 589 590 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLongValid)) { 591 char temp_value[256]; // arbitrarily long string 592 snprintf(temp_value, 593 sizeof(temp_value)/sizeof(char) - 1, 594 "%d/%d,%d/%d,%d/%d", 595 abs(mEXIFData.mGPSData.mLongDeg), 1, 596 abs(mEXIFData.mGPSData.mLongMin), 1, 597 abs(mEXIFData.mGPSData.mLongSec), abs(mEXIFData.mGPSData.mLongSecDiv)); 598 ret = exifTable->insertElement(TAG_GPS_LONG, temp_value); 599 } 600 601 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLongValid)) { 602 ret = exifTable->insertElement(TAG_GPS_LONG_REF, mEXIFData.mGPSData.mLongRef); 603 } 604 605 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mAltitudeValid)) { 606 char temp_value[256]; // arbitrarily long string 607 snprintf(temp_value, 608 sizeof(temp_value)/sizeof(char) - 1, 609 "%d/%d", 610 abs( mEXIFData.mGPSData.mAltitude), 1); 611 ret = exifTable->insertElement(TAG_GPS_ALT, temp_value); 612 } 613 614 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mAltitudeValid)) { 615 char temp_value[5]; 616 snprintf(temp_value, 617 sizeof(temp_value)/sizeof(char) - 1, 618 "%d", mEXIFData.mGPSData.mAltitudeRef); 619 ret = exifTable->insertElement(TAG_GPS_ALT_REF, temp_value); 620 } 621 622 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mMapDatumValid)) { 623 ret = exifTable->insertElement(TAG_GPS_MAP_DATUM, mEXIFData.mGPSData.mMapDatum); 624 } 625 626 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mProcMethodValid)) { 627 char temp_value[GPS_PROCESSING_SIZE]; 628 629 memcpy(temp_value, ExifAsciiPrefix, sizeof(ExifAsciiPrefix)); 630 memcpy(temp_value + sizeof(ExifAsciiPrefix), 631 mEXIFData.mGPSData.mProcMethod, 632 (GPS_PROCESSING_SIZE - sizeof(ExifAsciiPrefix))); 633 ret = exifTable->insertElement(TAG_GPS_PROCESSING_METHOD, temp_value); 634 } 635 636 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mVersionIdValid)) { 637 char temp_value[256]; // arbitrarily long string 638 snprintf(temp_value, 639 sizeof(temp_value)/sizeof(char) - 1, 640 "%d,%d,%d,%d", 641 mEXIFData.mGPSData.mVersionId[0], 642 mEXIFData.mGPSData.mVersionId[1], 643 mEXIFData.mGPSData.mVersionId[2], 644 mEXIFData.mGPSData.mVersionId[3]); 645 ret = exifTable->insertElement(TAG_GPS_VERSION_ID, temp_value); 646 } 647 648 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mTimeStampValid)) { 649 char temp_value[256]; // arbitrarily long string 650 snprintf(temp_value, 651 sizeof(temp_value)/sizeof(char) - 1, 652 "%d/%d,%d/%d,%d/%d", 653 mEXIFData.mGPSData.mTimeStampHour, 1, 654 mEXIFData.mGPSData.mTimeStampMin, 1, 655 mEXIFData.mGPSData.mTimeStampSec, 1); 656 ret = exifTable->insertElement(TAG_GPS_TIMESTAMP, temp_value); 657 } 658 659 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mDatestampValid) ) { 660 ret = exifTable->insertElement(TAG_GPS_DATESTAMP, mEXIFData.mGPSData.mDatestamp); 661 } 662 663 if (NO_ERROR == ret) { 664 const char* exif_orient = 665 ExifElementsTable::degreesToExifOrientation(mPictureRotation); 666 667 if (exif_orient) { 668 ret = exifTable->insertElement(TAG_ORIENTATION, exif_orient); 669 } 670 } 671 672 // fill in short and ushort tags 673 if (NO_ERROR == ret) { 674 char temp_value[2]; 675 temp_value[1] = '\0'; 676 677 // AWB 678 if (mParameters3A.WhiteBallance == OMX_WhiteBalControlAuto) { 679 temp_value[0] = '0'; 680 } else { 681 temp_value[0] = '1'; 682 } 683 exifTable->insertElement(TAG_WHITEBALANCE, temp_value); 684 685 // MeteringMode 686 // TODO(XXX): only supporting this metering mode at the moment, may change in future 687 temp_value[0] = '2'; 688 exifTable->insertElement(TAG_METERING_MODE, temp_value); 689 690 // ExposureProgram 691 // TODO(XXX): only supporting this exposure program at the moment, may change in future 692 temp_value[0] = '3'; 693 exifTable->insertElement(TAG_EXPOSURE_PROGRAM, temp_value); 694 695 // ColorSpace 696 temp_value[0] = '1'; 697 exifTable->insertElement(TAG_COLOR_SPACE, temp_value); 698 699 temp_value[0] = '2'; 700 exifTable->insertElement(TAG_SENSING_METHOD, temp_value); 701 702 temp_value[0] = '1'; 703 exifTable->insertElement(TAG_CUSTOM_RENDERED, temp_value); 704 } 705 706 if (pAncillaryData && (NO_ERROR == ret)) { 707 unsigned int numerator = 0, denominator = 0; 708 char temp_value[256]; 709 unsigned int temp_num = 0; 710 711 // DigitalZoomRatio 712 snprintf(temp_value, 713 sizeof(temp_value)/sizeof(char), 714 "%u/%u", 715 pAncillaryData->nDigitalZoomFactor, 1024); 716 exifTable->insertElement(TAG_DIGITALZOOMRATIO, temp_value); 717 718 // ExposureTime 719 snprintf(temp_value, 720 sizeof(temp_value)/sizeof(char), 721 "%u/%u", 722 pAncillaryData->nExposureTime, 1000000); 723 exifTable->insertElement(TAG_EXPOSURETIME, temp_value); 724 725 // ApertureValue and FNumber 726 snprintf(temp_value, 727 sizeof(temp_value)/sizeof(char), 728 "%u/%u", 729 pAncillaryData->nApertureValue, 100); 730 exifTable->insertElement(TAG_FNUMBER, temp_value); 731 exifTable->insertElement(TAG_APERTURE, temp_value); 732 733 // ISO 734 snprintf(temp_value, 735 sizeof(temp_value)/sizeof(char), 736 "%u,0,0", 737 pAncillaryData->nCurrentISO); 738 exifTable->insertElement(TAG_ISO_EQUIVALENT, temp_value); 739 740 // ShutterSpeed 741 snprintf(temp_value, 742 sizeof(temp_value)/sizeof(char), 743 "%f", 744 log(pAncillaryData->nExposureTime) / log(2)); 745 ExifElementsTable::stringToRational(temp_value, &numerator, &denominator); 746 snprintf(temp_value, sizeof(temp_value)/sizeof(char), "%u/%u", numerator, denominator); 747 exifTable->insertElement(TAG_SHUTTERSPEED, temp_value); 748 749 // Flash 750 if (mParameters3A.FlashMode == OMX_IMAGE_FlashControlAuto) { 751 if(pAncillaryData->nFlashStatus) temp_num = 0x19; // Flash fired, auto mode 752 else temp_num = 0x18; // Flash did not fire, auto mode 753 } else if (mParameters3A.FlashMode == OMX_IMAGE_FlashControlOn) { 754 if(pAncillaryData->nFlashStatus) temp_num = 0x9; // Flash fired, compulsory flash mode 755 else temp_num = 0x10; // Flash did not fire, compulsory flash mode 756 } else if(pAncillaryData->nFlashStatus) { 757 temp_num = 0x1; // Flash fired 758 } else { 759 temp_num = 0x0; // Flash did not fire 760 } 761 snprintf(temp_value, 762 sizeof(temp_value)/sizeof(char), 763 "%u", temp_num); 764 exifTable->insertElement(TAG_FLASH, temp_value); 765 766 if (pWhiteBalanceData) { 767 unsigned int lightsource = 0; 768 unsigned int colourtemp = pWhiteBalanceData->nColorTemperature; 769 bool flash_fired = (temp_num & 0x1); // value from flash above 770 771 // stole this from framework/tools_library/src/tools_sys_exif_tags.c 772 if( colourtemp <= 3200 ) { 773 lightsource = 3; // Tungsten 774 } else if( colourtemp > 3200 && colourtemp <= 4800 ) { 775 lightsource = 2; // Fluorescent 776 } else if( colourtemp > 4800 && colourtemp <= 5500 ) { 777 lightsource = 1; // Daylight 778 } else if( colourtemp > 5500 && colourtemp <= 6500 ) { 779 lightsource = 9; // Fine weather 780 } else if( colourtemp > 6500 ) { 781 lightsource = 10; // Cloudy weather 782 } 783 784 if(flash_fired) { 785 lightsource = 4; // Flash 786 } 787 788 snprintf(temp_value, 789 sizeof(temp_value)/sizeof(char), 790 "%u", lightsource); 791 exifTable->insertElement(TAG_LIGHT_SOURCE, temp_value); 792 } 793 } 794 795 LOG_FUNCTION_NAME_EXIT; 796 797 return ret; 798 } 799 800 status_t OMXCameraAdapter::convertGPSCoord(double coord, 801 int °, 802 int &min, 803 int &sec, 804 int &secDivisor) 805 { 806 double tmp; 807 808 LOG_FUNCTION_NAME; 809 810 if ( coord == 0 ) { 811 812 ALOGE("Invalid GPS coordinate"); 813 814 return -EINVAL; 815 } 816 817 deg = (int) floor(fabs(coord)); 818 tmp = ( fabs(coord) - floor(fabs(coord)) ) * GPS_MIN_DIV; 819 min = (int) floor(tmp); 820 tmp = ( tmp - floor(tmp) ) * ( GPS_SEC_DIV * GPS_SEC_ACCURACY ); 821 sec = (int) floor(tmp); 822 secDivisor = GPS_SEC_ACCURACY; 823 824 if( sec >= ( GPS_SEC_DIV * GPS_SEC_ACCURACY ) ) { 825 sec = 0; 826 min += 1; 827 } 828 829 if( min >= 60 ) { 830 min = 0; 831 deg += 1; 832 } 833 834 LOG_FUNCTION_NAME_EXIT; 835 836 return NO_ERROR; 837 } 838 839 }; 840