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 ¶ms,
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 °,
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