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
32namespace android {
33
34status_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
232status_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
511status_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
800status_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