1 /*
2 * Copyright (C) Texas Instruments - http://www.ti.com/
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /**
18 * @file OMXExif.cpp
19 *
20 * This file contains functionality for handling EXIF insertion.
21 *
22 */
23
24 #include "CameraHal.h"
25 #include "OMXCameraAdapter.h"
26 #include <math.h>
27
28 namespace Ti {
29 namespace Camera {
30
setParametersEXIF(const android::CameraParameters & params,BaseCameraAdapter::AdapterState state)31 status_t OMXCameraAdapter::setParametersEXIF(const android::CameraParameters ¶ms,
32 BaseCameraAdapter::AdapterState state)
33 {
34 status_t ret = NO_ERROR;
35 const char *valstr = NULL;
36 double gpsPos;
37
38 LOG_FUNCTION_NAME;
39
40 if( ( valstr = params.get(android::CameraParameters::KEY_GPS_LATITUDE) ) != NULL )
41 {
42 gpsPos = strtod(valstr, NULL);
43
44 if ( convertGPSCoord(gpsPos,
45 mEXIFData.mGPSData.mLatDeg,
46 mEXIFData.mGPSData.mLatMin,
47 mEXIFData.mGPSData.mLatSec,
48 mEXIFData.mGPSData.mLatSecDiv ) == NO_ERROR )
49 {
50
51 if ( 0 < gpsPos )
52 {
53 strncpy(mEXIFData.mGPSData.mLatRef, GPS_NORTH_REF, GPS_REF_SIZE);
54 }
55 else
56 {
57 strncpy(mEXIFData.mGPSData.mLatRef, GPS_SOUTH_REF, GPS_REF_SIZE);
58 }
59
60 mEXIFData.mGPSData.mLatValid = true;
61 }
62 else
63 {
64 mEXIFData.mGPSData.mLatValid = false;
65 }
66 }
67 else
68 {
69 mEXIFData.mGPSData.mLatValid = false;
70 }
71
72 if( ( valstr = params.get(android::CameraParameters::KEY_GPS_LONGITUDE) ) != NULL )
73 {
74 gpsPos = strtod(valstr, NULL);
75
76 if ( convertGPSCoord(gpsPos,
77 mEXIFData.mGPSData.mLongDeg,
78 mEXIFData.mGPSData.mLongMin,
79 mEXIFData.mGPSData.mLongSec,
80 mEXIFData.mGPSData.mLongSecDiv) == NO_ERROR )
81 {
82
83 if ( 0 < gpsPos )
84 {
85 strncpy(mEXIFData.mGPSData.mLongRef, GPS_EAST_REF, GPS_REF_SIZE);
86 }
87 else
88 {
89 strncpy(mEXIFData.mGPSData.mLongRef, GPS_WEST_REF, GPS_REF_SIZE);
90 }
91
92 mEXIFData.mGPSData.mLongValid= true;
93 }
94 else
95 {
96 mEXIFData.mGPSData.mLongValid = false;
97 }
98 }
99 else
100 {
101 mEXIFData.mGPSData.mLongValid = false;
102 }
103
104 if( ( valstr = params.get(android::CameraParameters::KEY_GPS_ALTITUDE) ) != NULL )
105 {
106 gpsPos = strtod(valstr, NULL);
107 mEXIFData.mGPSData.mAltitude = floor(fabs(gpsPos));
108 if (gpsPos < 0) {
109 mEXIFData.mGPSData.mAltitudeRef = 1;
110 } else {
111 mEXIFData.mGPSData.mAltitudeRef = 0;
112 }
113 mEXIFData.mGPSData.mAltitudeValid = true;
114 }
115 else
116 {
117 mEXIFData.mGPSData.mAltitudeValid= false;
118 }
119
120 if( (valstr = params.get(android::CameraParameters::KEY_GPS_TIMESTAMP)) != NULL )
121 {
122 long gpsTimestamp = strtol(valstr, NULL, 10);
123 struct tm *timeinfo = gmtime( ( time_t * ) & (gpsTimestamp) );
124 if ( NULL != timeinfo )
125 {
126 mEXIFData.mGPSData.mTimeStampHour = timeinfo->tm_hour;
127 mEXIFData.mGPSData.mTimeStampMin = timeinfo->tm_min;
128 mEXIFData.mGPSData.mTimeStampSec = timeinfo->tm_sec;
129 mEXIFData.mGPSData.mTimeStampValid = true;
130 }
131 else
132 {
133 mEXIFData.mGPSData.mTimeStampValid = false;
134 }
135 }
136 else
137 {
138 mEXIFData.mGPSData.mTimeStampValid = false;
139 }
140
141 if( ( valstr = params.get(android::CameraParameters::KEY_GPS_TIMESTAMP) ) != NULL )
142 {
143 long gpsDatestamp = strtol(valstr, NULL, 10);
144 struct tm *timeinfo = gmtime( ( time_t * ) & (gpsDatestamp) );
145 if ( NULL != timeinfo )
146 {
147 strftime(mEXIFData.mGPSData.mDatestamp, GPS_DATESTAMP_SIZE, "%Y:%m:%d", timeinfo);
148 mEXIFData.mGPSData.mDatestampValid = true;
149 }
150 else
151 {
152 mEXIFData.mGPSData.mDatestampValid = false;
153 }
154 }
155 else
156 {
157 mEXIFData.mGPSData.mDatestampValid = false;
158 }
159
160 if( ( valstr = params.get(android::CameraParameters::KEY_GPS_PROCESSING_METHOD) ) != NULL )
161 {
162 strncpy(mEXIFData.mGPSData.mProcMethod, valstr, GPS_PROCESSING_SIZE-1);
163 mEXIFData.mGPSData.mProcMethodValid = true;
164 }
165 else
166 {
167 mEXIFData.mGPSData.mProcMethodValid = false;
168 }
169
170 if( ( valstr = params.get(TICameraParameters::KEY_GPS_MAPDATUM) ) != NULL )
171 {
172 strncpy(mEXIFData.mGPSData.mMapDatum, valstr, GPS_MAPDATUM_SIZE-1);
173 mEXIFData.mGPSData.mMapDatumValid = true;
174 }
175 else
176 {
177 mEXIFData.mGPSData.mMapDatumValid = false;
178 }
179
180 if( ( valstr = params.get(TICameraParameters::KEY_GPS_VERSION) ) != NULL )
181 {
182 strncpy(mEXIFData.mGPSData.mVersionId, valstr, GPS_VERSION_SIZE-1);
183 mEXIFData.mGPSData.mVersionIdValid = true;
184 }
185 else
186 {
187 mEXIFData.mGPSData.mVersionIdValid = false;
188 }
189
190 if( ( valstr = params.get(TICameraParameters::KEY_EXIF_MODEL ) ) != NULL )
191 {
192 CAMHAL_LOGVB("EXIF Model: %s", valstr);
193 strncpy(mEXIFData.mModel, valstr, EXIF_MODEL_SIZE - 1);
194 mEXIFData.mModelValid= true;
195 }
196 else
197 {
198 mEXIFData.mModelValid= false;
199 }
200
201 if( ( valstr = params.get(TICameraParameters::KEY_EXIF_MAKE ) ) != NULL )
202 {
203 CAMHAL_LOGVB("EXIF Make: %s", valstr);
204 strncpy(mEXIFData.mMake, valstr, EXIF_MAKE_SIZE - 1);
205 mEXIFData.mMakeValid = true;
206 }
207 else
208 {
209 mEXIFData.mMakeValid= false;
210 }
211
212
213 if( ( valstr = params.get(android::CameraParameters::KEY_FOCAL_LENGTH) ) != NULL ) {
214 CAMHAL_LOGVB("EXIF Focal length: %s", valstr);
215 ExifElementsTable::stringToRational(valstr,
216 &mEXIFData.mFocalNum,
217 &mEXIFData.mFocalDen);
218 } else {
219 mEXIFData.mFocalNum = 0;
220 mEXIFData.mFocalDen = 0;
221 }
222
223
224 LOG_FUNCTION_NAME_EXIT;
225
226 return ret;
227 }
228
setupEXIF()229 status_t OMXCameraAdapter::setupEXIF()
230 {
231 status_t ret = NO_ERROR;
232 OMX_ERRORTYPE eError = OMX_ErrorNone;
233 OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer;
234 OMX_TI_CONFIG_EXIF_TAGS *exifTags;
235 unsigned char *startPtr = NULL;
236 unsigned char *sharedPtr = NULL;
237 struct timeval sTv;
238 struct tm *pTime;
239 OMXCameraPortParameters * capData = NULL;
240 CameraBuffer *memmgr_buf_array;
241 int buf_size = 0;
242
243 LOG_FUNCTION_NAME;
244
245 sharedBuffer.pSharedBuff = NULL;
246 capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
247
248 if ( OMX_StateInvalid == mComponentState )
249 {
250 CAMHAL_LOGEA("OMX component is in invalid state");
251 ret = -EINVAL;
252 }
253
254 if ( NO_ERROR == ret )
255 {
256 OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER);
257 sharedBuffer.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
258
259 //We allocate the shared buffer dynamically based on the
260 //requirements of the EXIF tags. The additional buffers will
261 //get stored after the EXIF configuration structure and the pointers
262 //will contain offsets within the shared buffer itself.
263 buf_size = sizeof(OMX_TI_CONFIG_EXIF_TAGS) +
264 ( EXIF_MODEL_SIZE ) +
265 ( EXIF_MAKE_SIZE ) +
266 ( EXIF_DATE_TIME_SIZE ) +
267 ( GPS_MAPDATUM_SIZE ) +
268 ( GPS_PROCESSING_SIZE );
269 buf_size = ((buf_size+4095)/4096)*4096;
270 sharedBuffer.nSharedBuffSize = buf_size;
271
272 memmgr_buf_array = mMemMgr.allocateBufferList(0, 0, NULL, buf_size, 1);
273 sharedBuffer.pSharedBuff = (OMX_U8*)camera_buffer_get_omx_ptr(&memmgr_buf_array[0]);
274 startPtr = ( OMX_U8 * ) memmgr_buf_array[0].opaque;
275
276 if ( NULL == startPtr)
277 {
278 CAMHAL_LOGEA("No resources to allocate OMX shared buffer");
279 ret = -1;
280 }
281
282 //Extra data begins right after the EXIF configuration structure.
283 sharedPtr = startPtr + sizeof(OMX_TI_CONFIG_EXIF_TAGS);
284 }
285
286 if ( NO_ERROR == ret )
287 {
288 exifTags = ( OMX_TI_CONFIG_EXIF_TAGS * ) startPtr;
289 OMX_INIT_STRUCT_PTR (exifTags, OMX_TI_CONFIG_EXIF_TAGS);
290 exifTags->nPortIndex = mCameraAdapterParameters.mImagePortIndex;
291
292 eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
293 ( OMX_INDEXTYPE ) OMX_TI_IndexConfigExifTags,
294 &sharedBuffer );
295 if ( OMX_ErrorNone != eError )
296 {
297 CAMHAL_LOGEB("Error while retrieving EXIF configuration structure 0x%x", eError);
298 ret = -1;
299 }
300 }
301
302 if ( NO_ERROR == ret )
303 {
304 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusModel ) &&
305 ( mEXIFData.mModelValid ) )
306 {
307 strncpy(( char * ) sharedPtr,
308 mEXIFData.mModel,
309 EXIF_MODEL_SIZE - 1);
310
311 exifTags->pModelBuff = ( OMX_S8 * ) ( sharedPtr - startPtr );
312 exifTags->ulModelBuffSizeBytes = strlen((char*)sharedPtr) + 1;
313 sharedPtr += EXIF_MODEL_SIZE;
314 exifTags->eStatusModel = OMX_TI_TagUpdated;
315 }
316
317 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusMake) &&
318 ( mEXIFData.mMakeValid ) )
319 {
320 strncpy( ( char * ) sharedPtr,
321 mEXIFData.mMake,
322 EXIF_MAKE_SIZE - 1);
323
324 exifTags->pMakeBuff = ( OMX_S8 * ) ( sharedPtr - startPtr );
325 exifTags->ulMakeBuffSizeBytes = strlen((char*)sharedPtr) + 1;
326 sharedPtr += EXIF_MAKE_SIZE;
327 exifTags->eStatusMake = OMX_TI_TagUpdated;
328 }
329
330 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusFocalLength ))
331 {
332 if (mEXIFData.mFocalNum || mEXIFData.mFocalDen ) {
333 exifTags->ulFocalLength[0] = (OMX_U32) mEXIFData.mFocalNum;
334 exifTags->ulFocalLength[1] = (OMX_U32) mEXIFData.mFocalDen;
335 CAMHAL_LOGVB("exifTags->ulFocalLength = [%u] [%u]",
336 (unsigned int)(exifTags->ulFocalLength[0]),
337 (unsigned int)(exifTags->ulFocalLength[1]));
338 exifTags->eStatusFocalLength = OMX_TI_TagUpdated;
339 }
340 }
341
342 if ( OMX_TI_TagReadWrite == exifTags->eStatusDateTime )
343 {
344 int status = gettimeofday (&sTv, NULL);
345 pTime = localtime (&sTv.tv_sec);
346 if ( ( 0 == status ) && ( NULL != pTime ) )
347 {
348 snprintf(( char * ) sharedPtr, EXIF_DATE_TIME_SIZE,
349 "%04d:%02d:%02d %02d:%02d:%02d",
350 pTime->tm_year + 1900,
351 pTime->tm_mon + 1,
352 pTime->tm_mday,
353 pTime->tm_hour,
354 pTime->tm_min,
355 pTime->tm_sec );
356 }
357
358 exifTags->pDateTimeBuff = ( OMX_S8 * ) ( sharedPtr - startPtr );
359 sharedPtr += EXIF_DATE_TIME_SIZE;
360 exifTags->ulDateTimeBuffSizeBytes = EXIF_DATE_TIME_SIZE;
361 exifTags->eStatusDateTime = OMX_TI_TagUpdated;
362 }
363
364 if ( OMX_TI_TagReadWrite == exifTags->eStatusImageWidth )
365 {
366 exifTags->ulImageWidth = capData->mWidth;
367 exifTags->eStatusImageWidth = OMX_TI_TagUpdated;
368 }
369
370 if ( OMX_TI_TagReadWrite == exifTags->eStatusImageHeight )
371 {
372 exifTags->ulImageHeight = capData->mHeight;
373 exifTags->eStatusImageHeight = OMX_TI_TagUpdated;
374 }
375
376 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsLatitude ) &&
377 ( mEXIFData.mGPSData.mLatValid ) )
378 {
379 exifTags->ulGpsLatitude[0] = abs(mEXIFData.mGPSData.mLatDeg);
380 exifTags->ulGpsLatitude[2] = abs(mEXIFData.mGPSData.mLatMin);
381 exifTags->ulGpsLatitude[4] = abs(mEXIFData.mGPSData.mLatSec);
382 exifTags->ulGpsLatitude[1] = 1;
383 exifTags->ulGpsLatitude[3] = 1;
384 exifTags->ulGpsLatitude[5] = abs(mEXIFData.mGPSData.mLatSecDiv);
385 exifTags->eStatusGpsLatitude = OMX_TI_TagUpdated;
386 }
387
388 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpslatitudeRef ) &&
389 ( mEXIFData.mGPSData.mLatValid ) )
390 {
391 exifTags->cGpslatitudeRef[0] = ( OMX_S8 ) mEXIFData.mGPSData.mLatRef[0];
392 exifTags->cGpslatitudeRef[1] = '\0';
393 exifTags->eStatusGpslatitudeRef = OMX_TI_TagUpdated;
394 }
395
396 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsLongitude ) &&
397 ( mEXIFData.mGPSData.mLongValid ) )
398 {
399 exifTags->ulGpsLongitude[0] = abs(mEXIFData.mGPSData.mLongDeg);
400 exifTags->ulGpsLongitude[2] = abs(mEXIFData.mGPSData.mLongMin);
401 exifTags->ulGpsLongitude[4] = abs(mEXIFData.mGPSData.mLongSec);
402 exifTags->ulGpsLongitude[1] = 1;
403 exifTags->ulGpsLongitude[3] = 1;
404 exifTags->ulGpsLongitude[5] = abs(mEXIFData.mGPSData.mLongSecDiv);
405 exifTags->eStatusGpsLongitude = OMX_TI_TagUpdated;
406 }
407
408 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsLongitudeRef ) &&
409 ( mEXIFData.mGPSData.mLongValid ) )
410 {
411 exifTags->cGpsLongitudeRef[0] = ( OMX_S8 ) mEXIFData.mGPSData.mLongRef[0];
412 exifTags->cGpsLongitudeRef[1] = '\0';
413 exifTags->eStatusGpsLongitudeRef = OMX_TI_TagUpdated;
414 }
415
416 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsAltitude ) &&
417 ( mEXIFData.mGPSData.mAltitudeValid) )
418 {
419 exifTags->ulGpsAltitude[0] = ( OMX_U32 ) mEXIFData.mGPSData.mAltitude;
420 exifTags->ulGpsAltitude[1] = 1;
421 exifTags->eStatusGpsAltitude = OMX_TI_TagUpdated;
422 }
423
424 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsAltitudeRef ) &&
425 ( mEXIFData.mGPSData.mAltitudeValid) )
426 {
427 exifTags->ucGpsAltitudeRef = (OMX_U8) mEXIFData.mGPSData.mAltitudeRef;
428 exifTags->eStatusGpsAltitudeRef = OMX_TI_TagUpdated;
429 }
430
431 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsMapDatum ) &&
432 ( mEXIFData.mGPSData.mMapDatumValid ) )
433 {
434 memcpy(sharedPtr, mEXIFData.mGPSData.mMapDatum, GPS_MAPDATUM_SIZE);
435
436 exifTags->pGpsMapDatumBuff = ( OMX_S8 * ) ( sharedPtr - startPtr );
437 exifTags->ulGpsMapDatumBuffSizeBytes = GPS_MAPDATUM_SIZE;
438 exifTags->eStatusGpsMapDatum = OMX_TI_TagUpdated;
439 sharedPtr += GPS_MAPDATUM_SIZE;
440 }
441
442 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsProcessingMethod ) &&
443 ( mEXIFData.mGPSData.mProcMethodValid ) )
444 {
445 exifTags->pGpsProcessingMethodBuff = ( OMX_S8 * ) ( sharedPtr - startPtr );
446 memcpy(sharedPtr, ExifAsciiPrefix, sizeof(ExifAsciiPrefix));
447 sharedPtr += sizeof(ExifAsciiPrefix);
448
449 memcpy(sharedPtr,
450 mEXIFData.mGPSData.mProcMethod,
451 ( GPS_PROCESSING_SIZE - sizeof(ExifAsciiPrefix) ) );
452 exifTags->ulGpsProcessingMethodBuffSizeBytes = GPS_PROCESSING_SIZE;
453 exifTags->eStatusGpsProcessingMethod = OMX_TI_TagUpdated;
454 sharedPtr += GPS_PROCESSING_SIZE;
455 }
456
457 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsVersionId ) &&
458 ( mEXIFData.mGPSData.mVersionIdValid ) )
459 {
460 exifTags->ucGpsVersionId[0] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[0];
461 exifTags->ucGpsVersionId[1] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[1];
462 exifTags->ucGpsVersionId[2] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[2];
463 exifTags->ucGpsVersionId[3] = ( OMX_U8 ) mEXIFData.mGPSData.mVersionId[3];
464 exifTags->eStatusGpsVersionId = OMX_TI_TagUpdated;
465 }
466
467 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsTimeStamp ) &&
468 ( mEXIFData.mGPSData.mTimeStampValid ) )
469 {
470 exifTags->ulGpsTimeStamp[0] = mEXIFData.mGPSData.mTimeStampHour;
471 exifTags->ulGpsTimeStamp[2] = mEXIFData.mGPSData.mTimeStampMin;
472 exifTags->ulGpsTimeStamp[4] = mEXIFData.mGPSData.mTimeStampSec;
473 exifTags->ulGpsTimeStamp[1] = 1;
474 exifTags->ulGpsTimeStamp[3] = 1;
475 exifTags->ulGpsTimeStamp[5] = 1;
476 exifTags->eStatusGpsTimeStamp = OMX_TI_TagUpdated;
477 }
478
479 if ( ( OMX_TI_TagReadWrite == exifTags->eStatusGpsDateStamp ) &&
480 ( mEXIFData.mGPSData.mDatestampValid ) )
481 {
482 strncpy( ( char * ) exifTags->cGpsDateStamp,
483 ( char * ) mEXIFData.mGPSData.mDatestamp,
484 GPS_DATESTAMP_SIZE );
485 exifTags->eStatusGpsDateStamp = OMX_TI_TagUpdated;
486 }
487
488 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
489 ( OMX_INDEXTYPE ) OMX_TI_IndexConfigExifTags,
490 &sharedBuffer );
491
492 if ( OMX_ErrorNone != eError )
493 {
494 CAMHAL_LOGEB("Error while setting EXIF configuration 0x%x", eError);
495 ret = -1;
496 }
497 }
498
499 if ( NULL != memmgr_buf_array )
500 {
501 mMemMgr.freeBufferList(memmgr_buf_array);
502 }
503
504 LOG_FUNCTION_NAME_EXIT;
505
506 return ret;
507 }
508
setupEXIF_libjpeg(ExifElementsTable * exifTable,OMX_TI_ANCILLARYDATATYPE * pAncillaryData,OMX_TI_WHITEBALANCERESULTTYPE * pWhiteBalanceData)509 status_t OMXCameraAdapter::setupEXIF_libjpeg(ExifElementsTable* exifTable,
510 OMX_TI_ANCILLARYDATATYPE* pAncillaryData,
511 OMX_TI_WHITEBALANCERESULTTYPE* pWhiteBalanceData)
512 {
513 status_t ret = NO_ERROR;
514 OMX_ERRORTYPE eError = OMX_ErrorNone;
515 struct timeval sTv;
516 struct tm *pTime;
517 OMXCameraPortParameters * capData = NULL;
518
519 LOG_FUNCTION_NAME;
520
521 capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
522
523 if ((NO_ERROR == ret) && (mEXIFData.mModelValid)) {
524 ret = exifTable->insertElement(TAG_MODEL, mEXIFData.mModel);
525 }
526
527 if ((NO_ERROR == ret) && (mEXIFData.mMakeValid)) {
528 ret = exifTable->insertElement(TAG_MAKE, mEXIFData.mMake);
529 }
530
531 if ((NO_ERROR == ret)) {
532 if (mEXIFData.mFocalNum || mEXIFData.mFocalDen) {
533 char temp_value[256]; // arbitrarily long string
534 snprintf(temp_value,
535 sizeof(temp_value)/sizeof(char),
536 "%u/%u",
537 mEXIFData.mFocalNum,
538 mEXIFData.mFocalDen);
539 ret = exifTable->insertElement(TAG_FOCALLENGTH, temp_value);
540
541 }
542 }
543
544 if ((NO_ERROR == ret)) {
545 int status = gettimeofday (&sTv, NULL);
546 pTime = localtime (&sTv.tv_sec);
547 char temp_value[EXIF_DATE_TIME_SIZE + 1];
548 if ((0 == status) && (NULL != pTime)) {
549 snprintf(temp_value, EXIF_DATE_TIME_SIZE,
550 "%04d:%02d:%02d %02d:%02d:%02d",
551 pTime->tm_year + 1900,
552 pTime->tm_mon + 1,
553 pTime->tm_mday,
554 pTime->tm_hour,
555 pTime->tm_min,
556 pTime->tm_sec );
557 ret = exifTable->insertElement(TAG_DATETIME, temp_value);
558 }
559 }
560
561 if ((NO_ERROR == ret)) {
562 char temp_value[5];
563 snprintf(temp_value, sizeof(temp_value)/sizeof(char), "%lu", capData->mWidth);
564 ret = exifTable->insertElement(TAG_IMAGE_WIDTH, temp_value);
565 }
566
567 if ((NO_ERROR == ret)) {
568 char temp_value[5];
569 snprintf(temp_value, sizeof(temp_value)/sizeof(char), "%lu", capData->mHeight);
570 ret = exifTable->insertElement(TAG_IMAGE_LENGTH, temp_value);
571 }
572
573 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLatValid)) {
574 char temp_value[256]; // arbitrarily long string
575 snprintf(temp_value,
576 sizeof(temp_value)/sizeof(char) - 1,
577 "%d/%d,%d/%d,%d/%d",
578 abs(mEXIFData.mGPSData.mLatDeg), 1,
579 abs(mEXIFData.mGPSData.mLatMin), 1,
580 abs(mEXIFData.mGPSData.mLatSec), abs(mEXIFData.mGPSData.mLatSecDiv));
581 ret = exifTable->insertElement(TAG_GPS_LAT, temp_value);
582 }
583
584 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLatValid)) {
585 ret = exifTable->insertElement(TAG_GPS_LAT_REF, mEXIFData.mGPSData.mLatRef);
586 }
587
588 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLongValid)) {
589 char temp_value[256]; // arbitrarily long string
590 snprintf(temp_value,
591 sizeof(temp_value)/sizeof(char) - 1,
592 "%d/%d,%d/%d,%d/%d",
593 abs(mEXIFData.mGPSData.mLongDeg), 1,
594 abs(mEXIFData.mGPSData.mLongMin), 1,
595 abs(mEXIFData.mGPSData.mLongSec), abs(mEXIFData.mGPSData.mLongSecDiv));
596 ret = exifTable->insertElement(TAG_GPS_LONG, temp_value);
597 }
598
599 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mLongValid)) {
600 ret = exifTable->insertElement(TAG_GPS_LONG_REF, mEXIFData.mGPSData.mLongRef);
601 }
602
603 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mAltitudeValid)) {
604 char temp_value[256]; // arbitrarily long string
605 snprintf(temp_value,
606 sizeof(temp_value)/sizeof(char) - 1,
607 "%d/%d",
608 abs( mEXIFData.mGPSData.mAltitude), 1);
609 ret = exifTable->insertElement(TAG_GPS_ALT, temp_value);
610 }
611
612 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mAltitudeValid)) {
613 char temp_value[5];
614 snprintf(temp_value,
615 sizeof(temp_value)/sizeof(char) - 1,
616 "%d", mEXIFData.mGPSData.mAltitudeRef);
617 ret = exifTable->insertElement(TAG_GPS_ALT_REF, temp_value);
618 }
619
620 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mMapDatumValid)) {
621 ret = exifTable->insertElement(TAG_GPS_MAP_DATUM, mEXIFData.mGPSData.mMapDatum);
622 }
623
624 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mProcMethodValid)) {
625 char temp_value[GPS_PROCESSING_SIZE];
626
627 memcpy(temp_value, ExifAsciiPrefix, sizeof(ExifAsciiPrefix));
628 memcpy(temp_value + sizeof(ExifAsciiPrefix),
629 mEXIFData.mGPSData.mProcMethod,
630 (GPS_PROCESSING_SIZE - sizeof(ExifAsciiPrefix)));
631 ret = exifTable->insertElement(TAG_GPS_PROCESSING_METHOD, temp_value);
632 }
633
634 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mVersionIdValid)) {
635 char temp_value[256]; // arbitrarily long string
636 snprintf(temp_value,
637 sizeof(temp_value)/sizeof(char) - 1,
638 "%d,%d,%d,%d",
639 mEXIFData.mGPSData.mVersionId[0],
640 mEXIFData.mGPSData.mVersionId[1],
641 mEXIFData.mGPSData.mVersionId[2],
642 mEXIFData.mGPSData.mVersionId[3]);
643 ret = exifTable->insertElement(TAG_GPS_VERSION_ID, temp_value);
644 }
645
646 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mTimeStampValid)) {
647 char temp_value[256]; // arbitrarily long string
648 snprintf(temp_value,
649 sizeof(temp_value)/sizeof(char) - 1,
650 "%d/%d,%d/%d,%d/%d",
651 mEXIFData.mGPSData.mTimeStampHour, 1,
652 mEXIFData.mGPSData.mTimeStampMin, 1,
653 mEXIFData.mGPSData.mTimeStampSec, 1);
654 ret = exifTable->insertElement(TAG_GPS_TIMESTAMP, temp_value);
655 }
656
657 if ((NO_ERROR == ret) && (mEXIFData.mGPSData.mDatestampValid) ) {
658 ret = exifTable->insertElement(TAG_GPS_DATESTAMP, mEXIFData.mGPSData.mDatestamp);
659 }
660
661 if (NO_ERROR == ret) {
662 const char* exif_orient =
663 ExifElementsTable::degreesToExifOrientation(mPictureRotation);
664
665 if (exif_orient) {
666 ret = exifTable->insertElement(TAG_ORIENTATION, exif_orient);
667 }
668 }
669
670 // fill in short and ushort tags
671 if (NO_ERROR == ret) {
672 char temp_value[2];
673 temp_value[1] = '\0';
674
675 // AWB
676 if (mParameters3A.WhiteBallance == OMX_WhiteBalControlAuto) {
677 temp_value[0] = '0';
678 } else {
679 temp_value[0] = '1';
680 }
681 exifTable->insertElement(TAG_WHITEBALANCE, temp_value);
682
683 // MeteringMode
684 // TODO(XXX): only supporting this metering mode at the moment, may change in future
685 temp_value[0] = '2';
686 exifTable->insertElement(TAG_METERING_MODE, temp_value);
687
688 // ExposureProgram
689 // TODO(XXX): only supporting this exposure program at the moment, may change in future
690 temp_value[0] = '3';
691 exifTable->insertElement(TAG_EXPOSURE_PROGRAM, temp_value);
692
693 // ColorSpace
694 temp_value[0] = '1';
695 exifTable->insertElement(TAG_COLOR_SPACE, temp_value);
696
697 temp_value[0] = '2';
698 exifTable->insertElement(TAG_SENSING_METHOD, temp_value);
699
700 temp_value[0] = '1';
701 exifTable->insertElement(TAG_CUSTOM_RENDERED, temp_value);
702 }
703
704 if (pAncillaryData && (NO_ERROR == ret)) {
705 unsigned int numerator = 0, denominator = 0;
706 char temp_value[256];
707 unsigned int temp_num = 0;
708
709 // DigitalZoomRatio
710 snprintf(temp_value,
711 sizeof(temp_value)/sizeof(char),
712 "%u/%u",
713 pAncillaryData->nDigitalZoomFactor, 1024);
714 exifTable->insertElement(TAG_DIGITALZOOMRATIO, temp_value);
715
716 // ExposureTime
717 snprintf(temp_value,
718 sizeof(temp_value)/sizeof(char),
719 "%u/%u",
720 pAncillaryData->nExposureTime, 1000000);
721 exifTable->insertElement(TAG_EXPOSURETIME, temp_value);
722
723 // ApertureValue and FNumber
724 snprintf(temp_value,
725 sizeof(temp_value)/sizeof(char),
726 "%u/%u",
727 pAncillaryData->nApertureValue, 100);
728 exifTable->insertElement(TAG_FNUMBER, temp_value);
729 exifTable->insertElement(TAG_APERTURE, temp_value);
730
731 // ISO
732 snprintf(temp_value,
733 sizeof(temp_value)/sizeof(char),
734 "%u,0,0",
735 pAncillaryData->nCurrentISO);
736 exifTable->insertElement(TAG_ISO_EQUIVALENT, temp_value);
737
738 // ShutterSpeed
739 snprintf(temp_value,
740 sizeof(temp_value)/sizeof(char),
741 "%f",
742 log(pAncillaryData->nExposureTime) / log(2));
743 ExifElementsTable::stringToRational(temp_value, &numerator, &denominator);
744 snprintf(temp_value, sizeof(temp_value)/sizeof(char), "%u/%u", numerator, denominator);
745 exifTable->insertElement(TAG_SHUTTERSPEED, temp_value);
746
747 // Flash
748 if (mParameters3A.FlashMode == OMX_IMAGE_FlashControlAuto) {
749 if(pAncillaryData->nFlashStatus) temp_num = 0x19; // Flash fired, auto mode
750 else temp_num = 0x18; // Flash did not fire, auto mode
751 } else if (mParameters3A.FlashMode == OMX_IMAGE_FlashControlOn) {
752 if(pAncillaryData->nFlashStatus) temp_num = 0x9; // Flash fired, compulsory flash mode
753 else temp_num = 0x10; // Flash did not fire, compulsory flash mode
754 } else if(pAncillaryData->nFlashStatus) {
755 temp_num = 0x1; // Flash fired
756 } else {
757 temp_num = 0x0; // Flash did not fire
758 }
759 snprintf(temp_value,
760 sizeof(temp_value)/sizeof(char),
761 "%u", temp_num);
762 exifTable->insertElement(TAG_FLASH, temp_value);
763
764 if (pWhiteBalanceData) {
765 unsigned int lightsource = 0;
766 unsigned int colourtemp = pWhiteBalanceData->nColorTemperature;
767 bool flash_fired = (temp_num & 0x1); // value from flash above
768
769 // stole this from framework/tools_library/src/tools_sys_exif_tags.c
770 if( colourtemp <= 3200 ) {
771 lightsource = 3; // Tungsten
772 } else if( colourtemp > 3200 && colourtemp <= 4800 ) {
773 lightsource = 2; // Fluorescent
774 } else if( colourtemp > 4800 && colourtemp <= 5500 ) {
775 lightsource = 1; // Daylight
776 } else if( colourtemp > 5500 && colourtemp <= 6500 ) {
777 lightsource = 9; // Fine weather
778 } else if( colourtemp > 6500 ) {
779 lightsource = 10; // Cloudy weather
780 }
781
782 if(flash_fired) {
783 lightsource = 4; // Flash
784 }
785
786 snprintf(temp_value,
787 sizeof(temp_value)/sizeof(char),
788 "%u", lightsource);
789 exifTable->insertElement(TAG_LIGHT_SOURCE, temp_value);
790 }
791 }
792
793 LOG_FUNCTION_NAME_EXIT;
794
795 return ret;
796 }
797
convertGPSCoord(double coord,int & deg,int & min,int & sec,int & secDivisor)798 status_t OMXCameraAdapter::convertGPSCoord(double coord,
799 int °,
800 int &min,
801 int &sec,
802 int &secDivisor)
803 {
804 double tmp;
805
806 LOG_FUNCTION_NAME;
807
808 if ( coord == 0 ) {
809
810 CAMHAL_LOGE("Invalid GPS coordinate");
811
812 return -EINVAL;
813 }
814
815 deg = (int) floor(fabs(coord));
816 tmp = ( fabs(coord) - floor(fabs(coord)) ) * GPS_MIN_DIV;
817 min = (int) floor(tmp);
818 tmp = ( tmp - floor(tmp) ) * ( GPS_SEC_DIV * GPS_SEC_ACCURACY );
819 sec = (int) floor(tmp);
820 secDivisor = GPS_SEC_ACCURACY;
821
822 if( sec >= ( GPS_SEC_DIV * GPS_SEC_ACCURACY ) ) {
823 sec = 0;
824 min += 1;
825 }
826
827 if( min >= 60 ) {
828 min = 0;
829 deg += 1;
830 }
831
832 LOG_FUNCTION_NAME_EXIT;
833
834 return NO_ERROR;
835 }
836
837 } // namespace Camera
838 } // namespace Ti
839