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 
setParametersEXIF(const CameraParameters & params,BaseCameraAdapter::AdapterState state)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 
setupEXIF()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 
setupEXIF_libjpeg(ExifElementsTable * exifTable,OMX_TI_ANCILLARYDATATYPE * pAncillaryData,OMX_TI_WHITEBALANCERESULTTYPE * pWhiteBalanceData)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 
convertGPSCoord(double coord,int & deg,int & min,int & sec,int & secDivisor)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