Home | History | Annotate | Download | only in OMXCameraAdapter
      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 &params,
     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 &deg,
    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