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 mEXIFData.mModelValid= true; 197 } 198 else 199 { 200 mEXIFData.mModelValid= false; 201 } 202 203 if( ( valstr = params.get(TICameraParameters::KEY_EXIF_MAKE ) ) != NULL ) 204 { 205 CAMHAL_LOGVB("EXIF Make: %s", valstr); 206 mEXIFData.mMakeValid = true; 207 } 208 else 209 { 210 mEXIFData.mMakeValid= false; 211 } 212 213 LOG_FUNCTION_NAME_EXIT; 214 215 return ret; 216 } 217 218 status_t OMXCameraAdapter::setupEXIF() 219 { 220 status_t ret = NO_ERROR; 221 OMX_ERRORTYPE eError = OMX_ErrorNone; 222 OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer; 223 OMX_TI_CONFIG_EXIF_TAGS *exifTags; 224 unsigned char *sharedPtr = NULL; 225 struct timeval sTv; 226 struct tm *pTime; 227 OMXCameraPortParameters * capData = NULL; 228 MemoryManager memMgr; 229 OMX_U8** memmgr_buf_array = NULL; 230 int buf_size = 0; 231 232 LOG_FUNCTION_NAME; 233 234 sharedBuffer.pSharedBuff = NULL; 235 capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 236 237 if ( OMX_StateInvalid == mComponentState ) 238 { 239 CAMHAL_LOGEA("OMX component is in invalid state"); 240 ret = -EINVAL; 241 } 242 243 if ( NO_ERROR == ret ) 244 { 245 OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER); 246 sharedBuffer.nPortIndex = mCameraAdapterParameters.mImagePortIndex; 247 248 //We allocate the shared buffer dynamically based on the 249 //requirements of the EXIF tags. The additional buffers will 250 //get stored after the EXIF configuration structure and the pointers 251 //will contain offsets within the shared buffer itself. 252 buf_size = sizeof(OMX_TI_CONFIG_EXIF_TAGS) + 253 ( EXIF_MODEL_SIZE ) + 254 ( EXIF_MAKE_SIZE ) + 255 ( EXIF_DATE_TIME_SIZE ) + 256 ( GPS_MAPDATUM_SIZE ) + 257 ( GPS_PROCESSING_SIZE ); 258 buf_size = ((buf_size+4095)/4096)*4096; 259 sharedBuffer.nSharedBuffSize = buf_size; 260 261 memmgr_buf_array = (OMX_U8 **)memMgr.allocateBuffer(0, 0, NULL, buf_size, 1); 262 sharedBuffer.pSharedBuff = ( OMX_U8 * ) memmgr_buf_array[0]; 263 264 if ( NULL == sharedBuffer.pSharedBuff ) 265 { 266 CAMHAL_LOGEA("No resources to allocate OMX shared buffer"); 267 ret = -1; 268 } 269 270 //Extra data begins right after the EXIF configuration structure. 271 sharedPtr = sharedBuffer.pSharedBuff + sizeof(OMX_TI_CONFIG_EXIF_TAGS); 272 } 273 274 if ( NO_ERROR == ret ) 275 { 276 exifTags = ( OMX_TI_CONFIG_EXIF_TAGS * ) sharedBuffer.pSharedBuff; 277 OMX_INIT_STRUCT_PTR (exifTags, OMX_TI_CONFIG_EXIF_TAGS); 278 exifTags->nPortIndex = mCameraAdapterParameters.mImagePortIndex; 279 280 eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp, 281 ( OMX_INDEXTYPE ) OMX_TI_IndexConfigExifTags, 282 &sharedBuffer ); 283 if ( OMX_ErrorNone != eError ) 284 { 285 CAMHAL_LOGEB("Error while retrieving EXIF configuration structure 0x%x", eError); 286 ret = -1; 287 } 288 } 289 290 if ( NO_ERROR == ret ) 291 { 292 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusModel ) && 293 ( mEXIFData.mModelValid ) ) 294 { 295 strncpy(( char * ) sharedPtr, 296 ( char * ) mParams.get(TICameraParameters::KEY_EXIF_MODEL ), 297 EXIF_MODEL_SIZE - 1); 298 299 exifTags->pModelBuff = ( OMX_S8 * ) ( sharedPtr - sharedBuffer.pSharedBuff ); 300 exifTags->ulModelBuffSizeBytes = strlen((char*)sharedPtr) + 1; 301 sharedPtr += EXIF_MODEL_SIZE; 302 exifTags->eStatusModel = OMX_TI_TagUpdated; 303 } 304 305 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusMake) && 306 ( mEXIFData.mMakeValid ) ) 307 { 308 strncpy( ( char * ) sharedPtr, 309 ( char * ) mParams.get(TICameraParameters::KEY_EXIF_MAKE ), 310 EXIF_MAKE_SIZE - 1); 311 312 exifTags->pMakeBuff = ( OMX_S8 * ) ( sharedPtr - sharedBuffer.pSharedBuff ); 313 exifTags->ulMakeBuffSizeBytes = strlen((char*)sharedPtr) + 1; 314 sharedPtr += EXIF_MAKE_SIZE; 315 exifTags->eStatusMake = OMX_TI_TagUpdated; 316 } 317 318 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusFocalLength )) 319 { 320 unsigned int numerator = 0, denominator = 0; 321 ExifElementsTable::stringToRational(mParams.get(CameraParameters::KEY_FOCAL_LENGTH), 322 &numerator, &denominator); 323 if (numerator || denominator) { 324 exifTags->ulFocalLength[0] = (OMX_U32) numerator; 325 exifTags->ulFocalLength[1] = (OMX_U32) denominator; 326 CAMHAL_LOGVB("exifTags->ulFocalLength = [%u] [%u]", 327 (unsigned int)(exifTags->ulFocalLength[0]), 328 (unsigned int)(exifTags->ulFocalLength[1])); 329 exifTags->eStatusFocalLength = OMX_TI_TagUpdated; 330 } 331 } 332 333 if ( OMX_TI_TagReadWrite == exifTags->eStatusDateTime ) 334 { 335 int status = gettimeofday (&sTv, NULL); 336 pTime = localtime (&sTv.tv_sec); 337 if ( ( 0 == status ) && ( NULL != pTime ) ) 338 { 339 snprintf(( char * ) sharedPtr, EXIF_DATE_TIME_SIZE, 340 "%04d:%02d:%02d %02d:%02d:%02d", 341 pTime->tm_year + 1900, 342 pTime->tm_mon + 1, 343 pTime->tm_mday, 344 pTime->tm_hour, 345 pTime->tm_min, 346 pTime->tm_sec ); 347 } 348 349 exifTags->pDateTimeBuff = ( OMX_S8 * ) ( sharedPtr - sharedBuffer.pSharedBuff ); 350 sharedPtr += EXIF_DATE_TIME_SIZE; 351 exifTags->ulDateTimeBuffSizeBytes = EXIF_DATE_TIME_SIZE; 352 exifTags->eStatusDateTime = OMX_TI_TagUpdated; 353 } 354 355 if ( OMX_TI_TagReadWrite == exifTags->eStatusImageWidth ) 356 { 357 exifTags->ulImageWidth = capData->mWidth; 358 exifTags->eStatusImageWidth = OMX_TI_TagUpdated; 359 } 360 361 if ( OMX_TI_TagReadWrite == exifTags->eStatusImageHeight ) 362 { 363 exifTags->ulImageHeight = capData->mHeight; 364 exifTags->eStatusImageHeight = OMX_TI_TagUpdated; 365 } 366 367 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsLatitude ) && 368 ( mEXIFData.mGPSData.mLatValid ) ) 369 { 370 exifTags->ulGpsLatitude[0] = abs(mEXIFData.mGPSData.mLatDeg); 371 exifTags->ulGpsLatitude[2] = abs(mEXIFData.mGPSData.mLatMin); 372 exifTags->ulGpsLatitude[4] = abs(mEXIFData.mGPSData.mLatSec); 373 exifTags->ulGpsLatitude[1] = 1; 374 exifTags->ulGpsLatitude[3] = 1; 375 exifTags->ulGpsLatitude[5] = abs(mEXIFData.mGPSData.mLatSecDiv); 376 exifTags->eStatusGpsLatitude = OMX_TI_TagUpdated; 377 } 378 379 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpslatitudeRef ) && 380 ( mEXIFData.mGPSData.mLatValid ) ) 381 { 382 exifTags->cGpslatitudeRef[0] = ( OMX_S8 ) mEXIFData.mGPSData.mLatRef[0]; 383 exifTags->cGpslatitudeRef[1] = '\0'; 384 exifTags->eStatusGpslatitudeRef = OMX_TI_TagUpdated; 385 } 386 387 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsLongitude ) && 388 ( mEXIFData.mGPSData.mLongValid ) ) 389 { 390 exifTags->ulGpsLongitude[0] = abs(mEXIFData.mGPSData.mLongDeg); 391 exifTags->ulGpsLongitude[2] = abs(mEXIFData.mGPSData.mLongMin); 392 exifTags->ulGpsLongitude[4] = abs(mEXIFData.mGPSData.mLongSec); 393 exifTags->ulGpsLongitude[1] = 1; 394 exifTags->ulGpsLongitude[3] = 1; 395 exifTags->ulGpsLongitude[5] = abs(mEXIFData.mGPSData.mLongSecDiv); 396 exifTags->eStatusGpsLongitude = OMX_TI_TagUpdated; 397 } 398 399 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsLongitudeRef ) && 400 ( mEXIFData.mGPSData.mLongValid ) ) 401 { 402 exifTags->cGpsLongitudeRef[0] = ( OMX_S8 ) mEXIFData.mGPSData.mLongRef[0]; 403 exifTags->cGpsLongitudeRef[1] = '\0'; 404 exifTags->eStatusGpsLongitudeRef = OMX_TI_TagUpdated; 405 } 406 407 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsAltitude ) && 408 ( mEXIFData.mGPSData.mAltitudeValid) ) 409 { 410 exifTags->ulGpsAltitude[0] = ( OMX_U32 ) mEXIFData.mGPSData.mAltitude; 411 exifTags->ulGpsAltitude[1] = 1; 412 exifTags->eStatusGpsAltitude = OMX_TI_TagUpdated; 413 } 414 415 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsAltitudeRef ) && 416 ( mEXIFData.mGPSData.mAltitudeValid) ) 417 { 418 exifTags->ucGpsAltitudeRef = (OMX_U8) mEXIFData.mGPSData.mAltitudeRef; 419 exifTags->eStatusGpsAltitudeRef = OMX_TI_TagUpdated; 420 } 421 422 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsMapDatum ) && 423 ( mEXIFData.mGPSData.mMapDatumValid ) ) 424 { 425 memcpy(sharedPtr, mEXIFData.mGPSData.mMapDatum, GPS_MAPDATUM_SIZE); 426 427 exifTags->pGpsMapDatumBuff = ( OMX_S8 * ) ( sharedPtr - sharedBuffer.pSharedBuff ); 428 exifTags->ulGpsMapDatumBuffSizeBytes = GPS_MAPDATUM_SIZE; 429 exifTags->eStatusGpsMapDatum = OMX_TI_TagUpdated; 430 sharedPtr += GPS_MAPDATUM_SIZE; 431 } 432 433 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsProcessingMethod ) && 434 ( mEXIFData.mGPSData.mProcMethodValid ) ) 435 { 436 exifTags->pGpsProcessingMethodBuff = ( OMX_S8 * ) ( sharedPtr - sharedBuffer.pSharedBuff ); 437 memcpy(sharedPtr, ExifAsciiPrefix, sizeof(ExifAsciiPrefix)); 438 sharedPtr += sizeof(ExifAsciiPrefix); 439 440 memcpy(sharedPtr, 441 mEXIFData.mGPSData.mProcMethod, 442 ( GPS_PROCESSING_SIZE - sizeof(ExifAsciiPrefix) ) ); 443 exifTags->ulGpsProcessingMethodBuffSizeBytes = GPS_PROCESSING_SIZE; 444 exifTags->eStatusGpsProcessingMethod = OMX_TI_TagUpdated; 445 sharedPtr += GPS_PROCESSING_SIZE; 446 } 447 448 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsVersionId ) && 449 ( mEXIFData.mGPSData.mVersionIdValid ) ) 450 { 451 exifTags->ucGpsVersionId[0] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[0]; 452 exifTags->ucGpsVersionId[1] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[1]; 453 exifTags->ucGpsVersionId[2] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[2]; 454 exifTags->ucGpsVersionId[3] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[3]; 455 exifTags->eStatusGpsVersionId = OMX_TI_TagUpdated; 456 } 457 458 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsTimeStamp ) && 459 ( mEXIFData.mGPSData.mTimeStampValid ) ) 460 { 461 exifTags->ulGpsTimeStamp[0] = mEXIFData.mGPSData.mTimeStampHour; 462 exifTags->ulGpsTimeStamp[2] = mEXIFData.mGPSData.mTimeStampMin; 463 exifTags->ulGpsTimeStamp[4] = mEXIFData.mGPSData.mTimeStampSec; 464 exifTags->ulGpsTimeStamp[1] = 1; 465 exifTags->ulGpsTimeStamp[3] = 1; 466 exifTags->ulGpsTimeStamp[5] = 1; 467 exifTags->eStatusGpsTimeStamp = OMX_TI_TagUpdated; 468 } 469 470 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsDateStamp ) && 471 ( mEXIFData.mGPSData.mDatestampValid ) ) 472 { 473 strncpy( ( char * ) exifTags->cGpsDateStamp, 474 ( char * ) mEXIFData.mGPSData.mDatestamp, 475 GPS_DATESTAMP_SIZE ); 476 exifTags->eStatusGpsDateStamp = OMX_TI_TagUpdated; 477 } 478 479 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 480 ( OMX_INDEXTYPE ) OMX_TI_IndexConfigExifTags, 481 &sharedBuffer ); 482 483 if ( OMX_ErrorNone != eError ) 484 { 485 CAMHAL_LOGEB("Error while setting EXIF configuration 0x%x", eError); 486 ret = -1; 487 } 488 } 489 490 if ( NULL != memmgr_buf_array ) 491 { 492 memMgr.freeBuffer(memmgr_buf_array); 493 } 494 495 LOG_FUNCTION_NAME_EXIT; 496 497 return ret; 498 } 499 500 status_t OMXCameraAdapter::setupEXIF_libjpeg(ExifElementsTable* exifTable) 501 { 502 status_t ret = NO_ERROR; 503 OMX_ERRORTYPE eError = OMX_ErrorNone; 504 struct timeval sTv; 505 struct tm *pTime; 506 OMXCameraPortParameters * capData = NULL; 507 508 LOG_FUNCTION_NAME; 509 510 capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 511 512 if ((NO_ERROR == ret) && (mEXIFData.mModelValid)) { 513 ret = exifTable->insertElement(TAG_MODEL, mParams.get(TICameraParameters::KEY_EXIF_MODEL)); 514 } 515 516 if ((NO_ERROR == ret) && (mEXIFData.mMakeValid)) { 517 ret = exifTable->insertElement(TAG_MAKE, mParams.get(TICameraParameters::KEY_EXIF_MAKE)); 518 } 519 520 if ((NO_ERROR == ret)) { 521 unsigned int numerator = 0, denominator = 0; 522 ExifElementsTable::stringToRational(mParams.get(CameraParameters::KEY_FOCAL_LENGTH), 523 &numerator, &denominator); 524 if (numerator || denominator) { 525 char temp_value[256]; // arbitrarily long string 526 snprintf(temp_value, 527 sizeof(temp_value)/sizeof(char), 528 "%u/%u", numerator, denominator); 529 ret = exifTable->insertElement(TAG_FOCALLENGTH, temp_value); 530 531 } 532 } 533 534 if ((NO_ERROR == ret)) { 535 int status = gettimeofday (&sTv, NULL); 536 pTime = localtime (&sTv.tv_sec); 537 char temp_value[EXIF_DATE_TIME_SIZE + 1]; 538 if ((0 == status) && (NULL != pTime)) { 539 snprintf(temp_value, EXIF_DATE_TIME_SIZE, 540 "%04d:%02d:%02d %02d:%02d:%02d", 541 pTime->tm_year + 1900, 542 pTime->tm_mon + 1, 543 pTime->tm_mday, 544 pTime->tm_hour, 545 pTime->tm_min, 546 pTime->tm_sec ); 547 548 ret = exifTable->insertElement(TAG_DATETIME, temp_value); 549 } 550 } 551 552 if ((NO_ERROR == ret)) { 553 char temp_value[5]; 554 snprintf(temp_value, sizeof(temp_value)/sizeof(char), "%lu", capData->mWidth); 555 ret = exifTable->insertElement(TAG_IMAGE_WIDTH, temp_value); 556 } 557 558 if ((NO_ERROR == ret)) { 559 char temp_value[5]; 560 snprintf(temp_value, sizeof(temp_value)/sizeof(char), "%lu", capData->mHeight); 561 ret = exifTable->insertElement(TAG_IMAGE_LENGTH, temp_value); 562 } 563 564 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLatValid)) { 565 char temp_value[256]; // arbitrarily long string 566 snprintf(temp_value, 567 sizeof(temp_value)/sizeof(char) - 1, 568 "%d/%d,%d/%d,%d/%d", 569 abs(mEXIFData.mGPSData.mLatDeg), 1, 570 abs(mEXIFData.mGPSData.mLatMin), 1, 571 abs(mEXIFData.mGPSData.mLatSec), abs(mEXIFData.mGPSData.mLatSecDiv)); 572 ret = exifTable->insertElement(TAG_GPS_LAT, temp_value); 573 } 574 575 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLatValid)) { 576 ret = exifTable->insertElement(TAG_GPS_LAT_REF, mEXIFData.mGPSData.mLatRef); 577 } 578 579 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLongValid)) { 580 char temp_value[256]; // arbitrarily long string 581 snprintf(temp_value, 582 sizeof(temp_value)/sizeof(char) - 1, 583 "%d/%d,%d/%d,%d/%d", 584 abs(mEXIFData.mGPSData.mLongDeg), 1, 585 abs(mEXIFData.mGPSData.mLongMin), 1, 586 abs(mEXIFData.mGPSData.mLongSec), abs(mEXIFData.mGPSData.mLongSecDiv)); 587 ret = exifTable->insertElement(TAG_GPS_LONG, temp_value); 588 } 589 590 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLongValid)) { 591 ret = exifTable->insertElement(TAG_GPS_LONG_REF, mEXIFData.mGPSData.mLongRef); 592 } 593 594 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mAltitudeValid)) { 595 char temp_value[256]; // arbitrarily long string 596 snprintf(temp_value, 597 sizeof(temp_value)/sizeof(char) - 1, 598 "%d/%d", 599 abs( mEXIFData.mGPSData.mAltitude), 1); 600 ret = exifTable->insertElement(TAG_GPS_ALT, temp_value); 601 } 602 603 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mAltitudeValid)) { 604 char temp_value[5]; 605 snprintf(temp_value, 606 sizeof(temp_value)/sizeof(char) - 1, 607 "%d", mEXIFData.mGPSData.mAltitudeRef); 608 ret = exifTable->insertElement(TAG_GPS_ALT_REF, temp_value); 609 } 610 611 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mMapDatumValid)) { 612 ret = exifTable->insertElement(TAG_GPS_MAP_DATUM, mEXIFData.mGPSData.mMapDatum); 613 } 614 615 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mProcMethodValid)) { 616 char temp_value[GPS_PROCESSING_SIZE]; 617 618 memcpy(temp_value, ExifAsciiPrefix, sizeof(ExifAsciiPrefix)); 619 memcpy(temp_value + sizeof(ExifAsciiPrefix), 620 mParams.get(CameraParameters::KEY_GPS_PROCESSING_METHOD), 621 (GPS_PROCESSING_SIZE - sizeof(ExifAsciiPrefix))); 622 ret = exifTable->insertElement(TAG_GPS_PROCESSING_METHOD, temp_value); 623 } 624 625 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mVersionIdValid)) { 626 char temp_value[256]; // arbitrarily long string 627 snprintf(temp_value, 628 sizeof(temp_value)/sizeof(char) - 1, 629 "%d,%d,%d,%d", 630 mEXIFData.mGPSData.mVersionId[0], 631 mEXIFData.mGPSData.mVersionId[1], 632 mEXIFData.mGPSData.mVersionId[2], 633 mEXIFData.mGPSData.mVersionId[3]); 634 ret = exifTable->insertElement(TAG_GPS_VERSION_ID, temp_value); 635 } 636 637 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mTimeStampValid)) { 638 char temp_value[256]; // arbitrarily long string 639 snprintf(temp_value, 640 sizeof(temp_value)/sizeof(char) - 1, 641 "%d/%d,%d/%d,%d/%d", 642 mEXIFData.mGPSData.mTimeStampHour, 1, 643 mEXIFData.mGPSData.mTimeStampMin, 1, 644 mEXIFData.mGPSData.mTimeStampSec, 1); 645 ret = exifTable->insertElement(TAG_GPS_TIMESTAMP, temp_value); 646 } 647 648 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mDatestampValid) ) { 649 ret = exifTable->insertElement(TAG_GPS_DATESTAMP, mEXIFData.mGPSData.mDatestamp); 650 } 651 652 if ((NO_ERROR == ret) && mParams.get(CameraParameters::KEY_ROTATION) ) { 653 const char* exif_orient = 654 ExifElementsTable::degreesToExifOrientation(mParams.get(CameraParameters::KEY_ROTATION)); 655 656 if (exif_orient) { 657 ret = exifTable->insertElement(TAG_ORIENTATION, exif_orient); 658 } 659 } 660 661 LOG_FUNCTION_NAME_EXIT; 662 663 return ret; 664 } 665 666 status_t OMXCameraAdapter::convertGPSCoord(double coord, 667 int °, 668 int &min, 669 int &sec, 670 int &secDivisor) 671 { 672 double tmp; 673 674 LOG_FUNCTION_NAME; 675 676 if ( coord == 0 ) { 677 678 LOGE("Invalid GPS coordinate"); 679 680 return -EINVAL; 681 } 682 683 deg = (int) floor(fabs(coord)); 684 tmp = ( fabs(coord) - floor(fabs(coord)) ) * GPS_MIN_DIV; 685 min = (int) floor(tmp); 686 tmp = ( tmp - floor(tmp) ) * ( GPS_SEC_DIV * GPS_SEC_ACCURACY ); 687 sec = (int) floor(tmp); 688 secDivisor = GPS_SEC_ACCURACY; 689 690 if( sec >= ( GPS_SEC_DIV * GPS_SEC_ACCURACY ) ) { 691 sec = 0; 692 min += 1; 693 } 694 695 if( min >= 60 ) { 696 min = 0; 697 deg += 1; 698 } 699 700 LOG_FUNCTION_NAME_EXIT; 701 702 return NO_ERROR; 703 } 704 705 }; 706