Tizen 2.1 base
[platform/core/multimedia/libmm-camcorder.git] / src / mm_camcorder_exifinfo.c
1 /*
2  * libmm-camcorder
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jeongmo Yang <jm80.yang@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21  
22 #include "mm_camcorder_exifinfo.h"
23 #include "mm_camcorder_exifdef.h"
24
25 #include <libexif/exif-loader.h>
26 #include <libexif/exif-utils.h>
27 #include <libexif/exif-data.h>
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <time.h>
32 #include <mm_debug.h>
33 #include <mm_error.h>
34 #include <glib.h>
35
36 #define MM_EXIFINFO_USE_BINARY_EXIFDATA         1
37 #define JPEG_MAX_SIZE                           20000000
38 #define JPEG_THUMBNAIL_MAX_SIZE                 (128*1024)
39 #define JPEG_DATA_OFFSET                        2
40 #define EXIF_MARKER_SOI_LENGTH                  2
41 #define EXIF_MARKER_APP1_LENGTH                 2
42 #define EXIF_APP1_LENGTH                        2
43
44 #if MM_EXIFINFO_USE_BINARY_EXIFDATA
45 /**
46  * Exif Binary Data.
47  */
48 #include <string.h>
49 #define _EXIF_BIN_SIZE_         ((unsigned int)174)
50 unsigned char g_exif_bin [_EXIF_BIN_SIZE_] = {
51    0x45 , 0x78 , 0x69 , 0x66 , 0x00 , 0x00 , 0x49 , 0x49 , 0x2a , 0x00 , 0x08 , 0x00 , 0x00 , 0x00 , 0x05 , 0x00
52  , 0x1a , 0x01 , 0x05 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x4a , 0x00 , 0x00 , 0x00 , 0x1b , 0x01 , 0x05 , 0x00
53  , 0x01 , 0x00 , 0x00 , 0x00 , 0x52 , 0x00 , 0x00 , 0x00 , 0x28 , 0x01 , 0x03 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00
54  , 0x02 , 0x00 , 0x00 , 0x00 , 0x13 , 0x02 , 0x03 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00
55  , 0x69 , 0x87 , 0x04 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x5a , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
56  , 0x48 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x48 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00
57  , 0x06 , 0x00 , 0x00 , 0x90 , 0x07 , 0x00 , 0x04 , 0x00 , 0x00 , 0x00 , 0x30 , 0x32 , 0x31 , 0x30 , 0x01 , 0x91
58  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xa0 , 0x07 , 0x00 , 0x04 , 0x00
59  , 0x00 , 0x00 , 0x30 , 0x31 , 0x30 , 0x30 , 0x01 , 0xa0 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
60  , 0x00 , 0x00 , 0x02 , 0xa0 , 0x04 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x03 , 0xa0
61  , 0x04 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
62 };
63 #endif
64
65 /**
66  * Structure for exif entry.
67  */
68 typedef struct  _mm_exif_entry_t
69 {
70         ExifTag                 tag;                    /**< exif tag*/
71         ExifFormat              format;                 /**< exif format*/
72         unsigned long   components;             /**< number of components*/
73         unsigned char   *data;                  /**< data*/
74         unsigned int    size;                   /**< size of data*/
75 } mm_exif_entry_type;
76
77
78 /**
79  * local functions.
80  */
81 static void
82 _exif_set_uint16 (int is_motorola, void * out, unsigned short in)
83 {
84         if (is_motorola) {
85                 ((unsigned char *)out)[0] = in & 0x00ff;
86                 ((unsigned char *)out)[1] = in >> 8;
87         } else {
88                 ((unsigned char *)out)[0] = in >> 8;
89                 ((unsigned char *)out)[1] = in & 0x00ff;
90         }
91 }
92
93
94 #ifdef _MMCAMCORDER_EXIF_GET_JPEG_MARKER_OFFSET
95 static unsigned long
96 _exif_get_jpeg_marker_offset (void *jpeg, int jpeg_size, unsigned short marker)
97 {
98         unsigned char   *p = NULL;
99         unsigned char   *src = jpeg;
100         int                             src_sz = jpeg_size;
101         unsigned char   m[2];
102         unsigned long   ret;
103         int i;
104
105         // mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
106
107         m[0] = marker >> 8;
108         m[1] = marker & 0x00FF;
109
110         mmf_debug (MMF_DEBUG_LOG,"[%05d][%s] marker: 0x%02X 0x%02X\n\n", __LINE__, __func__,m[0], m[1]);
111
112         if (*src == 0xff && *(src + 1) == 0xd8) 
113         {
114                 p = src + 2; /* SOI(start of image) */
115         } 
116         else 
117         {
118                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] invalid JPEG file.\n", __LINE__, __func__);
119                 return 0UL;
120         }
121
122         for (i = 0; i < src_sz - (1 + 2); i++, p++) 
123         {
124                 if (*p == 0xff) 
125                 {
126                         /*marker is 0xFFxx*/
127                         if (*(p + 1) == m[1]) 
128                         {
129                                 ret = p - src;
130                                 mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]marker offset: %lu %p %p.\n", __LINE__, __func__,ret, (p+1), src);
131                                 return ret;
132                         }
133                 } 
134         }
135         mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]Marker not found.\n", __LINE__, __func__);
136         return 0UL;
137 }
138 #endif /* _MMCAMCORDER_EXIF_GET_JPEG_MARKER_OFFSET */
139
140
141 ExifData*
142 mm_exif_get_exif_data_from_data (mm_exif_info_t *info)
143 {
144         ExifData                *ed = NULL;
145
146         //mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
147
148         ed = exif_data_new_from_data(info->data, info->size);
149         if( ed == NULL )
150         {
151                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]Null exif data. (ed:%p)\n", __LINE__, __func__, ed);
152         }
153
154         return ed;
155 }
156
157
158 ExifData*
159 mm_exif_get_exif_from_info (mm_exif_info_t *info)
160 {
161         ExifData                *ed = NULL;
162         ExifLoader              *loader = NULL;
163
164         unsigned char   size[2];
165         unsigned int    i;
166
167         //mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
168         
169         /*get ExifData from info*/
170         loader = exif_loader_new ();
171
172         size[0] = (unsigned char) (info->size);
173         size[1] = (unsigned char) (info->size >> 8);
174         exif_loader_write (loader, size, 2);
175
176         for (i = 0; i < info->size && exif_loader_write (loader, info->data + i, 1); i++);
177
178         ed = exif_loader_get_data (loader);
179         exif_loader_unref (loader);
180         return ed;
181 }
182
183
184 int
185 mm_exif_set_exif_to_info (mm_exif_info_t *info, ExifData *exif)
186 {
187         unsigned char   *eb = NULL;
188         unsigned int    ebs;
189
190         if (!exif)
191         {
192                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]exif Null\n", __LINE__, __func__);
193                 return MM_ERROR_CAMCORDER_NOT_INITIALIZED;
194         }
195
196         mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]exif(ifd :%p)\n", __LINE__, __func__, exif->ifd);
197
198         if(info->data)
199         {
200                 free (info->data); 
201                 info->data = NULL; 
202                 info->size = 0; 
203         }
204
205         exif_data_save_data (exif, &eb, &ebs);
206         if(eb==NULL)
207         {
208                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]MM_ERROR_CAMCORDER_LOW_MEMORY\n", __LINE__, __func__);
209                 return MM_ERROR_CAMCORDER_LOW_MEMORY;
210         }
211         info->data = eb;
212         info->size = ebs;
213         return MM_ERROR_NONE;
214 }
215
216
217 int
218 mm_exif_set_add_entry (ExifData *exif, ExifIfd ifd, ExifTag tag,ExifFormat format,unsigned long components,unsigned char* data)
219 {
220         /*mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);*/
221         ExifData *ed = (ExifData *)exif;
222         ExifEntry *e = NULL;
223
224         if (exif == NULL || format <= 0 || components <= 0 || data == NULL) {
225                 mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s] invalid argument exif=%p format=%d, components=%lu data=%p!\n",
226                                           __LINE__, __func__,exif,format,components,data);
227                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
228         }
229
230         /*remove same tag in EXIF*/
231         exif_content_remove_entry(ed->ifd[ifd], exif_content_get_entry(ed->ifd[ifd], tag));
232
233         /*create new tag*/
234         e = exif_entry_new();
235         if (e == NULL) {
236                 mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s] entry create error!\n", __LINE__, __func__);
237                 return MM_ERROR_CAMCORDER_LOW_MEMORY;
238         }
239
240         exif_entry_initialize(e, tag);
241
242         e->tag = tag;
243         e->format = format;
244         e->components = components;
245
246         if (e->size == 0) {
247                 e->data = NULL;
248                 e->data = malloc(exif_format_get_size(format) * e->components);
249                 if (!e->data) {
250                         exif_entry_unref(e);
251                         return MM_ERROR_CAMCORDER_LOW_MEMORY;
252                 }
253
254                 if (format == EXIF_FORMAT_ASCII) {
255                         memset(e->data, '\0', exif_format_get_size(format) * e->components);
256                 }
257         }
258
259         e->size = exif_format_get_size(format) * e->components;
260         memcpy(e->data,data,e->size);
261         exif_content_add_entry(ed->ifd[ifd], e);
262         exif_entry_unref(e);
263
264         return MM_ERROR_NONE;
265 }
266
267
268
269
270 /**
271  * global functions.
272  */
273
274
275 int
276 mm_exif_create_exif_info (mm_exif_info_t **info)
277 {
278         mm_exif_info_t *x = NULL;
279 #if (MM_EXIFINFO_USE_BINARY_EXIFDATA == 0)
280         ExifData *ed = NULL;
281         unsigned char *eb = NULL;
282         unsigned int ebs;
283 #endif
284         mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]\n", __LINE__, __func__);
285
286         if (!info) {
287                 mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s] NULL pointer\n", __LINE__, __func__);
288                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
289         }
290
291         x = malloc(sizeof(mm_exif_info_t));
292         if (!x) {
293                 mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s]malloc error\n", __LINE__, __func__);
294                 return MM_ERROR_CAMCORDER_LOW_MEMORY;
295         }
296 #if MM_EXIFINFO_USE_BINARY_EXIFDATA
297         x->data = NULL;
298         x->data = malloc(_EXIF_BIN_SIZE_);
299         if (!x->data) {
300                 mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s]malloc error\n", __LINE__, __func__);
301                 free(x);
302                 return MM_ERROR_CAMCORDER_LOW_MEMORY;
303         }
304         memcpy(x->data, g_exif_bin, _EXIF_BIN_SIZE_);
305         x->size = _EXIF_BIN_SIZE_;
306 #else
307         ed = exif_data_new();
308         if (!ed) {
309                 mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s]exif data new error\n", __LINE__, __func__);
310                 return MM_ERROR_CAMCORDER_LOW_MEMORY;
311         }
312
313         exif_data_set_byte_order(ed, EXIF_BYTE_ORDER_INTEL);
314         exif_data_set_data_type(ed, EXIF_DATA_TYPE_COMPRESSED);
315         exif_data_set_option(ed, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
316
317         exif_data_fix(ed);
318
319         exif_data_save_data(ed, &eb, &ebs);
320         if (eb == NULL) {
321                 mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s]exif_data_save_data error\n", __LINE__, __func__);
322                 free(x->data);
323                 free(x);
324                 exif_data_unref(ed);
325                 return MM_ERROR_CAMCORDER_INTERNAL;
326         }
327         exif_data_unref(ed);
328
329         x->data = eb;
330         x->size = ebs;
331 #endif
332         *info = x;
333
334         mmf_debug(MMF_DEBUG_LOG, "%s() Data:%p Size:%d\n", __func__, x->data, x->size);
335
336         return MM_ERROR_NONE;
337 }
338
339 void
340 mm_exif_destory_exif_info (mm_exif_info_t *info)
341 {
342         //mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
343
344 #if MM_EXIFINFO_USE_BINARY_EXIFDATA
345         if (info) {
346                 if (info->data) 
347                         free (info->data);
348                 free (info);
349         }
350 #else
351         if (info) {
352                 if (info->data) 
353                         exif_mem_free (info->data);
354                 free (info);
355         }
356 #endif
357 }
358
359
360 int
361 mm_exif_add_thumbnail_info (mm_exif_info_t *info, void *thumbnail, int width, int height, int len)
362 {
363         ExifData *ed = NULL;
364         static ExifLong elong[10];
365
366         unsigned char *p_compressed = NULL;
367         int ret = MM_ERROR_NONE;
368         int cntl = 0;
369
370         mmf_debug (MMF_DEBUG_LOG,"[%05d][%s] Thumbnail size:%d, width:%d, height:%d\n", __LINE__, __func__, len, width, height);
371
372         if( len > JPEG_THUMBNAIL_MAX_SIZE )
373         {
374                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] Thumbnail size[%d] over!!! Skip inserting thumbnail...\n", __LINE__, __func__, len);
375                 return MM_ERROR_NONE;
376         }
377
378         /* get ExifData from info*/
379         ed = mm_exif_get_exif_from_info(info);
380         ed->data = thumbnail;
381         ed->size = len;
382
383         /* set thumbnail data */
384         p_compressed = malloc(sizeof(ExifShort));
385         if (p_compressed != NULL) {
386                 exif_set_short(p_compressed, exif_data_get_byte_order(ed), 6);
387                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_1, EXIF_TAG_COMPRESSION, EXIF_FORMAT_SHORT, 1, p_compressed);
388                 if (ret != MM_ERROR_NONE) {
389                         goto exit;
390                 }
391         } else {
392                 ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
393                 goto exit;
394         }
395
396         /* set thumbnail size */
397         exif_set_long ((unsigned char *)&elong[cntl], exif_data_get_byte_order(ed), width);
398         ret = mm_exif_set_add_entry(ed, EXIF_IFD_1, EXIF_TAG_IMAGE_WIDTH, EXIF_FORMAT_LONG, 1, (unsigned char*)&elong[cntl++]);
399         if (ret != MM_ERROR_NONE) {
400                 goto exit;
401         }
402         exif_set_long ((unsigned char *)&elong[cntl], exif_data_get_byte_order(ed), height);
403         ret = mm_exif_set_add_entry(ed, EXIF_IFD_1, EXIF_TAG_IMAGE_LENGTH, EXIF_FORMAT_LONG, 1, (unsigned char*)&elong[cntl++]);
404         if (ret != MM_ERROR_NONE) {
405                 goto exit;
406         }
407
408         ret = mm_exif_set_exif_to_info (info, ed);
409         if (ret != MM_ERROR_NONE) {
410                 goto exit;
411         }
412
413         ed->data = NULL;
414         ed->size = 0;
415         exif_data_unref (ed);   
416
417 exit :
418         if(p_compressed != NULL)
419                 free(p_compressed);
420         return ret;
421 }
422
423
424 int mm_exif_mnote_create (ExifData *exif)
425 {
426         ExifData* ed = exif;
427         ExifDataOption o = 0;
428         if(!ed){
429                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] invalid argument exif=%p \n", __LINE__, __func__,ed);
430                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
431         }
432
433         if(!exif_data_mnote_data_new(ed, MAKER_SAMSUNG,  o )){
434                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_mnote_data_samsung_new() failed. \n", __LINE__, __func__);
435                 return MM_ERROR_CAMCORDER_MNOTE_CREATION;
436         }
437
438         return MM_ERROR_NONE;
439 }
440
441
442 int mm_exif_mnote_set_add_entry (ExifData *exif, MnoteSamsungTag tag, int index, int subindex1, int subindex2)
443 {
444         ExifData *ed = exif;
445         ExifMnoteData *md;
446
447         ExifShort product_id = 32768;   //should be modified
448         char serialNum[] = "SerialNum123"; //should be modified
449
450         if(!ed){
451                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] invalid argument exif=%p \n", __LINE__, __func__,ed);
452                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
453         }
454
455         md = exif_data_get_mnote_data (ed);
456         if(!md){
457                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_get_mnote_data() failed. \n", __LINE__, __func__);
458                 return MM_ERROR_CAMCORDER_MNOTE_CREATION;
459         }
460
461         if(!exif_data_mnote_set_mem_for_adding_entry(md, MAKER_SAMSUNG)){
462                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_mem_for_adding_entry() failed. \n", __LINE__, __func__);
463                 return MM_ERROR_CAMCORDER_MNOTE_MALLOC;
464         }
465
466         exif_mnote_data_set_byte_order(md, (ExifByteOrder) exif_data_get_data_order(ed));
467
468         switch(tag){
469                 case MNOTE_SAMSUNG_TAG_MNOTE_VERSION:
470                         if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_UNDEFINED, 4, index)){
471                                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
472                                 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
473                         }
474                         break;
475                 case MNOTE_SAMSUNG_TAG_DEVICE_ID:
476                         if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, index)){
477                                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
478                                 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
479                         }
480                         break;
481                 case MNOTE_SAMSUNG_TAG_MODEL_ID:
482                         if(!exif_data_mnote_set_add_entry_subtag(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, MNOTE_SAMSUNG_SUBTAG_MODEL_ID_CLASS, subindex1, MNOTE_SAMSUNG_SUBTAG_MODEL_ID_DEVEL, subindex2, product_id )){
483                                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry_subtag() failed. \n", __LINE__, __func__);
484                                 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
485                         }       
486                         break;
487                 case MNOTE_SAMSUNG_TAG_COLOR_INFO:
488                 case MNOTE_SAMSUNG_TAG_SERIAL_NUM:
489                         if(!exif_data_mnote_set_add_entry_string(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_ASCII, strlen(serialNum), serialNum)){
490                                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry_string() failed. \n", __LINE__, __func__);
491                                 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
492                         }
493                         break;
494                 case MNOTE_SAMSUNG_TAG_IMAGE_COUNT:
495                 case MNOTE_SAMSUNG_TAG_GPS_INFO01:
496                 case MNOTE_SAMSUNG_TAG_GPS_INFO02:
497                 case MNOTE_SAMSUNG_TAG_PREVIEW_IMAGE:
498                 case MNOTE_SAMSUNG_TAG_FAVOR_TAGGING:
499                 case MNOTE_SAMSUNG_TAG_SRW_COMPRESS:
500                 case MNOTE_SAMSUNG_TAG_COLOR_SPACE:
501                         if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, index)){
502                                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
503                                 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
504                         }
505                         break;
506                 case MNOTE_SAMSUNG_TAG_AE:
507                 case MNOTE_SAMSUNG_TAG_AF:
508                 case MNOTE_SAMSUNG_TAG_AWB01:
509                 case MNOTE_SAMSUNG_TAG_AWB02:
510                 case MNOTE_SAMSUNG_TAG_IPC:
511                 case MNOTE_SAMSUNG_TAG_SCENE_RESULT:
512                 case MNOTE_SAMSUNG_TAG_SADEBUG_INFO01:
513                 case MNOTE_SAMSUNG_TAG_SADEBUG_INFO02:
514                 case MNOTE_SAMSUNG_TAG_FACE_DETECTION:
515                         if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, index)){
516                                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
517                                 return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
518                         }
519                         break;
520                 case MNOTE_SAMSUNG_TAG_FACE_FEAT01:
521                 case MNOTE_SAMSUNG_TAG_FACE_FEAT02:
522                 case MNOTE_SAMSUNG_TAG_FACE_RECOG:
523                 case MNOTE_SAMSUNG_TAG_LENS_INFO:
524                 case MNOTE_SAMSUNG_TAG_THIRDPARTY:
525                         break;
526                 default:
527                         break;
528         }
529         return MM_ERROR_NONE;
530 }
531
532
533 int
534 mm_exif_write_exif_jpeg_to_file (char *filename, mm_exif_info_t *info,  void *jpeg, int jpeg_len)
535 {
536         FILE *fp = NULL;
537         unsigned short head[2] = {0,};
538         unsigned short head_len = 0;
539         unsigned char *eb = NULL;
540         unsigned int ebs;
541
542         mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]\n", __LINE__, __func__);
543
544         eb = info->data;
545         ebs = info->size;
546
547         /*create file*/
548         fp = fopen (filename, "wb");
549         if (!fp) {
550                 mmf_debug (MMF_DEBUG_ERROR, "%s(), fopen() failed [%s].\n", __func__, filename);
551                 return MM_ERROR_IMAGE_FILEOPEN;
552         }
553
554         /*set SOI, APP1*/
555         _exif_set_uint16 (0, &head[0], 0xffd8);
556         _exif_set_uint16 (0, &head[1], 0xffe1);
557         /*set header length*/
558         _exif_set_uint16 (0, &head_len, (unsigned short)(ebs + 2));
559
560         if(head[0]==0 || head[1]==0 || head_len==0)
561         {
562                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]setting error\n", __LINE__, __func__);
563                 fclose (fp);
564                 return -1;
565         }
566
567         fwrite (&head[0], 1, EXIF_MARKER_SOI_LENGTH, fp);       /*SOI marker*/
568         fwrite (&head[1], 1, EXIF_MARKER_APP1_LENGTH, fp);      /*APP1 marker*/
569         fwrite (&head_len, 1, EXIF_APP1_LENGTH, fp);            /*length of APP1*/
570         fwrite (eb, 1, ebs, fp);                                /*EXIF*/
571         fwrite (jpeg + JPEG_DATA_OFFSET, 1, jpeg_len - JPEG_DATA_OFFSET, fp);   /*IMAGE*/
572
573         fclose (fp);
574
575         return MM_ERROR_NONE;
576 }
577
578 int
579 mm_exif_write_exif_jpeg_to_memory (void **mem, unsigned int *length, mm_exif_info_t *info,  void *jpeg, unsigned int jpeg_len)
580 {
581         unsigned short head[2] = {0,};
582         unsigned short head_len = 0;
583         unsigned char *eb = NULL;
584         unsigned int ebs;
585
586         /*output*/
587         unsigned char *m = NULL;
588         int m_len = 0;
589
590         mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]\n", __LINE__, __func__);
591
592         if(info==NULL || jpeg==NULL)
593         {
594                 mmf_debug (MMF_DEBUG_ERROR, "%s(), MM_ERROR_CAMCORDER_INVALID_ARGUMENT info=%p, jpeg=%p\n", __func__,info,jpeg);
595                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
596         }
597
598         if(jpeg_len>JPEG_MAX_SIZE)
599         {
600                 mmf_debug (MMF_DEBUG_ERROR, "%s(),jpeg_len is worng jpeg_len=%d\n", __func__,jpeg_len);
601                 return MM_ERROR_CAMCORDER_DEVICE_WRONG_JPEG;    
602         }
603
604         eb = info->data;
605         ebs = info->size;
606
607         /*length of output image*/
608         /*SOI + APP1 + length of APP1 + length of EXIF + IMAGE*/
609         m_len = EXIF_MARKER_SOI_LENGTH + EXIF_MARKER_APP1_LENGTH + EXIF_APP1_LENGTH + ebs + (jpeg_len - JPEG_DATA_OFFSET);
610         /*alloc output image*/
611         m = malloc (m_len);
612         if (!m) {
613                 mmf_debug (MMF_DEBUG_ERROR, "%s(), malloc() failed.\n", __func__);
614                 return MM_ERROR_CAMCORDER_LOW_MEMORY;   
615         }
616
617         /*set SOI, APP1*/
618         _exif_set_uint16 (0, &head[0], 0xffd8);
619         _exif_set_uint16 (0, &head[1], 0xffe1);
620         /*set header length*/
621         _exif_set_uint16 (0, &head_len, (unsigned short)(ebs + 2));
622         if (head[0] == 0 || head[1] == 0 || head_len == 0) {
623                 mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]setting error\n", __LINE__, __func__);
624                 free(m);
625                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
626         }
627
628         /* Complete JPEG+EXIF */
629         /*SOI marker*/
630         memcpy(m, &head[0], EXIF_MARKER_SOI_LENGTH);
631         /*APP1 marker*/
632         memcpy(m + EXIF_MARKER_SOI_LENGTH,
633                &head[1], EXIF_MARKER_APP1_LENGTH);
634         /*length of APP1*/
635         memcpy(m + EXIF_MARKER_SOI_LENGTH + EXIF_MARKER_APP1_LENGTH,
636                &head_len, EXIF_APP1_LENGTH);
637         /*EXIF*/
638         memcpy(m + EXIF_MARKER_SOI_LENGTH + EXIF_MARKER_APP1_LENGTH + EXIF_APP1_LENGTH,
639                eb, ebs);
640         /*IMAGE*/
641         memcpy(m + EXIF_MARKER_SOI_LENGTH + EXIF_MARKER_APP1_LENGTH + EXIF_APP1_LENGTH + ebs,
642                jpeg + JPEG_DATA_OFFSET, jpeg_len - JPEG_DATA_OFFSET);
643
644         mmf_debug(MMF_DEBUG_LOG,"[%05d][%s] JPEG+EXIF Copy DONE(original:%d, copied:%d)\n",
645                                 __LINE__, __func__, jpeg_len, jpeg_len - JPEG_DATA_OFFSET);
646
647         /*set ouput param*/
648         *mem    = m;
649         *length = m_len;
650
651         return MM_ERROR_NONE;
652 }