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 #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 &params,
     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 &deg,
    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