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