Update error handling for capture while recording
[platform/core/multimedia/libmm-camcorder.git] / src / mm_camcorder_stillshot.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 /*=======================================================================================
23 |  INCLUDE FILES                                                                        |
24 =======================================================================================*/
25 #include <stdlib.h>
26 #include <sys/time.h>
27 #include <sys/times.h>
28 #include <gst/video/cameracontrol.h>
29 #include "mm_camcorder_internal.h"
30 #include "mm_camcorder_stillshot.h"
31 #include "mm_camcorder_exifinfo.h"
32 #include "mm_camcorder_exifdef.h"
33 #include <libexif/exif-loader.h>
34 #include <libexif/exif-utils.h>
35 #include <libexif/exif-data.h>
36
37 /*---------------------------------------------------------------------------------------
38 |    GLOBAL VARIABLE DEFINITIONS for internal                                           |
39 ---------------------------------------------------------------------------------------*/
40 #define EXIF_SET_ERR(return_type, tag_id) \
41 do { \
42         _mmcam_dbg_err("error=%x,tag=%x", return_type, tag_id); \
43         if (return_type == (int)MM_ERROR_CAMCORDER_LOW_MEMORY) { \
44                 goto exit; \
45         } \
46 } while (0)
47
48 /*---------------------------------------------------------------------------------------
49 |    LOCAL VARIABLE DEFINITIONS for internal                                            |
50 ---------------------------------------------------------------------------------------*/
51 #define THUMBNAIL_WIDTH         320
52 #define THUMBNAIL_HEIGHT        240
53 #define THUMBNAIL_JPEG_QUALITY  90
54 #define TRY_LOCK_MAX_COUNT      100
55 #define TRY_LOCK_TIME           20000   /* ms */
56 #define H264_PREVIEW_BITRATE    1024*10 /* kbps */
57 #define H264_PREVIEW_NEWGOP_INTERVAL    1000 /* ms */
58 #define _MMCAMCORDER_MAKE_THUMBNAIL_INTERNAL_ENCODE
59
60
61 /*---------------------------------------------------------------------------------------
62 |    LOCAL FUNCTION PROTOTYPES:                                                         |
63 ---------------------------------------------------------------------------------------*/
64 /** STATIC INTERNAL FUNCTION **/
65 /* Functions for JPEG capture without Encode bin */
66 int _mmcamcorder_image_cmd_capture(MMHandleType handle);
67 int _mmcamcorder_image_cmd_preview_start(MMHandleType handle);
68 int _mmcamcorder_image_cmd_preview_stop(MMHandleType handle);
69 static void __mmcamcorder_image_capture_cb(GstElement *element, GstSample *sample1, GstSample *sample2, GstSample *sample3, gpointer u_data);
70
71 /* sound status changed callback */
72 static void __sound_status_changed_cb(keynode_t* node, void *data);
73
74 /*=======================================================================================
75 |  FUNCTION DEFINITIONS                                                                 |
76 =======================================================================================*/
77
78 /*---------------------------------------------------------------------------------------
79 |    GLOBAL FUNCTION DEFINITIONS:                                                       |
80 ---------------------------------------------------------------------------------------*/
81
82
83 int _mmcamcorder_create_stillshot_pipeline(MMHandleType handle)
84 {
85         int err = MM_ERROR_UNKNOWN;
86         GstPad *srcpad = NULL;
87         GstPad *sinkpad = NULL;
88
89         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
90         _MMCamcorderSubContext *sc = NULL;
91
92         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
93
94         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
95         mmf_return_val_if_fail(sc && sc->info_image && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
96
97         _mmcam_dbg_log("");
98
99         /* Create gstreamer element */
100         _mmcam_dbg_log("Using Encodebin for capturing");
101
102         /* Create capture pipeline */
103         _MMCAMCORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCODE_MAIN_PIPE, "capture_pipeline", err);
104
105         err = _mmcamcorder_create_encodesink_bin((MMHandleType)hcamcorder, MM_CAMCORDER_ENCBIN_PROFILE_IMAGE);
106         if (err != MM_ERROR_NONE)
107                 return err;
108
109         /* add element and encodesink bin to encode main pipeline */
110         gst_bin_add_many(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
111                 sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst,
112                 sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst,
113                 sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst,
114                 NULL);
115
116         /* Link each element : appsrc - capsfilter - encodesink bin */
117         srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, "src");
118         sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "sink");
119         _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
120
121         srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "src");
122         sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "image_sink0");
123         _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
124
125         /* connect handoff signal to get capture data */
126         MMCAMCORDER_SIGNAL_CONNECT(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst,
127                 _MMCAMCORDER_HANDLER_STILLSHOT, "handoff",
128                 G_CALLBACK(__mmcamcorder_handoff_callback),
129                 hcamcorder);
130
131         return MM_ERROR_NONE;
132
133 pipeline_creation_error:
134         _mmcamcorder_remove_stillshot_pipeline(handle);
135         return err;
136 }
137
138
139 int _mmcamcorder_connect_capture_signal(MMHandleType handle)
140 {
141         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
142         _MMCamcorderSubContext *sc = NULL;
143
144         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
145
146         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
147         mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
148
149         /* check video source element */
150         if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
151                 _mmcam_dbg_warn("connect capture signal to _MMCAMCORDER_VIDEOSRC_SRC");
152                 MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst,
153                         _MMCAMCORDER_HANDLER_STILLSHOT, "still-capture",
154                         G_CALLBACK(__mmcamcorder_image_capture_cb),
155                         hcamcorder);
156
157                 return MM_ERROR_NONE;
158         } else {
159                 _mmcam_dbg_err("videosrc element is not created yet");
160                 return MM_ERROR_CAMCORDER_NOT_INITIALIZED;
161         }
162 }
163
164
165 int _mmcamcorder_remove_stillshot_pipeline(MMHandleType handle)
166 {
167         int ret = MM_ERROR_NONE;
168         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
169         _MMCamcorderSubContext *sc = NULL;
170
171         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
172
173         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
174         mmf_return_val_if_fail(sc && sc->info_image && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
175
176         _mmcam_dbg_log("");
177
178         /* Check pipeline */
179         if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst) {
180                 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_NULL);
181                 if (ret != MM_ERROR_NONE) {
182                         _mmcam_dbg_err("Faile to change encode main pipeline state [0x%x]", ret);
183                         return ret;
184                 }
185
186                 _mmcamcorder_remove_all_handlers(handle, _MMCAMCORDER_HANDLER_STILLSHOT | _MMCAMCORDER_HANDLER_VIDEOREC);
187
188                 GstPad *reqpad = NULL;
189
190                 /* release request pad */
191                 reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "image");
192                 if (reqpad) {
193                         gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
194                         gst_object_unref(reqpad);
195                         reqpad = NULL;
196                 }
197
198                 /* release encode main pipeline */
199                 gst_object_unref(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst);
200
201                 _mmcam_dbg_log("Encoder pipeline removed");
202         } else {
203                 _mmcam_dbg_log("encode main pipeline is already removed");
204         }
205
206         return MM_ERROR_NONE;
207 }
208
209
210 void _mmcamcorder_destroy_video_capture_pipeline(MMHandleType handle)
211 {
212         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
213         _MMCamcorderSubContext *sc = NULL;
214         int display_reuse_hint = FALSE;
215         GstElement *sink_element = NULL;
216         mmf_attrs_t *attrs = NULL;
217         int attr_index = 0;
218         mmf_attribute_t *attr_item = NULL;
219
220         mmf_return_if_fail(hcamcorder);
221
222         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
223         mmf_return_if_fail(sc && sc->element);
224
225         _mmcam_dbg_log("");
226
227         if (sc->element[_MMCAMCORDER_MAIN_PIPE].gst) {
228                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
229                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
230
231                 /* check reuse flag for display element */
232                 mm_camcorder_get_attributes(handle, NULL,
233                         MMCAM_DISPLAY_REUSE_HINT, &display_reuse_hint,
234                         NULL);
235
236                 _mmcam_dbg_log("display reuse hint %d", display_reuse_hint);
237
238                 if (!display_reuse_hint)
239                         goto _REUSE_CHECK_DONE;
240
241                 sink_element = sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst;
242                 if (!sink_element) {
243                         _mmcam_dbg_warn("sink element is NULL");
244                         goto _REUSE_CHECK_DONE;
245                 }
246
247                 attrs = (mmf_attrs_t *)MMF_CAMCORDER_ATTRS(handle);
248                 if (!attrs) {
249                         _mmcam_dbg_warn("attribute is NULL");
250                         goto _REUSE_CHECK_DONE;
251                 }
252
253                 _mmcam_dbg_log("REF sink element %p and set it to attribute", sink_element);
254
255                 /* ref element before remove it from pipeline */
256                 gst_object_ref(sink_element);
257
258                 if (!gst_bin_remove(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst), sink_element))
259                         _mmcam_dbg_warn("failed to remove sink element from pipeline");
260
261                 /* reset floating reference flag to avoid leak after next use */
262                 g_object_force_floating(G_OBJECT(sink_element));
263
264                 /* set sink element pointer to attribute */
265                 mm_attrs_get_index((MMHandleType)attrs, MMCAM_DISPLAY_REUSE_ELEMENT, &attr_index);
266                 attr_item = &attrs->items[attr_index];
267                 mmf_attribute_set_data(attr_item, (void *)sink_element, sizeof(*sink_element));
268                 mmf_attribute_commit(attr_item);
269
270                 /* remove notify callback */
271                 g_object_weak_unref(G_OBJECT(sink_element), (GWeakNotify)_mmcamcorder_element_release_noti, sc);
272
273                 sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst = NULL;
274                 sc->element[_MMCAMCORDER_VIDEOSINK_SINK].id = _MMCAMCORDER_NONE;
275
276 _REUSE_CHECK_DONE:
277                 traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:UNREALIZE:SET_NULL_TO_PIPELINE");
278
279                 _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_NULL);
280
281                 traceEnd(TTRACE_TAG_CAMERA);
282
283                 _mmcamcorder_remove_all_handlers(handle, _MMCAMCORDER_HANDLER_CATEGORY_ALL);
284
285                 traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:UNREALIZE:UNREF_PIPELINE");
286
287                 gst_object_unref(sc->element[_MMCAMCORDER_MAIN_PIPE].gst);
288
289                 traceEnd(TTRACE_TAG_CAMERA);
290
291                 /* NULL initialization will be done in _mmcamcorder_element_release_noti */
292         }
293
294         return;
295 }
296
297
298 int _mmcamcorder_image_cmd_capture(MMHandleType handle)
299 {
300         int ret = MM_ERROR_NONE;
301         int UseCaptureMode = 0;
302         int width = 0;
303         int height = 0;
304         int fps = 0;
305         int cap_format = MM_PIXEL_FORMAT_NV12;
306         int image_encoder = MM_IMAGE_CODEC_JPEG;
307         int strobe_mode = MM_CAMCORDER_STROBE_MODE_OFF;
308         int is_modified_size = FALSE;
309         int tag_orientation = 0;
310         unsigned int cap_fourcc = 0;
311
312         char *err_name = NULL;
313         const char *videosrc_name = NULL;
314
315         GstCameraControl *control = NULL;
316
317         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
318         _MMCamcorderImageInfo *info = NULL;
319         _MMCamcorderSubContext *sc = NULL;
320         type_element *VideosrcElement = NULL;
321         MMCamcorderStateType current_state = MM_CAMCORDER_STATE_NONE;
322
323         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
324
325         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
326         mmf_return_val_if_fail(sc && sc->info_image && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
327
328         _mmcam_dbg_log("");
329
330         info = sc->info_image;
331
332         if (info->capturing) {
333                 _mmcam_dbg_err("already capturing");
334                 return MM_ERROR_CAMCORDER_DEVICE_BUSY;
335         }
336
337         _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
338                 CONFIGURE_CATEGORY_MAIN_CAPTURE,
339                 "UseCaptureMode",
340                 &UseCaptureMode);
341
342         _mmcamcorder_conf_get_element(handle, hcamcorder->conf_main,
343                 CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
344                 "VideosrcElement",
345                 &VideosrcElement);
346
347         _mmcamcorder_conf_get_value_element_name(VideosrcElement, &videosrc_name);
348
349         /* get current state */
350         mm_camcorder_get_state(handle, &current_state);
351
352         /* set capture flag */
353         info->capturing = TRUE;
354
355         ret = mm_camcorder_get_attributes(handle, &err_name,
356                 MMCAM_IMAGE_ENCODER, &image_encoder,
357                 MMCAM_CAMERA_WIDTH, &width,
358                 MMCAM_CAMERA_HEIGHT, &height,
359                 MMCAM_CAMERA_FPS, &fps,
360                 MMCAM_CAPTURE_FORMAT, &cap_format,
361                 MMCAM_CAPTURE_WIDTH, &info->width,
362                 MMCAM_CAPTURE_HEIGHT, &info->height,
363                 MMCAM_CAPTURE_COUNT, &info->count,
364                 MMCAM_CAPTURE_INTERVAL, &info->interval,
365                 MMCAM_STROBE_MODE, &strobe_mode,
366                 MMCAM_TAG_ORIENTATION, &tag_orientation,
367                 NULL);
368         if (err_name) {
369                 _mmcam_dbg_warn("get_attributes err %s, ret 0x%x", err_name, ret);
370                 SAFE_FREE(err_name);
371         }
372
373         ret = MM_ERROR_NONE;
374
375         /* check capture count */
376         if (info->count < 1) {
377                 _mmcam_dbg_err("capture count[%d] is invalid", info->count);
378                 ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
379                 goto cmd_done;
380         } else if (info->count == 1) {
381                 info->type = _MMCamcorder_SINGLE_SHOT;
382         } else {
383                 info->type = _MMCamcorder_MULTI_SHOT;
384                 info->next_shot_time = 0;
385                 info->multi_shot_stop = FALSE;
386
387                 /* sound init */
388                 _mmcamcorder_sound_init(handle);
389         }
390
391         _mmcam_dbg_log("preview(%dx%d,fmt:%d), capture(%dx%d,fmt:%d), count(%d), hdr mode(%d), interval (%d)",
392                 width, height, info->preview_format, info->width, info->height, cap_format,
393                 info->count, info->hdr_capture_mode, info->interval);
394
395         /* check state */
396         if (current_state >= MM_CAMCORDER_STATE_RECORDING) {
397                 if (sc->bencbin_capture) {
398                         _mmcam_dbg_err("could not capture in this target while recording");
399                         ret = MM_ERROR_CAMCORDER_INVALID_STATE;
400                         goto cmd_done;
401                 }
402
403                 if (info->type == _MMCamcorder_MULTI_SHOT ||
404                     info->hdr_capture_mode != MM_CAMCORDER_HDR_OFF) {
405                         _mmcam_dbg_err("does not support multi/HDR capture while recording");
406                         ret = MM_ERROR_CAMCORDER_INVALID_STATE;
407                         goto cmd_done;
408                 }
409
410                 /* check capture size if ZSL is not supported*/
411                 if (hcamcorder->support_zsl_capture == FALSE) {
412                         _mmcam_dbg_warn("Capture size should be same with preview size while recording");
413                         _mmcam_dbg_warn("Capture size %dx%d -> %dx%d", info->width, info->height, width, height);
414
415                         info->width = width;
416                         info->height = height;
417
418                         _mmcam_dbg_log("set capture width and height [%dx%d] to camera plugin", width, height);
419                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-width", width);
420                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-height", height);
421
422                         is_modified_size = TRUE;
423                 }
424         }
425
426         info->capture_cur_count = 0;
427         info->capture_send_count = 0;
428
429         sc->internal_encode = FALSE;
430
431         if (!sc->bencbin_capture) {
432                 /* Check encoding method */
433                 if (cap_format == MM_PIXEL_FORMAT_ENCODED) {
434                         if ((sc->SensorEncodedCapture && info->type == _MMCamcorder_SINGLE_SHOT) ||
435                             hcamcorder->support_zsl_capture || is_modified_size) {
436                                 cap_fourcc = _mmcamcorder_get_fourcc(cap_format, image_encoder, hcamcorder->use_zero_copy_format);
437                                 _mmcam_dbg_log("Sensor JPEG Capture [is_modified_size:%d]", is_modified_size);
438                         } else {
439                                 /* no need to encode internally if ITLV format */
440                                 if (info->preview_format != MM_PIXEL_FORMAT_ITLV_JPEG_UYVY)
441                                         sc->internal_encode = TRUE;
442
443                                 cap_fourcc = _mmcamcorder_get_fourcc(info->preview_format, image_encoder, hcamcorder->use_zero_copy_format);
444
445                                 _mmcam_dbg_log("MSL JPEG Capture : capture fourcc %c%c%c%c",
446                                         cap_fourcc, cap_fourcc>>8, cap_fourcc>>16, cap_fourcc>>24);
447                         }
448                 } else {
449                         cap_fourcc = _mmcamcorder_get_fourcc(cap_format, MM_IMAGE_CODEC_INVALID, hcamcorder->use_zero_copy_format);
450                 }
451
452                 _mmcam_dbg_log("capture format (%d)", cap_format);
453
454                 /* Note: width/height of capture is set in commit function of attribute or in create function of pipeline */
455                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-fourcc", cap_fourcc);
456                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-interval", info->interval);
457                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-count", info->count);
458
459                 if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
460                         _mmcam_dbg_err("Can't cast Video source into camera control.");
461                         ret = MM_ERROR_CAMCORDER_NOT_SUPPORTED;
462                         goto cmd_done;
463                 }
464
465                 control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
466                 gst_camera_control_set_capture_command(control, GST_CAMERA_CONTROL_CAPTURE_COMMAND_START);
467         } else {
468                 int need_change = 0;
469                 int set_width = 0;
470                 int set_height = 0;
471                 int cap_jpeg_quality = 0;
472
473                 if (UseCaptureMode) {
474                         if (width != MMFCAMCORDER_HIGHQUALITY_WIDTH || height != MMFCAMCORDER_HIGHQUALITY_HEIGHT)
475                                 need_change = 1;
476                 } else {
477                         if (width != info->width || height != info->height)
478                                 need_change = 1;
479                 }
480
481                 if (need_change) {
482                         int rotation = 0;
483
484                         _mmcam_dbg_log("Need to change resolution");
485
486                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
487                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
488
489                         /* make pipeline state as READY */
490                         ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY);
491
492                         /* check decoder recreation */
493                         if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
494                                 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
495                                 return MM_ERROR_CAMCORDER_INTERNAL;
496                         }
497
498                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
499                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
500
501                         if (ret != MM_ERROR_NONE) {
502                                 _mmcam_dbg_err("failed to set state PAUSED %x", ret);
503                                 goto cmd_done;
504                         }
505
506                         if (UseCaptureMode) {
507                                 set_width = MMFCAMCORDER_HIGHQUALITY_WIDTH;
508                                 set_height = MMFCAMCORDER_HIGHQUALITY_HEIGHT;
509                         } else {
510                                 set_width = info->width;
511                                 set_height = info->height;
512                         }
513
514                         mm_camcorder_get_attributes(handle, &err_name,
515                                 MMCAM_CAMERA_ROTATION, &rotation,
516                                 NULL);
517                         if (err_name) {
518                                 _mmcam_dbg_warn("get_attributes err %s", err_name);
519                                 SAFE_FREE(err_name);
520                         }
521
522                         /* set new caps */
523                         ret = _mmcamcorder_set_videosrc_caps(handle, sc->fourcc, set_width, set_height, fps, rotation);
524                         if (!ret) {
525                                 _mmcam_dbg_err("_mmcamcorder_set_videosrc_caps failed");
526                                 ret = MM_ERROR_CAMCORDER_INTERNAL;
527                                 goto cmd_done;
528                         }
529
530                         info->resolution_change = TRUE;
531
532                         /* set frame stability count for capture */
533                         _mmcamcorder_video_frame_stabilize(handle, _MMCamcorder_CMD_CAPTURE);
534
535                         /* make pipeline state as PLAYING */
536                         ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_PLAYING);
537                         if (ret != MM_ERROR_NONE) {
538                                 _mmcam_dbg_err("failed to set state PLAYING %x", ret);
539                                 goto cmd_done;
540                         }
541
542                         _mmcam_dbg_log("Change to target resolution(%d, %d)", set_width, set_height);
543                 } else {
544                         _mmcam_dbg_log("No need to change resolution. Open toggle now.");
545                         info->resolution_change = FALSE;
546                 }
547
548                 /* add encodesinkbin */
549                 ret = _mmcamcorder_create_stillshot_pipeline((MMHandleType)hcamcorder);
550                 if (ret != MM_ERROR_NONE) {
551                         _mmcam_dbg_err("failed to create encodesinkbin %x", ret);
552                         goto cmd_done;
553                 }
554
555                 ret = mm_camcorder_get_attributes(handle, &err_name,
556                         MMCAM_IMAGE_ENCODER_QUALITY, &cap_jpeg_quality,
557                         NULL);
558                 if (err_name) {
559                         _mmcam_dbg_warn("get_attributes err %s, ret 0x%x", err_name, ret);
560                         SAFE_FREE(err_name);
561                 }
562
563                 /* set JPEG quality */
564                 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_IENC].gst, "quality", cap_jpeg_quality);
565
566                 /* set handoff signal as TRUE */
567                 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "signal-handoffs", TRUE);
568                 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
569
570                 /* Prepare for the shutter sound when it's the bencbin mode capture */
571                 sc->info_video->is_firstframe = TRUE;
572
573                 /* set push encoding buffer as TRUE */
574                 sc->info_video->push_encoding_buffer = PUSH_ENCODING_BUFFER_INIT;
575
576                 /* make encode pipeline state as PLAYING */
577                 ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PLAYING);
578                 if (ret != MM_ERROR_NONE) {
579                         _mmcam_dbg_err("failed to set state PLAYING %x", ret);
580                         goto cmd_done;
581                 }
582         }
583
584         /* Play capture sound here if single capture */
585         if ((info->type == _MMCamcorder_SINGLE_SHOT &&
586              (hcamcorder->support_zsl_capture == FALSE ||
587               strobe_mode == MM_CAMCORDER_STROBE_MODE_OFF)) ||
588             info->hdr_capture_mode) {
589                 if (current_state < MM_CAMCORDER_STATE_RECORDING &&
590                     hcamcorder->support_zsl_capture == TRUE &&
591                     !info->hdr_capture_mode) {
592                         _mmcamcorder_sound_solo_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_CAPTURE01, FALSE);
593                 }
594
595                 /* set flag */
596                 info->played_capture_sound = TRUE;
597         } else {
598                 /* set flag */
599                 info->played_capture_sound = FALSE;
600         }
601
602 cmd_done:
603         if (ret != MM_ERROR_NONE) {
604                 info->capturing = FALSE;
605
606                 /* sound finalize */
607                 if (info->type == _MMCamcorder_MULTI_SHOT)
608                         _mmcamcorder_sound_finalize(handle);
609
610                 /* send signal for task thread : It prevent unnecessary invalid operation error in task thread */
611                 if (hcamcorder->capture_in_recording) {
612                         hcamcorder->capture_in_recording = FALSE;
613
614                         g_mutex_lock(&hcamcorder->task_thread_lock);
615
616                         if (hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_CHECK_CAPTURE_IN_RECORDING) {
617                                 hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_NONE;
618                                 _mmcam_dbg_log("send signal for capture in recording");
619                                 g_cond_signal(&hcamcorder->task_thread_cond);
620                         } else {
621                                 _mmcam_dbg_warn("unexpected task thread state : %d", hcamcorder->task_thread_state);
622                         }
623
624                         g_mutex_unlock(&hcamcorder->task_thread_lock);
625                 }
626         }
627
628         return ret;
629 }
630
631
632 int _mmcamcorder_image_cmd_preview_start(MMHandleType handle)
633 {
634         int ret = MM_ERROR_NONE;
635         int width = 0;
636         int height = 0;
637         int fps = 0;
638         int rotation = 0;
639         unsigned int current_framecount = 0;
640         int current_state = MM_CAMCORDER_STATE_NONE;
641         gboolean fps_auto = FALSE;
642         char *err_name = NULL;
643         const char *videosrc_name = NULL;
644
645         GstState state;
646         GstElement *pipeline = NULL;
647         GstCameraControl *control = NULL;
648
649         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
650         _MMCamcorderImageInfo *info = NULL;
651         _MMCamcorderSubContext *sc = NULL;
652         type_element *VideosrcElement = NULL;
653
654         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
655
656         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
657         mmf_return_val_if_fail(sc && sc->info_image && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
658
659         /*_mmcam_dbg_log("");*/
660
661         pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
662         info = sc->info_image;
663
664         _mmcamcorder_conf_get_element(handle, hcamcorder->conf_main,
665                 CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
666                 "VideosrcElement",
667                 &VideosrcElement);
668
669         _mmcamcorder_conf_get_value_element_name(VideosrcElement, &videosrc_name);
670
671         sc->display_interval = 0;
672         sc->previous_slot_time = 0;
673
674         /* Image info */
675         info->next_shot_time = 0;
676         info->multi_shot_stop = TRUE;
677         info->capturing = FALSE;
678
679         current_state = _mmcamcorder_get_state(handle);
680         _mmcam_dbg_log("current state [%d]", current_state);
681
682         if (!sc->bencbin_capture) {
683                 _mmcam_dbg_log("Preview start");
684
685                 /* just set capture stop command if current state is CAPTURING */
686                 if (current_state == MM_CAMCORDER_STATE_CAPTURING) {
687                         if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
688                                 _mmcam_dbg_err("Can't cast Video source into camera control.");
689                                 return MM_ERROR_CAMCORDER_NOT_SUPPORTED;
690                         }
691
692                         control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
693                         gst_camera_control_set_capture_command(control, GST_CAMERA_CONTROL_CAPTURE_COMMAND_STOP);
694
695                         current_framecount = sc->kpi.video_framecount;
696                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
697                         if (info->type == _MMCamcorder_SINGLE_SHOT) {
698                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
699                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
700                         }
701                 } else {
702                         int focus_mode = 0;
703                         mmf_attrs_t *attr = (mmf_attrs_t *)MMF_CAMCORDER_ATTRS(handle);
704
705                         /* This case is starting of preview */
706                         ret = mm_camcorder_get_attributes(handle, &err_name,
707                                 MMCAM_CAMERA_FPS_AUTO, &fps_auto,
708                                 MMCAM_CAMERA_FOCUS_MODE, &focus_mode,
709                                 NULL);
710                         if (ret != MM_ERROR_NONE) {
711                                 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, ret);
712                                 SAFE_FREE(err_name);
713                         }
714
715                         _mmcam_dbg_log("focus mode %d", focus_mode);
716
717                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "fps-auto", fps_auto);
718
719                         /* set focus mode */
720                         if (attr) {
721                                 if (_mmcamcorder_check_supported_attribute(handle, MM_CAM_CAMERA_FOCUS_MODE)) {
722                                         mmf_attribute_set_modified(&(attr->items[MM_CAM_CAMERA_FOCUS_MODE]));
723                                         mmf_attrs_commit((MMHandleType)attr);
724                                 } else {
725                                         _mmcam_dbg_log("focus mode is not supported");
726                                 }
727                         } else {
728                                 _mmcam_dbg_err("failed to get attributes");
729                         }
730                 }
731         }
732
733         /* init prev_time */
734         sc->info_video->prev_preview_ts = 0;
735
736         gst_element_get_state(pipeline, &state, NULL, -1);
737
738         if (state == GST_STATE_PLAYING) {
739                 if (!sc->bencbin_capture) {
740                         int try_count = 0;
741
742                         if (hcamcorder->support_zsl_capture == FALSE) {
743                                 mmf_attrs_t *attr = (mmf_attrs_t *)MMF_CAMCORDER_ATTRS(handle);
744
745                                 /* Set strobe mode - strobe mode can not be set to driver while captuing */
746                                 if (attr) {
747                                         mmf_attribute_set_modified(&(attr->items[MM_CAM_STROBE_MODE]));
748                                         if (mmf_attrs_commit((MMHandleType) attr) == -1)
749                                                 _mmcam_dbg_warn("Failed to set strobe mode");
750                                 }
751
752                                 while (current_framecount >= sc->kpi.video_framecount &&
753                                         try_count++ < _MMCAMCORDER_CAPTURE_STOP_CHECK_COUNT) {
754                                         usleep(_MMCAMCORDER_CAPTURE_STOP_CHECK_INTERVAL);
755                                 }
756                         }
757
758                         if (info->type == _MMCamcorder_MULTI_SHOT) {
759                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
760                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
761                         }
762
763                         _mmcam_dbg_log("Wait Frame Done. count before[%d],after[%d], try_count[%d]",
764                                 current_framecount, sc->kpi.video_framecount, try_count);
765                 } else {
766                         ret = _mmcamcorder_remove_stillshot_pipeline(handle);
767                         if (ret != MM_ERROR_NONE)
768                                 goto cmd_error;
769
770                         if (info->resolution_change) {
771                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
772                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
773
774                                 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
775
776                                 /* check decoder recreation */
777                                 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
778                                         _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
779                                         return MM_ERROR_CAMCORDER_INTERNAL;
780                                 }
781
782                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
783                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
784
785                                 if (ret != MM_ERROR_NONE)
786                                         goto cmd_error;
787
788                                 /* check if resolution need to rollback */
789                                 mm_camcorder_get_attributes(handle, &err_name,
790                                         MMCAM_CAMERA_WIDTH, &width,
791                                         MMCAM_CAMERA_HEIGHT, &height,
792                                         MMCAM_CAMERA_FPS, &fps,
793                                         MMCAM_CAMERA_ROTATION, &rotation,
794                                         NULL);
795                                 if (err_name) {
796                                         _mmcam_dbg_warn("get_attributes err %s, ret 0x%x", err_name, ret);
797                                         SAFE_FREE(err_name);
798                                 }
799
800                                 /* set new caps */
801                                 ret = _mmcamcorder_set_videosrc_caps(handle, sc->fourcc, width, height, fps, rotation);
802                                 if (!ret) {
803                                         _mmcam_dbg_err("_mmcamcorder_set_videosrc_caps failed");
804                                         ret = MM_ERROR_CAMCORDER_INTERNAL;
805                                         goto cmd_error;
806                                 }
807
808                                 /* set frame stability count for preview */
809                                 _mmcamcorder_video_frame_stabilize(handle, _MMCamcorder_CMD_PREVIEW_START);
810
811                                 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
812                                 if (ret != MM_ERROR_NONE)
813                                         goto cmd_error;
814                         }
815                 }
816
817                 /* sound finalize */
818                 if (info->type == _MMCamcorder_MULTI_SHOT)
819                         _mmcamcorder_sound_finalize(handle);
820         } else {
821                 if (info->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) {
822                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "bitrate", H264_PREVIEW_BITRATE);
823                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "newgop-interval", H264_PREVIEW_NEWGOP_INTERVAL);
824                 }
825
826                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
827                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
828
829                 /* set frame stability count for preview */
830                 _mmcamcorder_video_frame_stabilize(handle, _MMCamcorder_CMD_PREVIEW_START);
831
832                 traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:START:SET_PLAYING_TO_PIPELINE");
833
834                 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
835
836                 traceEnd(TTRACE_TAG_CAMERA);
837
838                 if (ret != MM_ERROR_NONE)
839                         goto cmd_error;
840
841                 /* get sound status/volume level and register changed_cb */
842                 if (hcamcorder->shutter_sound_policy == VCONFKEY_CAMERA_SHUTTER_SOUND_POLICY_OFF &&
843                     info->sound_status == _SOUND_STATUS_INIT) {
844                         _mmcam_dbg_log("register vconf changed_cb and get sound status");
845
846                         /* register changed_cb */
847                         vconf_notify_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, __sound_status_changed_cb, hcamcorder);
848
849                         /* get sound status */
850                         vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &(info->sound_status));
851
852                         _mmcam_dbg_log("sound status %d", info->sound_status);
853                 }
854         }
855
856 cmd_error:
857         return ret;
858 }
859
860
861 int _mmcamcorder_image_cmd_preview_stop(MMHandleType handle)
862 {
863         int ret = MM_ERROR_NONE;
864         int strobe_mode = MM_CAMCORDER_STROBE_MODE_OFF;
865         int set_strobe = 0;
866         int display_reuse_hint = FALSE;
867         GstCameraControl *control = NULL;
868         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
869
870         GstElement *pipeline = NULL;
871
872         _MMCamcorderSubContext *sc = NULL;
873
874         _mmcam_dbg_log("");
875
876         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
877
878         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
879         mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
880
881         /* check strobe and set OFF if PERMANENT mode */
882         mm_camcorder_get_attributes(handle, NULL,
883                 MMCAM_STROBE_MODE, &strobe_mode,
884                 NULL);
885         if (strobe_mode == MM_CAMCORDER_STROBE_MODE_PERMANENT &&
886             GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
887                 _mmcam_dbg_log("current strobe mode is PERMANENT, set OFF");
888
889                 /* get camera control */
890                 control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
891                 if (control) {
892                         /* convert MSL to sensor value */
893                         set_strobe = _mmcamcorder_convert_msl_to_sensor(handle, MM_CAM_STROBE_MODE, MM_CAMCORDER_STROBE_MODE_OFF);
894
895                         /* set strobe OFF */
896                         gst_camera_control_set_strobe(control, GST_CAMERA_CONTROL_STROBE_MODE, set_strobe);
897
898                         _mmcam_dbg_log("set strobe OFF done - value: %d", set_strobe);
899                 } else {
900                         _mmcam_dbg_warn("cast CAMERA_CONTROL failed");
901                 }
902         }
903
904         pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
905
906         if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst) {
907                 _mmcam_dbg_log("pipeline is exist so need to remove pipeline and sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst=%p",
908                         sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst);
909                 _mmcamcorder_remove_recorder_pipeline(handle);
910         }
911
912         mm_camcorder_get_attributes(handle, NULL,
913                 MMCAM_DISPLAY_REUSE_HINT, &display_reuse_hint,
914                 NULL);
915
916         _mmcam_dbg_log("display reuse hint %d", display_reuse_hint);
917
918         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", display_reuse_hint);
919
920         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
921         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
922
923         traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:STOP:SET_READY_TO_PIPELINE");
924
925         ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
926
927         traceEnd(TTRACE_TAG_CAMERA);
928
929         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
930         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
931
932         if (display_reuse_hint)
933                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
934
935         /* deregister sound status callback */
936         if (sc->info_image->sound_status != _SOUND_STATUS_INIT) {
937                 _mmcam_dbg_log("deregister sound status callback");
938
939                 vconf_ignore_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, __sound_status_changed_cb);
940
941                 sc->info_image->sound_status = _SOUND_STATUS_INIT;
942         }
943
944         return ret;
945 }
946
947
948 int _mmcamcorder_video_capture_command(MMHandleType handle, int command)
949 {
950         int ret = MM_ERROR_NONE;
951
952         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
953         _MMCamcorderSubContext *sc = NULL;
954
955         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
956
957         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
958         mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
959
960         _mmcam_dbg_log("command %d", command);
961
962         switch (command) {
963         case _MMCamcorder_CMD_CAPTURE:
964                 ret = _mmcamcorder_image_cmd_capture(handle);
965                 break;
966         case _MMCamcorder_CMD_PREVIEW_START:
967                 ret = _mmcamcorder_image_cmd_preview_start(handle);
968
969                 /* I place this function last because it miscalculates a buffer that sents in GST_STATE_PAUSED */
970                 _mmcamcorder_video_current_framerate_init(handle);
971                 break;
972         case _MMCamcorder_CMD_PREVIEW_STOP:
973                 ret = _mmcamcorder_image_cmd_preview_stop(handle);
974                 break;
975         case _MMCamcorder_CMD_RECORD:
976         case _MMCamcorder_CMD_PAUSE:
977         case _MMCamcorder_CMD_CANCEL:
978         case _MMCamcorder_CMD_COMMIT:
979                 /* video recording command */
980                 ret = _mmcamcorder_video_command(handle, command);
981                 break;
982         default:
983                 ret =  MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
984                 break;
985         }
986
987         return ret;
988 }
989
990
991 void __mmcamcorder_init_stillshot_info(MMHandleType handle)
992 {
993         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
994         _MMCamcorderSubContext *sc = NULL;
995         _MMCamcorderImageInfo *info = NULL;
996
997         mmf_return_if_fail(hcamcorder);
998
999         sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1000         mmf_return_if_fail(sc && sc->info_image);
1001
1002         info = sc->info_image;
1003
1004         _mmcam_dbg_log("capture type[%d], capture send count[%d]", info->type, info->capture_send_count);
1005
1006         if (info->type == _MMCamcorder_SINGLE_SHOT || info->capture_send_count == info->count) {
1007                 info->capture_cur_count = 0;
1008                 info->capture_send_count = 0;
1009                 info->multi_shot_stop = TRUE;
1010                 info->next_shot_time = 0;
1011
1012                 /* capturing flag set to FALSE here */
1013                 info->capturing = FALSE;
1014         }
1015
1016         return;
1017 }
1018
1019
1020 int __mmcamcorder_capture_save_exifinfo(MMHandleType handle, MMCamcorderCaptureDataType *original, MMCamcorderCaptureDataType *thumbnail, int provide_exif)
1021 {
1022         int ret = MM_ERROR_NONE;
1023         unsigned char *data = NULL;
1024         unsigned int datalen = 0;
1025         _MMCamcorderSubContext *sc = NULL;
1026         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1027
1028         mmf_return_val_if_fail(hcamcorder, FALSE);
1029         sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1030         mmf_return_val_if_fail(sc, FALSE);
1031
1032         _mmcam_dbg_log("");
1033
1034         if (!original || original->data == NULL || original->length == 0) {
1035                 if (original) {
1036                         _mmcam_dbg_err("data=%p, length=%d",
1037                                 original->data, original->length);
1038                 } else {
1039                         _mmcam_dbg_err("original is null");
1040                 }
1041
1042                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
1043         } else {
1044                 /* original is input/output param. save original values to local var. */
1045                 data = original->data;
1046                 datalen = original->length;
1047         }
1048
1049         if (provide_exif == FALSE) {
1050                 if (thumbnail) {
1051                         if (thumbnail->data && thumbnail->length > 0) {
1052                                 _mmcam_dbg_log("thumbnail is added!thumbnail->data=%p thumbnail->width=%d ,thumbnail->height=%d",
1053                                         thumbnail->data, thumbnail->width, thumbnail->height);
1054
1055                                 /* add thumbnail exif info */
1056                                 ret = mm_exif_add_thumbnail_info(hcamcorder->exif_info,
1057                                         thumbnail->data,
1058                                         thumbnail->width,
1059                                         thumbnail->height,
1060                                         thumbnail->length);
1061                         } else {
1062                                 _mmcam_dbg_err("Skip adding thumbnail (data=%p, length=%d)",
1063                                         thumbnail->data, thumbnail->length);
1064                         }
1065                 }
1066         } else {
1067                 ret = MM_ERROR_NONE;
1068         }
1069
1070         if (ret == MM_ERROR_NONE) {
1071                 /* write jpeg with exif */
1072                 ret = mm_exif_write_exif_jpeg_to_memory(&original->data, &original->length, hcamcorder->exif_info, data, datalen);
1073                 if (ret != MM_ERROR_NONE)
1074                         _mmcam_dbg_err("mm_exif_write_exif_jpeg_to_memory error! [0x%x]", ret);
1075         }
1076
1077         _mmcam_dbg_log("END ret 0x%x", ret);
1078
1079         return ret;
1080 }
1081
1082
1083 void __mmcamcorder_get_capture_data_from_buffer(MMCamcorderCaptureDataType *capture_data, int pixtype, GstSample *sample)
1084 {
1085         GstCaps *caps = NULL;
1086         GstMapInfo mapinfo;
1087         const GstStructure *structure;
1088
1089         mmf_return_if_fail(capture_data && sample);
1090
1091         caps = gst_sample_get_caps(sample);
1092         if (caps == NULL) {
1093                 _mmcam_dbg_err("failed to get caps");
1094                 goto GET_FAILED;
1095         }
1096
1097         structure = gst_caps_get_structure(caps, 0);
1098         if (structure == NULL) {
1099                 _mmcam_dbg_err("failed to get structure");
1100                 goto GET_FAILED;
1101         }
1102
1103         memset(&mapinfo, 0x0, sizeof(GstMapInfo));
1104
1105         gst_buffer_map(gst_sample_get_buffer(sample), &mapinfo, GST_MAP_READ);
1106         capture_data->data = mapinfo.data;
1107         capture_data->format = pixtype;
1108         gst_structure_get_int(structure, "width", &capture_data->width);
1109         gst_structure_get_int(structure, "height", &capture_data->height);
1110         capture_data->length = mapinfo.size;
1111         gst_buffer_unmap(gst_sample_get_buffer(sample), &mapinfo);
1112
1113         _mmcam_dbg_warn("buffer data[%p],size[%dx%d],length[%d],format[%d]",
1114                 capture_data->data, capture_data->width, capture_data->height,
1115                 capture_data->length, capture_data->format);
1116         return;
1117
1118 GET_FAILED:
1119         capture_data->data = NULL;
1120         capture_data->format = MM_PIXEL_FORMAT_INVALID;
1121         capture_data->length = 0;
1122
1123         return;
1124 }
1125
1126
1127 int __mmcamcorder_set_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, MMCamcorderCaptureDataType *thumbnail, int provide_exif)
1128 {
1129         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1130         _MMCamcorderSubContext *sc = NULL;
1131
1132         mmf_return_val_if_fail(hcamcorder && dest, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
1133
1134         sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1135         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1136
1137         _mmcam_dbg_log("");
1138
1139         /* if tag enable and doesn't provide exif, we make it */
1140         _mmcam_dbg_log("Add exif information if existed(thumbnail[%p])", thumbnail);
1141         if (thumbnail && thumbnail->data)
1142                 return __mmcamcorder_capture_save_exifinfo(handle, dest, thumbnail, provide_exif);
1143         else
1144                 return __mmcamcorder_capture_save_exifinfo(handle, dest, NULL, provide_exif);
1145 }
1146
1147
1148 void __mmcamcorder_release_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, int tag_enable, int provide_exif)
1149 {
1150         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1151         _MMCamcorderSubContext *sc = NULL;
1152
1153         mmf_return_if_fail(hcamcorder);
1154         mmf_return_if_fail(dest);
1155
1156         sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1157         mmf_return_if_fail(sc);
1158
1159         _mmcam_dbg_log("tag : %d, provide exif : %d", tag_enable, provide_exif);
1160
1161         /* if dest->data is allocated in MSL, release it */
1162         if (tag_enable && !provide_exif) {
1163                 if (dest->data) {
1164                         free(dest->data);
1165                         dest->length = 0;
1166                         dest->data = NULL;
1167                         _mmcam_dbg_log("Jpeg is released!");
1168                 }
1169         } else {
1170                 _mmcam_dbg_log("No need to release");
1171         }
1172
1173         return;
1174 }
1175
1176
1177 static void __mmcamcorder_image_capture_cb(GstElement *element, GstSample *sample1, GstSample *sample2, GstSample *sample3, gpointer u_data)
1178 {
1179         int ret = MM_ERROR_NONE;
1180         int pixtype_main = MM_PIXEL_FORMAT_INVALID;
1181         int pixtype_thumb = MM_PIXEL_FORMAT_INVALID;
1182         int pixtype_scrnl = MM_PIXEL_FORMAT_INVALID;
1183         int codectype = MM_IMAGE_CODEC_JPEG;
1184         int attr_index = 0;
1185         int count = 0;
1186         int stop_cont_shot = FALSE;
1187         int tag_enable = FALSE;
1188         int provide_exif = FALSE;
1189         int capture_quality = 0;
1190         int try_lock_count = 0;
1191         gboolean send_captured_message = FALSE;
1192         unsigned char *exif_raw_data = NULL;
1193         unsigned char *internal_main_data = NULL;
1194         unsigned int internal_main_length = 0;
1195         unsigned char *internal_thumb_data = NULL;
1196         unsigned int internal_thumb_length = 0;
1197         unsigned char *compare_data = NULL;
1198
1199         MMCamcorderStateType current_state = MM_CAMCORDER_STATE_NONE;
1200         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1201         _MMCamcorderImageInfo *info = NULL;
1202         _MMCamcorderSubContext *sc = NULL;
1203         MMCamcorderCaptureDataType dest = {0,};
1204         MMCamcorderCaptureDataType thumb = {0,};
1205         MMCamcorderCaptureDataType scrnail = {0,};
1206         MMCamcorderCaptureDataType encode_src = {0,};
1207         GstMapInfo mapinfo1;
1208         GstMapInfo mapinfo2;
1209         GstMapInfo mapinfo3;
1210
1211         mmf_attrs_t *attrs = NULL;
1212         mmf_attribute_t *item_screennail = NULL;
1213         mmf_attribute_t *item_exif_raw_data = NULL;
1214
1215         mmf_return_if_fail(hcamcorder);
1216
1217         sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1218         mmf_return_if_fail(sc && sc->info_image);
1219
1220         info = sc->info_image;
1221
1222         memset(&mapinfo1, 0x0, sizeof(GstMapInfo));
1223         memset(&mapinfo2, 0x0, sizeof(GstMapInfo));
1224         memset(&mapinfo3, 0x0, sizeof(GstMapInfo));
1225
1226         /* get current state */
1227         current_state = _mmcamcorder_get_state((MMHandleType)hcamcorder);
1228
1229         _mmcam_dbg_err("START - current state %d", current_state);
1230
1231         /* check capture state */
1232         if (info->type == _MMCamcorder_MULTI_SHOT && info->capture_send_count > 0)
1233                 mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
1234                         MMCAM_CAPTURE_BREAK_CONTINUOUS_SHOT, &stop_cont_shot,
1235                         NULL);
1236
1237         if (!info->capturing || stop_cont_shot) {
1238                 _mmcam_dbg_warn("stop command[%d] or not capturing state[%d]. skip this...", stop_cont_shot, info->capturing);
1239
1240                 /* set FALSE here for the case that info->capturing is still FALSE
1241                         (== capture_send_count is 0 at the time _mmcamcorder_commit_capture_break_cont_shot is called) */
1242                 info->capturing = FALSE;
1243
1244                 /*free GstBuffer*/
1245                 if (sample1)
1246                         gst_sample_unref(sample1);
1247
1248                 if (sample2)
1249                         gst_sample_unref(sample2);
1250
1251                 if (sample3)
1252                         gst_sample_unref(sample3);
1253
1254                 return;
1255         }
1256
1257         /* check command lock to block capture callback if capture start API is not returned
1258            wait for 2 seconds at worst case */
1259         try_lock_count = 0;
1260         do {
1261                 _mmcam_dbg_log("Try command LOCK");
1262                 if (_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
1263                         _mmcam_dbg_log("command LOCK OK");
1264                         _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
1265                         break;
1266                 }
1267
1268                 if (try_lock_count++ < TRY_LOCK_MAX_COUNT) {
1269                         _mmcam_dbg_warn("command LOCK Failed, retry...[count %d]", try_lock_count);
1270                         usleep(TRY_LOCK_TIME);
1271                 } else {
1272                         _mmcam_dbg_err("failed to lock command LOCK");
1273                         break;
1274                 }
1275         } while (TRUE);
1276
1277         if (current_state < MM_CAMCORDER_STATE_RECORDING) {
1278                 /* play capture sound here if multi capture
1279                    or preview format is ITLV(because of AF and flash control in plugin) */
1280                 if (info->type == _MMCamcorder_MULTI_SHOT) {
1281                         g_mutex_lock(&hcamcorder->task_thread_lock);
1282                         _mmcam_dbg_log("send signal for sound play");
1283                         hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_SOUND_PLAY_START;
1284                         g_cond_signal(&hcamcorder->task_thread_cond);
1285                         g_mutex_unlock(&hcamcorder->task_thread_lock);
1286                 } else if (!info->played_capture_sound) {
1287                         _mmcamcorder_sound_solo_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_CAPTURE01, FALSE);
1288                 }
1289         }
1290
1291         /* init capture data */
1292         memset((void *)&dest, 0x0, sizeof(MMCamcorderCaptureDataType));
1293         memset((void *)&thumb, 0x0, sizeof(MMCamcorderCaptureDataType));
1294         memset((void *)&scrnail, 0x0, sizeof(MMCamcorderCaptureDataType));
1295
1296         /* Prepare main, thumbnail buffer */
1297         pixtype_main = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample1));
1298         if (pixtype_main == MM_PIXEL_FORMAT_INVALID) {
1299                 _mmcam_dbg_err("Unsupported pixel type");
1300                 MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INTERNAL);
1301                 goto error;
1302         }
1303
1304         /* Main image buffer */
1305         if (!sample1 || !gst_buffer_map(gst_sample_get_buffer(sample1), &mapinfo1, GST_MAP_READ)) {
1306                 _mmcam_dbg_err("sample1[%p] is NULL or gst_buffer_map failed", sample1);
1307                 MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INTERNAL);
1308                 goto error;
1309         } else {
1310                 if ((mapinfo1.data == NULL) && (mapinfo1.size == 0)) {
1311                         _mmcam_dbg_err("mapinfo1 is wrong (%p, size %d)", mapinfo1.data, mapinfo1.size);
1312                         MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INTERNAL);
1313                         gst_buffer_unmap(gst_sample_get_buffer(sample1), &mapinfo1);
1314                         goto error;
1315                 } else {
1316                         __mmcamcorder_get_capture_data_from_buffer(&dest, pixtype_main, sample1);
1317                 }
1318         }
1319
1320         if (!sample2 || !gst_buffer_map(gst_sample_get_buffer(sample2), &mapinfo2, GST_MAP_READ))
1321                 _mmcam_dbg_log("sample2[%p] is NULL or gst_buffer_map failed. Not Error.", sample2);
1322
1323         if (!sample3 || !gst_buffer_map(gst_sample_get_buffer(sample3), &mapinfo3, GST_MAP_READ))
1324                 _mmcam_dbg_log("sample3[%p] is NULL or gst_buffer_map failed. Not Error.", sample3);
1325
1326         /* Screennail image buffer */
1327         attrs = (mmf_attrs_t *)MMF_CAMCORDER_ATTRS(hcamcorder);
1328         mm_attrs_get_index((MMHandleType)attrs, MMCAM_CAPTURED_SCREENNAIL, &attr_index);
1329         item_screennail = &attrs->items[attr_index];
1330
1331         if (sample3 && mapinfo3.data && mapinfo3.size != 0) {
1332                 _mmcam_dbg_log("Screennail (sample3=%p,size=%d)", sample3, mapinfo3.size);
1333
1334                 pixtype_scrnl = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample3));
1335                 __mmcamcorder_get_capture_data_from_buffer(&scrnail, pixtype_scrnl, sample3);
1336
1337                 /* Set screennail attribute for application */
1338                 ret = mmf_attribute_set_data(item_screennail, &scrnail, sizeof(scrnail));
1339                 _mmcam_dbg_log("Screennail set attribute data %p, size %d, ret %x", &scrnail, sizeof(scrnail), ret);
1340         } else {
1341                 _mmcam_dbg_log("Sample3 has wrong pointer. Not Error. (sample3=%p)", sample3);
1342                 mmf_attribute_set_data(item_screennail, NULL, 0);
1343         }
1344
1345         /* commit screennail data */
1346         mmf_attribute_commit(item_screennail);
1347
1348         /* init thumb data */
1349         memset(&encode_src, 0x0, sizeof(MMCamcorderCaptureDataType));
1350
1351         /* get provide-exif */
1352         MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "provide-exif", &provide_exif);
1353
1354         /* Thumbnail image buffer */
1355         if (sample2 && mapinfo2.data && (mapinfo2.size != 0)) {
1356                 _mmcam_dbg_log("Thumbnail (buffer2=%p)", gst_sample_get_buffer(sample2));
1357                 pixtype_thumb = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample2));
1358                 __mmcamcorder_get_capture_data_from_buffer(&thumb, pixtype_thumb, sample2);
1359         } else {
1360                 _mmcam_dbg_log("Sample2 has wrong pointer. Not Error. (sample2 %p)", sample2);
1361
1362                 if (pixtype_main == MM_PIXEL_FORMAT_ENCODED && provide_exif) {
1363                         ExifLoader *l;
1364                         /* get thumbnail from EXIF */
1365                         l = exif_loader_new();
1366                         if (l) {
1367                                 ExifData *ed;
1368                                 char  width[10];
1369                                 char  height[10];
1370                                 ExifEntry *entry = NULL;
1371
1372                                 exif_loader_write(l, dest.data, dest.length);
1373
1374                                 /* Get a pointer to the EXIF data */
1375                                 ed = exif_loader_get_data(l);
1376
1377                                 /* The loader is no longer needed--free it */
1378                                 exif_loader_unref(l);
1379                                 l = NULL;
1380                                 if (ed) {
1381                                         entry = exif_content_get_entry(ed->ifd[EXIF_IFD_1], EXIF_TAG_IMAGE_WIDTH);
1382                                         if (entry != NULL)
1383                                                 exif_entry_get_value(entry, width, 10);
1384
1385                                         entry = NULL;
1386                                         entry = exif_content_get_entry(ed->ifd[EXIF_IFD_1], EXIF_TAG_IMAGE_LENGTH);
1387                                         if (entry != NULL)
1388                                                 exif_entry_get_value(entry, height, 10);
1389
1390                                         entry = NULL;
1391                                         /* Make sure the image had a thumbnail before trying to write it */
1392                                         if (ed->data && ed->size) {
1393                                                 thumb.data = malloc(ed->size);
1394                                                 if (thumb.data) {
1395                                                         memcpy(thumb.data, ed->data, ed->size);
1396                                                         thumb.length = ed->size;
1397                                                         thumb.format = MM_PIXEL_FORMAT_ENCODED;
1398                                                         thumb.width = atoi(width);
1399                                                         thumb.height = atoi(height);
1400                                                         internal_thumb_data = thumb.data;
1401                                                 } else {
1402                                                         _mmcam_dbg_err("failed to alloc thumbnail data");
1403                                                 }
1404                                         }
1405                                         exif_data_unref(ed);
1406                                         ed = NULL;
1407                                 } else {
1408                                         _mmcam_dbg_warn("failed to get exif data");
1409                                 }
1410                         } else {
1411                                 _mmcam_dbg_warn("failed to create exif loader");
1412                         }
1413                 }
1414
1415                 if (thumb.data == NULL) {
1416                         if (pixtype_main == MM_PIXEL_FORMAT_ENCODED &&
1417                             scrnail.data && scrnail.length != 0) {
1418                                 /* make thumbnail image with screennail data */
1419                                 memcpy(&encode_src, &scrnail, sizeof(MMCamcorderCaptureDataType));
1420                         } else if (sc->internal_encode) {
1421                                 /* make thumbnail image with main data, this is raw data */
1422                                 memcpy(&encode_src, &dest, sizeof(MMCamcorderCaptureDataType));
1423                         }
1424                 }
1425
1426                 /* encode thumbnail */
1427                 if (encode_src.data) {
1428                         size_t thumb_length = 0;
1429                         unsigned int thumb_width = 0;
1430                         unsigned int thumb_height = 0;
1431                         unsigned char *thumb_raw_data = NULL;
1432
1433                         /* encode image */
1434                         _mmcam_dbg_log("Encode Thumbnail");
1435
1436                         if (encode_src.width > THUMBNAIL_WIDTH) {
1437                                 /* calculate thumbnail size */
1438                                 thumb_width = THUMBNAIL_WIDTH;
1439                                 thumb_height = (thumb_width * encode_src.height) / encode_src.width;
1440                                 if (thumb_height % 2 != 0)
1441                                         thumb_height += 1;
1442
1443                                 _mmcam_dbg_log("need to resize : thumbnail size %dx%d, format %d",
1444                                         thumb_width, thumb_height, encode_src.format);
1445
1446                                 if ((encode_src.format == MM_PIXEL_FORMAT_UYVY ||
1447                                      encode_src.format == MM_PIXEL_FORMAT_YUYV) &&
1448                                      encode_src.width % thumb_width == 0 &&
1449                                      encode_src.height % thumb_height == 0) {
1450                                         if (!_mmcamcorder_downscale_UYVYorYUYV(encode_src.data, encode_src.width, encode_src.height,
1451                                                 &thumb_raw_data, thumb_width, thumb_height)) {
1452                                                 thumb_raw_data = NULL;
1453                                                 _mmcam_dbg_warn("_mmcamcorder_downscale_UYVYorYUYV failed. skip thumbnail making...");
1454                                         }
1455                                 } else {
1456                                         if (!_mmcamcorder_resize_frame(encode_src.data, encode_src.width, encode_src.height,
1457                                                 encode_src.length, encode_src.format,
1458                                                 &thumb_raw_data, &thumb_width, &thumb_height, &thumb_length)) {
1459                                                 thumb_raw_data = NULL;
1460                                                 _mmcam_dbg_warn("_mmcamcorder_resize_frame failed. skip thumbnail making...");
1461                                         }
1462                                 }
1463                         } else {
1464                                 thumb_width = encode_src.width;
1465                                 thumb_height = encode_src.height;
1466
1467                                 _mmcam_dbg_log("NO need to resize : thumbnail size %dx%d", thumb_width, thumb_height);
1468
1469                                 thumb_raw_data = encode_src.data;
1470                                 thumb_length = encode_src.length;
1471                         }
1472
1473                         if (thumb_raw_data) {
1474                                 ret = _mmcamcorder_encode_jpeg(thumb_raw_data, thumb_width, thumb_height,
1475                                         encode_src.format, thumb_length, THUMBNAIL_JPEG_QUALITY,
1476                                         (void **)&internal_thumb_data, &internal_thumb_length);
1477                                 if (ret) {
1478                                         _mmcam_dbg_log("encode THUMBNAIL done - data %p, length %d", internal_thumb_data, internal_thumb_length);
1479
1480                                         thumb.data = internal_thumb_data;
1481                                         thumb.length = internal_thumb_length;
1482                                         thumb.width = thumb_width;
1483                                         thumb.height = thumb_height;
1484                                         thumb.format = MM_PIXEL_FORMAT_ENCODED;
1485                                 } else {
1486                                         _mmcam_dbg_warn("failed to encode THUMBNAIL");
1487                                 }
1488
1489                                 /* release allocated raw data memory */
1490                                 if (thumb_raw_data != encode_src.data) {
1491                                         free(thumb_raw_data);
1492                                         thumb_raw_data = NULL;
1493                                         _mmcam_dbg_log("release thumb_raw_data");
1494                                 }
1495                         } else {
1496                                 _mmcam_dbg_warn("thumb_raw_data is NULL");
1497                         }
1498                 } else {
1499                         /* no raw data src for thumbnail */
1500                         _mmcam_dbg_log("no need to encode thumbnail");
1501                 }
1502         }
1503
1504         /* Encode JPEG */
1505         if (sc->internal_encode && pixtype_main != MM_PIXEL_FORMAT_ENCODED) {
1506                 mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
1507                         MMCAM_IMAGE_ENCODER_QUALITY, &capture_quality,
1508                         NULL);
1509                 _mmcam_dbg_log("Start Internal Encode - capture_quality %d", capture_quality);
1510
1511                 ret = _mmcamcorder_encode_jpeg(mapinfo1.data, dest.width, dest.height,
1512                         pixtype_main, dest.length, capture_quality,
1513                         (void **)&internal_main_data, &internal_main_length);
1514                 if (!ret) {
1515                         _mmcam_dbg_err("_mmcamcorder_encode_jpeg failed");
1516
1517                         MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INTERNAL);
1518
1519                         goto error;
1520                 }
1521
1522                 /* set format */
1523                 dest.data = internal_main_data;
1524                 dest.length = internal_main_length;
1525                 dest.format = MM_PIXEL_FORMAT_ENCODED;
1526
1527                 _mmcam_dbg_log("Done Internal Encode - data %p, length %d", dest.data, dest.length);
1528         }
1529
1530         if (pixtype_main < MM_PIXEL_FORMAT_ENCODED) {
1531                 _mmcam_dbg_log("raw capture, skip EXIF related functions");
1532                 goto _CAPTURE_CB_EXIF_DONE;
1533         }
1534
1535         /* create EXIF info */
1536         if (!provide_exif) {    /* make new exif */
1537                 ret = mm_exif_create_exif_info(&(hcamcorder->exif_info));
1538         } else {        /* load from jpeg buffer dest.data */
1539                 ret = mm_exif_load_exif_info(&(hcamcorder->exif_info), dest.data, dest.length);
1540                 if (ret != MM_ERROR_NONE) {
1541                         _mmcam_dbg_err("Failed to load exif_info [%x], try to create EXIF", ret);
1542                         provide_exif = FALSE;
1543                         ret = mm_exif_create_exif_info(&(hcamcorder->exif_info));
1544                 }
1545         }
1546         if (ret != MM_ERROR_NONE) {
1547                 _mmcam_dbg_err("Failed to create exif_info [%x], but keep going...", ret);
1548         } else {
1549                 /* add basic exif info */
1550                 if (!provide_exif) {
1551                         _mmcam_dbg_log("add basic exif info");
1552                         ret = __mmcamcorder_set_exif_basic_info((MMHandleType)hcamcorder, dest.width, dest.height);
1553                 } else {
1554                         _mmcam_dbg_log("update exif info");
1555                         ret = __mmcamcorder_update_exif_info((MMHandleType)hcamcorder, dest.data, dest.length);
1556                 }
1557
1558                 if (ret != MM_ERROR_NONE) {
1559                         _mmcam_dbg_warn("Failed set_exif_basic_info [%x], but keep going...", ret);
1560                         ret = MM_ERROR_NONE;
1561                 }
1562         }
1563
1564         /* get attribute item for EXIF data */
1565         mm_attrs_get_index((MMHandleType)attrs, MMCAM_CAPTURED_EXIF_RAW_DATA, &attr_index);
1566         item_exif_raw_data = &attrs->items[attr_index];
1567
1568         /* set EXIF data to attribute */
1569         if (hcamcorder->exif_info && hcamcorder->exif_info->data) {
1570                 exif_raw_data = (unsigned char *)malloc(hcamcorder->exif_info->size);
1571                 if (exif_raw_data) {
1572                         memcpy(exif_raw_data, hcamcorder->exif_info->data, hcamcorder->exif_info->size);
1573                         mmf_attribute_set_data(item_exif_raw_data, exif_raw_data, hcamcorder->exif_info->size);
1574                         _mmcam_dbg_log("set EXIF raw data %p, size %d", exif_raw_data, hcamcorder->exif_info->size);
1575                 } else {
1576                         _mmcam_dbg_warn("failed to alloc for EXIF, size %d", hcamcorder->exif_info->size);
1577                 }
1578         } else {
1579                 _mmcam_dbg_warn("failed to create EXIF. set EXIF as NULL");
1580                 mmf_attribute_set_data(item_exif_raw_data, NULL, 0);
1581         }
1582
1583         /* commit EXIF data */
1584         mmf_attribute_commit(item_exif_raw_data);
1585
1586         /* get tag-enable */
1587         mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL, MMCAM_TAG_ENABLE, &tag_enable, NULL);
1588
1589         /* Set extra data for JPEG if tag enabled and doesn't provide EXIF */
1590         if (tag_enable) {
1591                 mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
1592                         MMCAM_IMAGE_ENCODER, &codectype,
1593                         NULL);
1594                 _mmcam_dbg_log("codectype %d", codectype);
1595
1596                 switch (codectype) {
1597                 case MM_IMAGE_CODEC_JPEG:
1598                 case MM_IMAGE_CODEC_SRW:
1599                 case MM_IMAGE_CODEC_JPEG_SRW:
1600                         ret = __mmcamcorder_set_jpeg_data((MMHandleType)hcamcorder, &dest, &thumb, provide_exif);
1601                         if (ret != MM_ERROR_NONE) {
1602                                 _mmcam_dbg_err("Error on setting extra data to jpeg");
1603                                 MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, ret);
1604                                 goto error;
1605                         }
1606                         break;
1607                 default:
1608                         _mmcam_dbg_err("The codectype is not supported. (%d)", codectype);
1609                         MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INTERNAL);
1610                         goto error;
1611                 }
1612         }
1613
1614 _CAPTURE_CB_EXIF_DONE:
1615
1616         /* Handle Capture Callback */
1617         _MMCAMCORDER_LOCK_VCAPTURE_CALLBACK(hcamcorder);
1618
1619         if (hcamcorder->vcapture_cb) {
1620                 _mmcam_dbg_log("APPLICATION CALLBACK START");
1621                 if (thumb.data)
1622                         ret = hcamcorder->vcapture_cb(&dest, &thumb, hcamcorder->vcapture_cb_param);
1623                 else
1624                         ret = hcamcorder->vcapture_cb(&dest, NULL, hcamcorder->vcapture_cb_param);
1625
1626                 _mmcam_dbg_log("APPLICATION CALLBACK END");
1627         } else {
1628                 _mmcam_dbg_err("Capture callback is NULL.");
1629
1630                 MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
1631
1632                 goto err_release_exif;
1633         }
1634
1635         /* Set capture count */
1636         count = ++(info->capture_send_count);
1637         send_captured_message = TRUE;
1638
1639 err_release_exif:
1640         _MMCAMCORDER_UNLOCK_VCAPTURE_CALLBACK(hcamcorder);
1641
1642         /* init screennail and EXIF raw data */
1643         mmf_attribute_set_data(item_screennail, NULL, 0);
1644         mmf_attribute_commit(item_screennail);
1645         if (exif_raw_data) {
1646                 free(exif_raw_data);
1647                 exif_raw_data = NULL;
1648
1649                 mmf_attribute_set_data(item_exif_raw_data, NULL, 0);
1650                 mmf_attribute_commit(item_exif_raw_data);
1651         }
1652
1653         /* Release jpeg data */
1654         if (pixtype_main == MM_PIXEL_FORMAT_ENCODED)
1655                 __mmcamcorder_release_jpeg_data((MMHandleType)hcamcorder, &dest, tag_enable, provide_exif);
1656
1657 error:
1658         /* Check end condition and set proper value */
1659         if (info->hdr_capture_mode != MM_CAMCORDER_HDR_ON_AND_ORIGINAL ||
1660             (info->hdr_capture_mode == MM_CAMCORDER_HDR_ON_AND_ORIGINAL && count == 2)) {
1661                 __mmcamcorder_init_stillshot_info((MMHandleType)hcamcorder);
1662         }
1663
1664         /* release internal allocated data */
1665         if (sc->internal_encode)
1666                 compare_data = internal_main_data;
1667         else
1668                 compare_data = mapinfo1.data;
1669
1670         if (dest.data && compare_data &&
1671             dest.data != compare_data) {
1672                 _mmcam_dbg_log("release internal allocated data %p", dest.data);
1673                 free(dest.data);
1674                 dest.data = NULL;
1675                 dest.length = 0;
1676         }
1677         if (internal_main_data) {
1678                 _mmcam_dbg_log("release internal main data %p", internal_main_data);
1679                 free(internal_main_data);
1680                 internal_main_data = NULL;
1681         }
1682         if (internal_thumb_data) {
1683                 _mmcam_dbg_log("release internal thumb data %p", internal_thumb_data);
1684                 free(internal_thumb_data);
1685                 internal_thumb_data = NULL;
1686         }
1687
1688         /* reset compare_data */
1689         compare_data = NULL;
1690
1691         /*free GstBuffer*/
1692         if (sample1) {
1693                 gst_buffer_unmap(gst_sample_get_buffer(sample1), &mapinfo1);
1694                 gst_sample_unref(sample1);
1695         }
1696         if (sample2) {
1697                 gst_buffer_unmap(gst_sample_get_buffer(sample2), &mapinfo2);
1698                 gst_sample_unref(sample2);
1699         }
1700         if (sample3) {
1701                 gst_buffer_unmap(gst_sample_get_buffer(sample3), &mapinfo3);
1702                 gst_sample_unref(sample3);
1703         }
1704
1705         /* destroy exif info */
1706         mm_exif_destory_exif_info(hcamcorder->exif_info);
1707         hcamcorder->exif_info = NULL;
1708
1709         /* send captured message */
1710         if (send_captured_message) {
1711                 if (info->hdr_capture_mode != MM_CAMCORDER_HDR_ON_AND_ORIGINAL) {
1712                         /* Send CAPTURED message and count - capture success */
1713                         if (current_state >= MM_CAMCORDER_STATE_RECORDING)
1714                                 MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_VIDEO_SNAPSHOT_CAPTURED, count);
1715                         else
1716                                 MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_CAPTURED, count);
1717                 } else if (info->hdr_capture_mode == MM_CAMCORDER_HDR_ON_AND_ORIGINAL && count == 2) {
1718                         /* send captured message only once in HDR and Original Capture mode */
1719                         MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_CAPTURED, 1);
1720                 }
1721         }
1722
1723         if (current_state >= MM_CAMCORDER_STATE_RECORDING) {
1724                 /* Handle capture in recording case */
1725                 hcamcorder->capture_in_recording = FALSE;
1726
1727                 g_mutex_lock(&hcamcorder->task_thread_lock);
1728
1729                 if (hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_CHECK_CAPTURE_IN_RECORDING) {
1730                         _mmcam_dbg_log("send signal for capture in recording");
1731                         g_cond_signal(&hcamcorder->task_thread_cond);
1732                 } else {
1733                         _mmcam_dbg_warn("unexpected task thread state : %d", hcamcorder->task_thread_state);
1734                 }
1735
1736                 g_mutex_unlock(&hcamcorder->task_thread_lock);
1737
1738                 _MMCAMCORDER_CMD_SIGNAL(hcamcorder);
1739         }
1740
1741         _mmcam_dbg_err("END");
1742
1743         return;
1744 }
1745
1746
1747 gboolean __mmcamcorder_handoff_callback(GstElement *fakesink, GstBuffer *buffer, GstPad *pad, gpointer u_data)
1748 {
1749         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1750         _MMCamcorderSubContext *sc = NULL;
1751
1752         mmf_return_val_if_fail(hcamcorder, FALSE);
1753
1754         sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1755         mmf_return_val_if_fail(sc && sc->element, FALSE);
1756
1757         _mmcam_dbg_log("");
1758
1759         /* FIXME. How could you get a thumbnail? */
1760         __mmcamcorder_image_capture_cb(fakesink, gst_sample_new(buffer, gst_pad_get_current_caps(pad), NULL, NULL), NULL, NULL, u_data);
1761
1762         if (sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst) {
1763                 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "signal-handoffs", FALSE);
1764                 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1765                 sc->info_video->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
1766         }
1767
1768         return TRUE;
1769 }
1770
1771
1772 static ExifData *__mmcamcorder_update_exif_orientation(MMHandleType handle, ExifData *ed)
1773 {
1774         int value = 0;
1775         ExifShort eshort = 0;
1776         int ret = MM_ERROR_NONE;
1777
1778         mm_camcorder_get_attributes(handle, NULL, MMCAM_TAG_ORIENTATION, &value, NULL);
1779         _mmcam_dbg_log("get orientation [%d]", value);
1780         if (value == 0)
1781                 value = MM_EXIF_ORIENTATION;
1782
1783         exif_set_short((unsigned char *)&eshort, exif_data_get_byte_order(ed), value);
1784         ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_ORIENTATION,
1785                 EXIF_FORMAT_SHORT, 1, (const char *)&eshort);
1786         if (ret != MM_ERROR_NONE)
1787                 EXIF_SET_ERR(ret, EXIF_TAG_MAKER_NOTE);
1788
1789 exit:
1790         return ed;
1791 }
1792
1793
1794 static ExifData *__mmcamcorder_update_exif_make(MMHandleType handle, ExifData *ed)
1795 {
1796         int ret = MM_ERROR_NONE;
1797         char *make = strdup(MM_MAKER_NAME);
1798
1799         if (make) {
1800                 _mmcam_dbg_log("maker [%s]", make);
1801                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_MAKE,
1802                         EXIF_FORMAT_ASCII, strlen(make)+1, (const char *)make);
1803                 free(make);
1804                 if (ret != MM_ERROR_NONE)
1805                         EXIF_SET_ERR(ret, EXIF_TAG_MAKE);
1806         } else {
1807                 _mmcam_dbg_err("strdup failed [%s]", MM_MAKER_NAME);
1808         }
1809
1810 exit:
1811         return ed;
1812 }
1813
1814
1815 static ExifData *__mmcamcorder_update_exif_software(MMHandleType handle, ExifData *ed)
1816 {
1817         int ret = MM_ERROR_NONE;
1818         mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)handle;
1819
1820         if (hcamcorder == NULL || ed == NULL) {
1821                 _mmcam_dbg_err("NULL parameter %p,%p", hcamcorder, ed);
1822                 return NULL;
1823         }
1824
1825         if (hcamcorder->software_version) {
1826                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_SOFTWARE, EXIF_FORMAT_ASCII,
1827                         strlen(hcamcorder->software_version)+1, (const char *)hcamcorder->software_version);
1828
1829                 _mmcam_dbg_log("set software_version[%s] ret[0x%x]",
1830                         hcamcorder->software_version, ret);
1831         } else {
1832                 _mmcam_dbg_err("model_name is NULL");
1833         }
1834
1835         return ed;
1836 }
1837
1838
1839 static ExifData *__mmcamcorder_update_exif_model(MMHandleType handle, ExifData *ed)
1840 {
1841         int ret = MM_ERROR_NONE;
1842         mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)handle;
1843
1844         if (hcamcorder == NULL || ed == NULL) {
1845                 _mmcam_dbg_err("NULL parameter %p,%p", hcamcorder, ed);
1846                 return NULL;
1847         }
1848
1849         if (hcamcorder->model_name) {
1850                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_MODEL, EXIF_FORMAT_ASCII,
1851                         strlen(hcamcorder->model_name)+1, (const char *)hcamcorder->model_name);
1852
1853                 _mmcam_dbg_err("set model name[%s] ret[0x%x]",
1854                         hcamcorder->model_name, ret);
1855         } else {
1856                 _mmcam_dbg_err("model_name is NULL");
1857         }
1858
1859         return ed;
1860 }
1861
1862 static ExifData *__mmcamcorder_update_exif_gps(MMHandleType handle, ExifData *ed)
1863 {
1864         int ret = MM_ERROR_NONE;
1865         int gps_enable = TRUE;
1866         char *err_name = NULL;
1867         double latitude = INVALID_GPS_VALUE;
1868         double longitude = INVALID_GPS_VALUE;
1869         double altitude = INVALID_GPS_VALUE;
1870
1871         ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_TAG_GPS_ENABLE, &gps_enable, NULL);
1872         if (ret == MM_ERROR_NONE && gps_enable) {
1873                 ExifByte GpsVersion[4] = {2, 2, 0, 0};
1874
1875                 _mmcam_dbg_log("Tag for GPS is ENABLED.");
1876
1877                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_VERSION_ID,
1878                         EXIF_FORMAT_BYTE, 4, (const char *)&GpsVersion);
1879                 if (ret != MM_ERROR_NONE)
1880                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_VERSION_ID);
1881
1882                 ret = mm_camcorder_get_attributes(handle, &err_name,
1883                         MMCAM_TAG_LATITUDE, &latitude,
1884                         MMCAM_TAG_LONGITUDE, &longitude,
1885                         MMCAM_TAG_ALTITUDE, &altitude, NULL);
1886                 if (ret != MM_ERROR_NONE) {
1887                         _mmcam_dbg_err("failed to get gps info [%x][%s]", ret, err_name);
1888                         SAFE_FREE(err_name);
1889                         goto exit;
1890                 }
1891
1892                 _mmcam_dbg_log("latitude [%f]", latitude);
1893                 if (latitude != INVALID_GPS_VALUE) {
1894                         unsigned char *b = NULL;
1895                         unsigned int deg;
1896                         unsigned int min;
1897                         unsigned int sec;
1898                         ExifRational rData;
1899
1900                         if (latitude < 0) {
1901                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF,
1902                                         EXIF_FORMAT_ASCII, 2, "S");
1903                                 if (ret != MM_ERROR_NONE)
1904                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_LATITUDE_REF);
1905
1906                                 latitude = -latitude;
1907                         } else if (latitude > 0) {
1908                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF,
1909                                         EXIF_FORMAT_ASCII, 2, "N");
1910                                 if (ret != MM_ERROR_NONE)
1911                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_LATITUDE_REF);
1912                         }
1913
1914                         deg = (unsigned int)(latitude);
1915                         min = (unsigned int)((latitude-deg) * 60);
1916                         sec = (unsigned int)(((latitude-deg) * 3600) - min * 60);
1917
1918                         _mmcam_dbg_log("f_latitude deg[%d], min[%d], sec[%d]", deg, min, sec);
1919                         b = malloc(3 * sizeof(ExifRational));
1920                         if (b) {
1921                                 rData.numerator = deg;
1922                                 rData.denominator = 1;
1923                                 exif_set_rational(b, exif_data_get_byte_order(ed), rData);
1924                                 rData.numerator = min;
1925                                 exif_set_rational(b + 8, exif_data_get_byte_order(ed), rData);
1926                                 rData.numerator = sec;
1927                                 exif_set_rational(b + 16, exif_data_get_byte_order(ed), rData);
1928
1929                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE,
1930                                         EXIF_FORMAT_RATIONAL, 3, (const char *)b);
1931                                 free(b);
1932                                 if (ret != MM_ERROR_NONE)
1933                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_LATITUDE);
1934                         } else {
1935                                 _mmcam_dbg_warn("malloc failed");
1936                         }
1937                 }
1938
1939                 _mmcam_dbg_log("longitude [%f]", longitude);
1940                 if (longitude != INVALID_GPS_VALUE) {
1941                         unsigned char *b = NULL;
1942                         unsigned int deg;
1943                         unsigned int min;
1944                         unsigned int sec;
1945                         ExifRational rData;
1946
1947                         if (longitude < 0) {
1948                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF,
1949                                         EXIF_FORMAT_ASCII, 2, "W");
1950                                 if (ret != MM_ERROR_NONE)
1951                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_LONGITUDE_REF);
1952
1953                                 longitude = -longitude;
1954                         } else if (longitude > 0) {
1955                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF,
1956                                         EXIF_FORMAT_ASCII, 2, "E");
1957                                 if (ret != MM_ERROR_NONE)
1958                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_LONGITUDE_REF);
1959                         }
1960
1961                         deg = (unsigned int)(longitude);
1962                         min = (unsigned int)((longitude-deg) * 60);
1963                         sec = (unsigned int)(((longitude-deg) * 3600) - min * 60);
1964
1965                         _mmcam_dbg_log("longitude deg[%d], min[%d], sec[%d]", deg, min, sec);
1966                         b = malloc(3 * sizeof(ExifRational));
1967                         if (b) {
1968                                 rData.numerator = deg;
1969                                 rData.denominator = 1;
1970                                 exif_set_rational(b, exif_data_get_byte_order(ed), rData);
1971                                 rData.numerator = min;
1972                                 exif_set_rational(b+8, exif_data_get_byte_order(ed), rData);
1973                                 rData.numerator = sec;
1974                                 exif_set_rational(b+16, exif_data_get_byte_order(ed), rData);
1975                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE,
1976                                         EXIF_FORMAT_RATIONAL, 3, (const char *)b);
1977                                 free(b);
1978                                 if (ret != MM_ERROR_NONE)
1979                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_LONGITUDE);
1980                         } else {
1981                                 _mmcam_dbg_warn("malloc failed");
1982                         }
1983                 }
1984
1985                 _mmcam_dbg_log("f_altitude [%f]", altitude);
1986                 if (altitude != INVALID_GPS_VALUE) {
1987                         ExifByte alt_ref = 0;
1988                         unsigned char *b = NULL;
1989                         ExifRational rData;
1990                         b = malloc(sizeof(ExifRational));
1991                         if (b) {
1992                                 if (altitude < 0) {
1993                                         alt_ref = 1;
1994                                         altitude = -altitude;
1995                                 }
1996
1997                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_ALTITUDE_REF,
1998                                         EXIF_FORMAT_BYTE, 1, (const char *)&alt_ref);
1999                                 if (ret != MM_ERROR_NONE) {
2000                                         _mmcam_dbg_err("error [%x], tag [%x]", ret, EXIF_TAG_GPS_ALTITUDE_REF);
2001                                         if (ret == (int)MM_ERROR_CAMCORDER_LOW_MEMORY) {
2002                                                 free(b);
2003                                                 b = NULL;
2004                                                 goto exit;
2005                                         }
2006                                 }
2007
2008                                 rData.numerator = (unsigned int)(altitude + 0.5)*100;
2009                                 rData.denominator = 100;
2010                                 exif_set_rational(b, exif_data_get_byte_order(ed), rData);
2011                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_ALTITUDE,
2012                                         EXIF_FORMAT_RATIONAL, 1, (const char *)b);
2013                                 free(b);
2014                                 if (ret != MM_ERROR_NONE)
2015                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_ALTITUDE);
2016                         } else {
2017                                 _mmcam_dbg_warn("malloc failed");
2018                         }
2019                 }
2020
2021                 {
2022                         double gps_timestamp = INVALID_GPS_VALUE;
2023                         mm_camcorder_get_attributes(handle, NULL, "tag-gps-time-stamp", &gps_timestamp, NULL);
2024                         _mmcam_dbg_log("Gps timestamp [%f]", gps_timestamp);
2025                         if (gps_timestamp > 0.0) {
2026                                 unsigned char *b = NULL;
2027                                 unsigned int hour;
2028                                 unsigned int min;
2029                                 unsigned int microsec;
2030                                 ExifRational rData;
2031
2032                                 hour = (unsigned int)(gps_timestamp / 3600);
2033                                 min = (unsigned int)((gps_timestamp - 3600 * hour) / 60);
2034                                 microsec = (unsigned int)(((double)((double)gps_timestamp -(double)(3600 * hour)) -(double)(60 * min)) * 1000000);
2035
2036                                 _mmcam_dbg_log("Gps timestamp hour[%d], min[%d], microsec[%d]", hour, min, microsec);
2037                                 b = malloc(3 * sizeof(ExifRational));
2038                                 if (b) {
2039                                         rData.numerator = hour;
2040                                         rData.denominator = 1;
2041                                         exif_set_rational(b, exif_data_get_byte_order(ed), rData);
2042
2043                                         rData.numerator = min;
2044                                         rData.denominator = 1;
2045                                         exif_set_rational(b + 8, exif_data_get_byte_order(ed), rData);
2046
2047                                         rData.numerator = microsec;
2048                                         rData.denominator = 1000000;
2049                                         exif_set_rational(b + 16, exif_data_get_byte_order(ed), rData);
2050
2051                                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_TIME_STAMP,
2052                                                 EXIF_FORMAT_RATIONAL, 3, (const char *)b);
2053                                         free(b);
2054                                         if (ret != MM_ERROR_NONE)
2055                                                 EXIF_SET_ERR(ret, EXIF_TAG_GPS_TIME_STAMP);
2056                                 } else {
2057                                         _mmcam_dbg_warn("malloc failed.");
2058                                 }
2059                         }
2060                 }
2061
2062                 {
2063                         unsigned char *date_stamp = NULL;
2064                         int date_stamp_len = 0;
2065
2066                         mm_camcorder_get_attributes(handle, NULL, "tag-gps-date-stamp", &date_stamp, &date_stamp_len, NULL);
2067
2068                         if (date_stamp) {
2069                                 _mmcam_dbg_log("Date stamp [%s]", date_stamp);
2070
2071                                 /* cause it should include NULL char */
2072                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_DATE_STAMP,
2073                                         EXIF_FORMAT_ASCII, date_stamp_len + 1, (const char *)date_stamp);
2074                                 if (ret != MM_ERROR_NONE)
2075                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_DATE_STAMP);
2076                         }
2077                 }
2078
2079                 {
2080                         unsigned char *processing_method = NULL;
2081                         int processing_method_len = 0;
2082
2083                         mm_camcorder_get_attributes(handle, NULL, "tag-gps-processing-method", &processing_method, &processing_method_len, NULL);
2084
2085                         if (processing_method) {
2086                                 _mmcam_dbg_log("Processing method [%s]", processing_method);
2087
2088                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_PROCESSING_METHOD,
2089                                         EXIF_FORMAT_UNDEFINED, processing_method_len, (const char *)processing_method);
2090                                 if (ret != MM_ERROR_NONE)
2091                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_PROCESSING_METHOD);
2092                         }
2093                 }
2094         } else {
2095                 _mmcam_dbg_log("Tag for GPS is DISABLED.");
2096         }
2097
2098 exit:
2099         return ed;
2100 }
2101
2102
2103 int __mmcamcorder_update_exif_info(MMHandleType handle, void* imagedata, int imgln)
2104 {
2105         int ret = MM_ERROR_NONE;
2106         mmf_camcorder_t *hcamcorder = NULL;
2107         ExifData *ed = NULL;
2108
2109         hcamcorder = MMF_CAMCORDER(handle);
2110
2111         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2112
2113         ed = exif_data_new_from_data(imagedata, imgln);
2114         /*ed = mm_exif_get_exif_from_info(hcamcorder->exif_info);*/
2115
2116         if (ed == NULL) {
2117                 _mmcam_dbg_err("get exif data error!!");
2118                 return MM_ERROR_INVALID_HANDLE;
2119         }
2120
2121         /* update necessary */
2122
2123         __mmcamcorder_update_exif_make(handle, ed);
2124         __mmcamcorder_update_exif_software(handle, ed);
2125         __mmcamcorder_update_exif_model(handle, ed);
2126         __mmcamcorder_update_exif_orientation(handle, ed);
2127         __mmcamcorder_update_exif_gps(handle, ed);
2128         ret = mm_exif_set_exif_to_info(hcamcorder->exif_info, ed);
2129         if (ret != MM_ERROR_NONE)
2130                 _mmcam_dbg_err("mm_exif_set_exif_to_info err!! [%x]", ret);
2131
2132         exif_data_unref(ed);
2133         ed = NULL;
2134         return ret;
2135 }
2136
2137 int __mmcamcorder_set_exif_basic_info(MMHandleType handle, int image_width, int image_height)
2138 {
2139         int ret = MM_ERROR_NONE;
2140         int value;
2141         int str_val_len = 0;
2142         int cntl = 0;
2143         int cnts = 0;
2144         char *str_value = NULL;
2145         char *user_comment = NULL;
2146         ExifData *ed = NULL;
2147         ExifLong config;
2148         ExifLong ExifVersion;
2149         static ExifShort eshort[20];
2150         static ExifLong elong[10];
2151
2152         GstCameraControl *control = NULL;
2153         GstCameraControlExifInfo avsys_exif_info;
2154
2155         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2156         _MMCamcorderSubContext *sc = NULL;
2157
2158         _mmcam_dbg_log("");
2159
2160         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2161
2162         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2163         mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2164
2165         CLEAR(avsys_exif_info);
2166
2167         if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
2168                 _mmcam_dbg_err("Can't cast Video source into camera control. Skip camera control values...");
2169         } else {
2170                 control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
2171                 /* get device information */
2172                 gst_camera_control_get_exif_info(control, &avsys_exif_info);
2173         }
2174
2175         /* get ExifData from exif info */
2176         ed = mm_exif_get_exif_from_info(hcamcorder->exif_info);
2177         if (ed == NULL) {
2178                 _mmcam_dbg_err("get exif data error!!");
2179                 return MM_ERROR_INVALID_HANDLE;
2180         }
2181
2182         /* Receive attribute info */
2183
2184         /* START INSERT IFD_0 */
2185
2186         /*0. EXIF_TAG_EXIF_VERSION */
2187         ExifVersion = MM_EXIF_VERSION;
2188         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXIF_VERSION,
2189                 EXIF_FORMAT_UNDEFINED, 4, (const char *)&ExifVersion);
2190         if (ret != MM_ERROR_NONE)
2191                 EXIF_SET_ERR(ret, EXIF_TAG_EXIF_VERSION);
2192
2193         /*1. EXIF_TAG_IMAGE_WIDTH */ /*EXIF_TAG_PIXEL_X_DIMENSION*/
2194         value = image_width;
2195
2196         exif_set_long((unsigned char *)&elong[cntl], exif_data_get_byte_order(ed), value);
2197         ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH,
2198                 EXIF_FORMAT_LONG, 1, (const char *)&elong[cntl]);
2199         if (ret != MM_ERROR_NONE)
2200                 EXIF_SET_ERR(ret, EXIF_TAG_IMAGE_WIDTH);
2201
2202         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION,
2203                 EXIF_FORMAT_LONG, 1, (const char *)&elong[cntl++]);
2204         if (ret != MM_ERROR_NONE)
2205                 EXIF_SET_ERR(ret, EXIF_TAG_PIXEL_X_DIMENSION);
2206
2207         _mmcam_dbg_log("width[%d]", value);
2208
2209         /*2. EXIF_TAG_IMAGE_LENGTH*/ /*EXIF_TAG_PIXEL_Y_DIMENSION*/
2210         value = image_height;
2211
2212         exif_set_long((unsigned char *)&elong[cntl], exif_data_get_byte_order(ed), value);
2213         ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH,
2214                 EXIF_FORMAT_LONG, 1, (const char *)&elong[cntl]);
2215         if (ret != MM_ERROR_NONE)
2216                 EXIF_SET_ERR(ret, EXIF_TAG_IMAGE_LENGTH);
2217
2218         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION,
2219                 EXIF_FORMAT_LONG, 1, (const char *)&elong[cntl++]);
2220         if (ret != MM_ERROR_NONE)
2221                 EXIF_SET_ERR(ret, EXIF_TAG_PIXEL_Y_DIMENSION);
2222
2223         _mmcam_dbg_log("height[%d]", value);
2224
2225         /*4. EXIF_TAG_DATE_TIME */
2226
2227         /*12. EXIF_TAG_DATE_TIME_ORIGINAL */
2228
2229         /*13. EXIF_TAG_DATE_TIME_DIGITIZED*/
2230         {
2231                 unsigned char *b;
2232                 time_t t;
2233                 struct tm tm;
2234
2235                 b = malloc(20 * sizeof(unsigned char));
2236                 if (b == NULL) {
2237                         _mmcam_dbg_err("failed to alloc b");
2238                         ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
2239                         EXIF_SET_ERR(ret, EXIF_TAG_DATE_TIME);
2240                 }
2241
2242                 memset(b, '\0', 20);
2243
2244                 t = time(NULL);
2245                 tzset();
2246                 localtime_r(&t, &tm);
2247
2248                 snprintf((char *)b, 20, "%04i:%02i:%02i %02i:%02i:%02i",
2249                         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
2250                         tm.tm_hour, tm.tm_min, tm.tm_sec);
2251
2252                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_DATE_TIME, EXIF_FORMAT_ASCII, 20, (const char *)b);
2253                 if (ret != MM_ERROR_NONE) {
2254                         if (ret == (int)MM_ERROR_CAMCORDER_LOW_MEMORY)
2255                                 free(b);
2256
2257                         EXIF_SET_ERR(ret, EXIF_TAG_DATE_TIME);
2258                 }
2259
2260                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL, EXIF_FORMAT_ASCII, 20, (const char *)b);
2261                 if (ret != MM_ERROR_NONE) {
2262                         if (ret == (int)MM_ERROR_CAMCORDER_LOW_MEMORY)
2263                                 free(b);
2264
2265                         EXIF_SET_ERR(ret, EXIF_TAG_DATE_TIME_ORIGINAL);
2266                 }
2267
2268                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_DIGITIZED, EXIF_FORMAT_ASCII, 20, (const char *)b);
2269                 if (ret != MM_ERROR_NONE) {
2270                         if (ret == (int)MM_ERROR_CAMCORDER_LOW_MEMORY)
2271                                 free(b);
2272
2273                         EXIF_SET_ERR(ret, EXIF_TAG_DATE_TIME_DIGITIZED);
2274                 }
2275
2276                 free(b);
2277         }
2278
2279         /*5. EXIF_TAG_MAKE */
2280         __mmcamcorder_update_exif_make(handle, ed);
2281
2282 #ifdef WRITE_EXIF_MAKER_INFO /* FIXME */
2283
2284         /*6. EXIF_TAG_MODEL */
2285         __mmcamcorder_update_exif_model(handle, ed);
2286
2287 #endif
2288         /*6. EXIF_TAG_IMAGE_DESCRIPTION */
2289         mm_camcorder_get_attributes(handle, NULL, MMCAM_TAG_IMAGE_DESCRIPTION, &str_value, &str_val_len, NULL);
2290         if (str_value && str_val_len > 0) {
2291                 char *description = strdup(str_value);
2292
2293                 _mmcam_dbg_log("desctiption [%s]", str_value);
2294
2295                 if (description) {
2296                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_IMAGE_DESCRIPTION,
2297                                 EXIF_FORMAT_ASCII, strlen(description), (const char *)description);
2298                         free(description);
2299                         str_value = NULL;
2300                         str_val_len = 0;
2301                         if (ret != MM_ERROR_NONE)
2302                                 EXIF_SET_ERR(ret, EXIF_TAG_IMAGE_DESCRIPTION);
2303                 } else {
2304                         _mmcam_dbg_err("strdup failed for [%s]", str_value);
2305                 }
2306         } else {
2307                 _mmcam_dbg_warn("failed to get description");
2308         }
2309
2310         /*7. EXIF_TAG_SOFTWARE*/
2311         __mmcamcorder_update_exif_software(handle, ed);
2312
2313 /*
2314         if (control != NULL) {
2315                 char software[50] = {0,};
2316                 unsigned int len = 0;
2317
2318                 len = snprintf(software, sizeof(software), "%x.%x ", avsys_exif_info.software_used>>8, (avsys_exif_info.software_used & 0xff));
2319                 _mmcam_dbg_log("software [%s], len [%d]", software, len);
2320                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_SOFTWARE,
2321                         EXIF_FORMAT_ASCII, len, (const char *)software);
2322                 if (ret != MM_ERROR_NONE) {
2323                         EXIF_SET_ERR(ret, EXIF_TAG_SOFTWARE);
2324                 }
2325         }
2326 */
2327
2328         __mmcamcorder_update_exif_orientation(handle, ed);
2329
2330         /* START INSERT EXIF_IFD */
2331
2332         /*3. User Comment*/
2333         /*FIXME : get user comment from real user */
2334         user_comment = strdup(MM_USER_COMMENT);
2335         if (user_comment) {
2336                 _mmcam_dbg_log("user_comment=%s", user_comment);
2337                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_USER_COMMENT,
2338                         EXIF_FORMAT_ASCII, strlen(user_comment), (const char *)user_comment);
2339                 free(user_comment);
2340                 if (ret != MM_ERROR_NONE)
2341                         EXIF_SET_ERR(ret, EXIF_TAG_USER_COMMENT);
2342         } else {
2343                 ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
2344                 EXIF_SET_ERR(ret, EXIF_TAG_USER_COMMENT);
2345         }
2346
2347         /*9. EXIF_TAG_COLOR_SPACE */
2348         if (control != NULL) {
2349                 exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), avsys_exif_info.colorspace);
2350                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_COLOR_SPACE,
2351                         EXIF_FORMAT_SHORT, 1, (const char *)&eshort[cnts++]);
2352                 if (ret != MM_ERROR_NONE)
2353                         EXIF_SET_ERR(ret, EXIF_TAG_COLOR_SPACE);
2354         }
2355
2356         /*10. EXIF_TAG_COMPONENTS_CONFIGURATION */
2357         if (control != NULL) {
2358                 config = avsys_exif_info.component_configuration;
2359                 _mmcam_dbg_log("EXIF_TAG_COMPONENTS_CONFIGURATION [%4x] ", config);
2360                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_COMPONENTS_CONFIGURATION,
2361                         EXIF_FORMAT_UNDEFINED, 4, (const char *)&config);
2362                 if (ret != MM_ERROR_NONE)
2363                         EXIF_SET_ERR(ret, EXIF_TAG_COMPONENTS_CONFIGURATION);
2364         }
2365
2366         /*11. EXIF_TAG_COMPRESSED_BITS_PER_PIXEL */
2367         /* written  the device_info */
2368
2369         /*12. EXIF_TAG_DATE_TIME_ORIGINAL */
2370         /*13. EXIF_TAG_DATE_TIME_DIGITIZED*/
2371
2372         /*14. EXIF_TAG_EXPOSURE_TIME*/
2373         if (avsys_exif_info.exposure_time_numerator && avsys_exif_info.exposure_time_denominator) {
2374                 unsigned char *b = NULL;
2375                 ExifRational rData;
2376
2377                 _mmcam_dbg_log("EXIF_TAG_EXPOSURE_TIME numerator [%d], denominator [%d]",
2378                         avsys_exif_info.exposure_time_numerator, avsys_exif_info.exposure_time_denominator);
2379
2380                 b = malloc(sizeof(ExifRational));
2381                 if (b) {
2382                         rData.numerator = avsys_exif_info.exposure_time_numerator;
2383                         rData.denominator = avsys_exif_info.exposure_time_denominator;
2384
2385                         exif_set_rational(b, exif_data_get_byte_order(ed), rData);
2386                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_TIME,
2387                                 EXIF_FORMAT_RATIONAL, 1, (const char *)b);
2388                         free(b);
2389                         if (ret != MM_ERROR_NONE)
2390                                 EXIF_SET_ERR(ret, EXIF_TAG_EXPOSURE_TIME);
2391                 } else {
2392                         _mmcam_dbg_warn("malloc failed.");
2393                 }
2394         } else {
2395                 _mmcam_dbg_log("Skip set EXIF_TAG_EXPOSURE_TIME numerator [%d], denominator [%d]",
2396                         avsys_exif_info.exposure_time_numerator, avsys_exif_info.exposure_time_denominator);
2397         }
2398
2399         /*15. EXIF_TAG_FNUMBER */
2400         if (avsys_exif_info.aperture_f_num_numerator && avsys_exif_info.aperture_f_num_denominator) {
2401                 unsigned char *b = NULL;
2402                 ExifRational rData;
2403
2404                 _mmcam_dbg_log("EXIF_TAG_FNUMBER numerator [%d], denominator [%d]",
2405                         avsys_exif_info.aperture_f_num_numerator, avsys_exif_info.aperture_f_num_denominator);
2406
2407                 b = malloc(sizeof(ExifRational));
2408                 if (b) {
2409                         rData.numerator = avsys_exif_info.aperture_f_num_numerator;
2410                         rData.denominator = avsys_exif_info.aperture_f_num_denominator;
2411                         exif_set_rational(b, exif_data_get_byte_order(ed), rData);
2412                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FNUMBER,
2413                                 EXIF_FORMAT_RATIONAL, 1, (const char *)b);
2414                         free(b);
2415                         if (ret != MM_ERROR_NONE)
2416                                 EXIF_SET_ERR(ret, EXIF_TAG_FNUMBER);
2417                 } else {
2418                         _mmcam_dbg_warn("malloc failed.");
2419                 }
2420         } else {
2421                 _mmcam_dbg_log("Skip set EXIF_TAG_FNUMBER numerator [%d], denominator [%d]",
2422                         avsys_exif_info.aperture_f_num_numerator, avsys_exif_info.aperture_f_num_denominator);
2423         }
2424
2425         /*16. EXIF_TAG_EXPOSURE_PROGRAM*/
2426         /*FIXME*/
2427         value = MM_EXPOSURE_PROGRAM;
2428         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), value);
2429         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_PROGRAM,
2430                 EXIF_FORMAT_SHORT, 1, (const char *)&eshort[cnts++]);
2431         if (ret != MM_ERROR_NONE)
2432                 EXIF_SET_ERR(ret, EXIF_TAG_EXPOSURE_PROGRAM);
2433
2434         /*17. EXIF_TAG_ISO_SPEED_RATINGS*/
2435         if (avsys_exif_info.iso) {
2436                 _mmcam_dbg_log("EXIF_TAG_ISO_SPEED_RATINGS [%d]", avsys_exif_info.iso);
2437                 exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), avsys_exif_info.iso);
2438                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS,
2439                         EXIF_FORMAT_SHORT, 1, (const char *)&eshort[cnts++]);
2440                 if (ret != MM_ERROR_NONE)
2441                         EXIF_SET_ERR(ret, EXIF_TAG_ISO_SPEED_RATINGS);
2442         }
2443
2444         /*18. EXIF_TAG_SHUTTER_SPEED_VALUE*/
2445         if (avsys_exif_info.shutter_speed_numerator && avsys_exif_info.shutter_speed_denominator) {
2446                 unsigned char *b = NULL;
2447                 ExifSRational rsData;
2448
2449                 _mmcam_dbg_log("EXIF_TAG_SHUTTER_SPEED_VALUE numerator [%d], denominator [%d]",
2450                         avsys_exif_info.shutter_speed_numerator, avsys_exif_info.shutter_speed_denominator);
2451
2452                 b = malloc(sizeof(ExifSRational));
2453                 if (b) {
2454                         rsData.numerator = avsys_exif_info.shutter_speed_numerator;
2455                         rsData.denominator = avsys_exif_info.shutter_speed_denominator;
2456                         exif_set_srational(b, exif_data_get_byte_order(ed), rsData);
2457                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SHUTTER_SPEED_VALUE,
2458                                 EXIF_FORMAT_SRATIONAL, 1, (const char *)b);
2459                         free(b);
2460                         if (ret != MM_ERROR_NONE)
2461                                 EXIF_SET_ERR(ret, EXIF_TAG_SHUTTER_SPEED_VALUE);
2462                 } else {
2463                         _mmcam_dbg_warn("malloc failed.");
2464                 }
2465         } else {
2466                 _mmcam_dbg_log("Skip set EXIF_TAG_SHUTTER_SPEED_VALUE numerator [%d], denominator [%d]",
2467                         avsys_exif_info.shutter_speed_numerator, avsys_exif_info.shutter_speed_denominator);
2468         }
2469
2470         /*19. EXIF_TAG_APERTURE_VALUE*/
2471         if (avsys_exif_info.aperture_in_APEX) {
2472                 unsigned char *b = NULL;
2473                 ExifRational rData;
2474
2475                 _mmcam_dbg_log("EXIF_TAG_APERTURE_VALUE [%d]", avsys_exif_info.aperture_in_APEX);
2476
2477                 b = malloc(sizeof(ExifRational));
2478                 if (b) {
2479                         rData.numerator = avsys_exif_info.aperture_in_APEX;
2480                         rData.denominator = 1;
2481                         exif_set_rational(b, exif_data_get_byte_order(ed), rData);
2482                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_APERTURE_VALUE,
2483                                 EXIF_FORMAT_RATIONAL, 1, (const char *)b);
2484                         free(b);
2485                         if (ret != MM_ERROR_NONE)
2486                                 EXIF_SET_ERR(ret, EXIF_TAG_APERTURE_VALUE);
2487                 } else {
2488                         _mmcam_dbg_warn("malloc failed.");
2489                 }
2490         } else {
2491                 _mmcam_dbg_log("Skip set EXIF_TAG_APERTURE_VALUE [%d]", avsys_exif_info.aperture_in_APEX);
2492         }
2493
2494         /*20. EXIF_TAG_BRIGHTNESS_VALUE*/
2495         if (avsys_exif_info.brigtness_numerator && avsys_exif_info.brightness_denominator) {
2496                 unsigned char *b = NULL;
2497                 ExifSRational rsData;
2498
2499                 _mmcam_dbg_log("EXIF_TAG_BRIGHTNESS_VALUE numerator [%d], denominator [%d]",
2500                         avsys_exif_info.brigtness_numerator, avsys_exif_info.brightness_denominator);
2501
2502                 b = malloc(sizeof(ExifSRational));
2503                 if (b) {
2504                         rsData.numerator = avsys_exif_info.brigtness_numerator;
2505                         rsData.denominator = avsys_exif_info.brightness_denominator;
2506                         exif_set_srational(b, exif_data_get_byte_order(ed), rsData);
2507                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_BRIGHTNESS_VALUE,
2508                                 EXIF_FORMAT_SRATIONAL, 1, (const char *)b);
2509                         free(b);
2510                         if (ret != MM_ERROR_NONE)
2511                                 EXIF_SET_ERR(ret, EXIF_TAG_BRIGHTNESS_VALUE);
2512                 } else {
2513                         _mmcam_dbg_warn("malloc failed.");
2514                 }
2515         } else {
2516                 _mmcam_dbg_log("Skip set EXIF_TAG_BRIGHTNESS_VALUE numerator [%d], denominatorr [%d]",
2517                         avsys_exif_info.brigtness_numerator, avsys_exif_info.brightness_denominator);
2518         }
2519
2520         /*21. EXIF_TAG_EXPOSURE_BIAS_VALUE*/
2521         value = 0;
2522         ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_BRIGHTNESS, &value, NULL);
2523         if (ret == MM_ERROR_NONE) {
2524                 unsigned char *b = NULL;
2525                 ExifSRational rsData;
2526
2527                 _mmcam_dbg_log("EXIF_TAG_BRIGHTNESS_VALUE %d, default %d, step denominator %d",
2528                         value, hcamcorder->brightness_default, hcamcorder->brightness_step_denominator);
2529
2530                 b = malloc(sizeof(ExifSRational));
2531                 if (b) {
2532                         rsData.numerator = value - hcamcorder->brightness_default;
2533                         if (hcamcorder->brightness_step_denominator != 0) {
2534                                 rsData.denominator = hcamcorder->brightness_step_denominator;
2535                         } else {
2536                                 _mmcam_dbg_warn("brightness_step_denominator is ZERO, so set 1");
2537                                 rsData.denominator = 1;
2538                         }
2539                         exif_set_srational(b, exif_data_get_byte_order(ed), rsData);
2540                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_BIAS_VALUE,
2541                                 EXIF_FORMAT_SRATIONAL, 1, (const char *)b);
2542                         free(b);
2543                         if (ret != MM_ERROR_NONE)
2544                                 EXIF_SET_ERR(ret, EXIF_TAG_EXPOSURE_BIAS_VALUE);
2545                 } else {
2546                         _mmcam_dbg_warn("malloc failed.");
2547                 }
2548         } else {
2549                 _mmcam_dbg_log("failed to get MMCAM_FILTER_BRIGHTNESS [%x]", ret);
2550         }
2551
2552         /*22  EXIF_TAG_MAX_APERTURE_VALUE*/
2553 /*
2554         if (avsys_exif_info.max_lens_aperture_in_APEX) {
2555                 unsigned char *b = NULL;
2556                 ExifRational rData;
2557
2558                 _mmcam_dbg_log("EXIF_TAG_MAX_APERTURE_VALUE [%d]", avsys_exif_info.max_lens_aperture_in_APEX);
2559
2560                 b = malloc(sizeof(ExifRational));
2561                 if (b) {
2562                         rData.numerator = avsys_exif_info.max_lens_aperture_in_APEX;
2563                         rData.denominator = 1;
2564                         exif_set_rational(b, exif_data_get_byte_order(ed), rData);
2565                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_MAX_APERTURE_VALUE,
2566                                 EXIF_FORMAT_RATIONAL, 1, b);
2567                         free(b);
2568                         if (ret != MM_ERROR_NONE)
2569                                 EXIF_SET_ERR(ret, EXIF_TAG_MAX_APERTURE_VALUE);
2570                 } else {
2571                         _mmcam_dbg_warn("failed to alloc for MAX aperture value");
2572                 }
2573         }
2574 */
2575
2576         /*23. EXIF_TAG_SUBJECT_DISTANCE*/
2577         /* defualt : none */
2578
2579         /*24. EXIF_TAG_METERING_MODE */
2580         if (control != NULL) {
2581                 exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), avsys_exif_info.metering_mode);
2582                 _mmcam_dbg_log("EXIF_TAG_METERING_MODE [%d]", avsys_exif_info.metering_mode);
2583                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_METERING_MODE,
2584                         EXIF_FORMAT_SHORT, 1, (const char *)&eshort[cnts++]);
2585                 if (ret != MM_ERROR_NONE)
2586                         EXIF_SET_ERR(ret, EXIF_TAG_METERING_MODE);
2587         }
2588
2589         /*25. EXIF_TAG_LIGHT_SOURCE*/
2590
2591         /*26. EXIF_TAG_FLASH*/
2592         if (control != NULL) {
2593                 exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), avsys_exif_info.flash);
2594                 _mmcam_dbg_log("EXIF_TAG_FLASH [%d]", avsys_exif_info.flash);
2595                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH,
2596                         EXIF_FORMAT_SHORT, 1, (const char *)&eshort[cnts++]);
2597                 if (ret != MM_ERROR_NONE)
2598                         EXIF_SET_ERR(ret, EXIF_TAG_FLASH);
2599         }
2600
2601         /*27. EXIF_TAG_FOCAL_LENGTH*/
2602         if (avsys_exif_info.focal_len_numerator && avsys_exif_info.focal_len_denominator) {
2603                 unsigned char *b = NULL;
2604                 ExifRational rData;
2605
2606                 _mmcam_dbg_log("EXIF_TAG_FOCAL_LENGTH numerator [%d], denominator [%d]",
2607                         avsys_exif_info.focal_len_numerator, avsys_exif_info.focal_len_denominator);
2608
2609                 b = malloc(sizeof(ExifRational));
2610                 if (b) {
2611                         rData.numerator = avsys_exif_info.focal_len_numerator;
2612                         rData.denominator = avsys_exif_info.focal_len_denominator;
2613                         exif_set_rational(b, exif_data_get_byte_order(ed), rData);
2614                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH,
2615                                 EXIF_FORMAT_RATIONAL, 1, (const char *)b);
2616                         free(b);
2617                         if (ret != MM_ERROR_NONE)
2618                                 EXIF_SET_ERR(ret, EXIF_TAG_FOCAL_LENGTH);
2619                 } else {
2620                         _mmcam_dbg_warn("malloc failed.");
2621                 }
2622         } else {
2623                 _mmcam_dbg_log("Skip set EXIF_TAG_FOCAL_LENGTH numerator [%d], denominator [%d]",
2624                         avsys_exif_info.focal_len_numerator, avsys_exif_info.focal_len_denominator);
2625         }
2626
2627         /*28. EXIF_TAG_SENSING_METHOD*/
2628         /*FIXME*/
2629         value = MM_SENSING_MODE;
2630         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), value);
2631         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SENSING_METHOD,
2632                 EXIF_FORMAT_SHORT, 1, (const char *)&eshort[cnts++]);
2633         if (ret != MM_ERROR_NONE)
2634                 EXIF_SET_ERR(ret, EXIF_TAG_SENSING_METHOD);
2635
2636         /*29. EXIF_TAG_FILE_SOURCE*/
2637 /*
2638         value = MM_FILE_SOURCE;
2639         exif_set_long(&elong[cntl], exif_data_get_byte_order(ed),value);
2640         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FILE_SOURCE,
2641                 EXIF_FORMAT_UNDEFINED, 4, (const char *)&elong[cntl++]);
2642         if (ret != MM_ERROR_NONE)
2643                 EXIF_SET_ERR(ret, EXIF_TAG_FILE_SOURCE);
2644 */
2645
2646         /*30. EXIF_TAG_SCENE_TYPE*/
2647 /*
2648         value = MM_SCENE_TYPE;
2649         exif_set_long(&elong[cntl], exif_data_get_byte_order(ed),value);
2650         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SCENE_TYPE,
2651                 EXIF_FORMAT_UNDEFINED, 4, (const char *)&elong[cntl++]);
2652         if (ret != MM_ERROR_NONE)
2653                 EXIF_SET_ERR(ret, EXIF_TAG_SCENE_TYPE);
2654 */
2655
2656         /*31. EXIF_TAG_EXPOSURE_MODE*/
2657         /*FIXME*/
2658         value = MM_EXPOSURE_MODE;
2659         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), value);
2660         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_MODE,
2661                 EXIF_FORMAT_SHORT, 1, (const char *)&eshort[cnts++]);
2662         if (ret != MM_ERROR_NONE)
2663                 EXIF_SET_ERR(ret, EXIF_TAG_EXPOSURE_MODE);
2664
2665         /*32. EXIF_TAG_WHITE_BALANCE*/
2666         ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_WB, &value, NULL);
2667         if (ret == MM_ERROR_NONE) {
2668                 int set_value = 0;
2669                 _mmcam_dbg_log("WHITE BALANCE [%d]", value);
2670
2671                 if (value == MM_CAMCORDER_WHITE_BALANCE_AUTOMATIC)
2672                         set_value = 0;
2673                 else
2674                         set_value = 1;
2675
2676                 exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), set_value);
2677                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_WHITE_BALANCE,
2678                         EXIF_FORMAT_SHORT, 1, (const char *)&eshort[cnts++]);
2679                 if (ret != MM_ERROR_NONE)
2680                         EXIF_SET_ERR(ret, EXIF_TAG_WHITE_BALANCE);
2681         } else {
2682                 _mmcam_dbg_warn("failed to get white balance [%x]", ret);
2683         }
2684
2685         /*33. EXIF_TAG_DIGITAL_ZOOM_RATIO*/
2686 /*
2687         ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_CAMERA_DIGITAL_ZOOM, &value, NULL);
2688         if (ret == MM_ERROR_NONE) {
2689                 _mmcam_dbg_log("DIGITAL ZOOM [%d]", value);
2690
2691                 exif_set_long(&elong[cntl], exif_data_get_byte_order(ed), value);
2692                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_DIGITAL_ZOOM_RATIO,
2693                         EXIF_FORMAT_LONG, 1, (const char *)&elong[cntl++]);
2694                 if (ret != MM_ERROR_NONE)
2695                         EXIF_SET_ERR(ret, EXIF_TAG_DIGITAL_ZOOM_RATIO);
2696         } else {
2697                 _mmcam_dbg_warn("failed to get digital zoom [%x]", ret);
2698         }
2699 */
2700
2701         /*34. EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM*/
2702         /*FIXME*/
2703 /*
2704         value = MM_FOCAL_LENGTH_35MMFILM;
2705         exif_set_short(&eshort[cnts], exif_data_get_byte_order(ed),value);
2706         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM,
2707                 EXIF_FORMAT_SHORT, 1, (const char *)&eshort[cnts++]);
2708         if (ret != MM_ERROR_NONE)
2709                 EXIF_SET_ERR(ret, EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM);
2710 */
2711
2712         /*35. EXIF_TAG_SCENE_CAPTURE_TYPE*/
2713         {
2714                 int scene_capture_type;
2715
2716                 ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_SCENE_MODE, &value, NULL);
2717                 if (ret == MM_ERROR_NONE) {
2718                         _mmcam_dbg_log("Scene mode(program mode) [%d]", value);
2719
2720                         switch (value) {
2721                         case MM_CAMCORDER_SCENE_MODE_NORMAL:
2722                                 scene_capture_type = 0; /* standard */
2723                                 break;
2724                         case MM_CAMCORDER_SCENE_MODE_PORTRAIT:
2725                                 scene_capture_type = 2; /* portrait */
2726                                 break;
2727                         case MM_CAMCORDER_SCENE_MODE_LANDSCAPE:
2728                                 scene_capture_type = 1; /* landscape */
2729                                 break;
2730                         case MM_CAMCORDER_SCENE_MODE_NIGHT_SCENE:
2731                                 scene_capture_type = 3; /* night scene */
2732                                 break;
2733                         default:
2734                                 scene_capture_type = 4; /* Others */
2735                                 break;
2736                         }
2737
2738                         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), scene_capture_type);
2739                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SCENE_CAPTURE_TYPE,
2740                                 EXIF_FORMAT_SHORT, 1, (const char *)&eshort[cnts++]);
2741                         if (ret != MM_ERROR_NONE)
2742                                 EXIF_SET_ERR(ret, EXIF_TAG_SCENE_CAPTURE_TYPE);
2743                 } else {
2744                         _mmcam_dbg_warn("failed to get scene mode [%x]", ret);
2745                 }
2746         }
2747
2748         /*36. EXIF_TAG_GAIN_CONTROL*/
2749         /*FIXME*/
2750 /*
2751         value = MM_GAIN_CONTROL;
2752         exif_set_long(&elong[cntl], exif_data_get_byte_order(ed), value);
2753         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_GAIN_CONTROL,
2754                 EXIF_FORMAT_LONG, 1, (const char *)&elong[cntl++]);
2755         if (ret != MM_ERROR_NONE)
2756                 EXIF_SET_ERR(ret, EXIF_TAG_GAIN_CONTROL);
2757 */
2758
2759
2760         /*37. EXIF_TAG_CONTRAST */
2761         {
2762                 type_int_range *irange = NULL;
2763                 int level = 0;
2764
2765                 _mmcamcorder_conf_get_value_int_range(hcamcorder->conf_ctrl,
2766                         CONFIGURE_CATEGORY_CTRL_EFFECT,
2767                         "Contrast",
2768                         &irange);
2769                 if (irange != NULL) {
2770                         mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_CONTRAST, &value, NULL);
2771
2772                         _mmcam_dbg_log("CONTRAST currentt [%d], default [%d]", value, irange->default_value);
2773
2774                         if (value == irange->default_value)
2775                                 level = MM_VALUE_NORMAL;
2776                         else if (value < irange->default_value)
2777                                 level = MM_VALUE_LOW;
2778                         else
2779                                 level = MM_VALUE_HARD;
2780
2781                         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), level);
2782                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_CONTRAST,
2783                                 EXIF_FORMAT_SHORT, 1, (const char *)&eshort[cnts++]);
2784                         if (ret != MM_ERROR_NONE)
2785                                 EXIF_SET_ERR(ret, EXIF_TAG_CONTRAST);
2786                 } else {
2787                         _mmcam_dbg_warn("failed to get range of contrast");
2788                 }
2789         }
2790
2791         /*38. EXIF_TAG_SATURATION*/
2792         {
2793                 type_int_range *irange = NULL;
2794                 int level = 0;
2795
2796                 _mmcamcorder_conf_get_value_int_range(hcamcorder->conf_ctrl,
2797                         CONFIGURE_CATEGORY_CTRL_EFFECT,
2798                         "Saturation",
2799                         &irange);
2800                 if (irange != NULL) {
2801                         mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_SATURATION, &value, NULL);
2802
2803                         _mmcam_dbg_log("SATURATION current [%d], default [%d]", value, irange->default_value);
2804
2805                         if (value == irange->default_value)
2806                                 level = MM_VALUE_NORMAL;
2807                         else if (value < irange->default_value)
2808                                 level = MM_VALUE_LOW;
2809                         else
2810                                 level = MM_VALUE_HARD;
2811
2812                         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), level);
2813                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SATURATION,
2814                                 EXIF_FORMAT_SHORT, 1, (const char *)&eshort[cnts++]);
2815                         if (ret != MM_ERROR_NONE)
2816                                 EXIF_SET_ERR(ret, EXIF_TAG_SATURATION);
2817                 } else {
2818                         _mmcam_dbg_warn("failed to get range of saturation");
2819                 }
2820         }
2821
2822         /*39. EXIF_TAG_SHARPNESS*/
2823         {
2824                 type_int_range *irange = NULL;
2825                 int level = 0;
2826
2827                 _mmcamcorder_conf_get_value_int_range(hcamcorder->conf_ctrl,
2828                         CONFIGURE_CATEGORY_CTRL_EFFECT,
2829                         "Sharpness",
2830                         &irange);
2831                 if (irange != NULL) {
2832                         mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_SHARPNESS, &value, NULL);
2833
2834                         _mmcam_dbg_log("SHARPNESS current [%d], default [%d]", value, irange->default_value);
2835
2836                         if (value == irange->default_value)
2837                                 level = MM_VALUE_NORMAL;
2838                         else if (value < irange->default_value)
2839                                 level = MM_VALUE_LOW;
2840                         else
2841                                 level = MM_VALUE_HARD;
2842
2843                         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), level);
2844                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SHARPNESS,
2845                                 EXIF_FORMAT_SHORT, 1, (const char *)&eshort[cnts++]);
2846                         if (ret != MM_ERROR_NONE)
2847                                 EXIF_SET_ERR(ret, EXIF_TAG_SHARPNESS);
2848                 } else {
2849                         _mmcam_dbg_warn("failed to get range of sharpness");
2850                 }
2851         }
2852
2853         /*40. EXIF_TAG_SUBJECT_DISTANCE_RANGE*/
2854         /*FIXME*/
2855         value = MM_SUBJECT_DISTANCE_RANGE;
2856         _mmcam_dbg_log("DISTANCE_RANGE [%d]", value);
2857         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), value);
2858         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SUBJECT_DISTANCE_RANGE,
2859                 EXIF_FORMAT_SHORT, 1, (const char *)&eshort[cnts++]);
2860         if (ret != MM_ERROR_NONE)
2861                 EXIF_SET_ERR(ret, EXIF_TAG_SUBJECT_DISTANCE_RANGE);
2862
2863         /* GPS information */
2864         __mmcamcorder_update_exif_gps(handle, ed);
2865
2866         _mmcam_dbg_log("");
2867
2868         ret = mm_exif_set_exif_to_info(hcamcorder->exif_info, ed);
2869         if (ret != MM_ERROR_NONE)
2870                 _mmcam_dbg_err("mm_exif_set_exif_to_info err!! [%x]", ret);
2871
2872 exit:
2873         _mmcam_dbg_log("finished!! [%x]", ret);
2874
2875         if (ed)
2876                 exif_data_unref(ed);
2877
2878         return ret;
2879 }
2880
2881
2882 static void __sound_status_changed_cb(keynode_t* node, void *data)
2883 {
2884         mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)data;
2885         _MMCamcorderImageInfo *info = NULL;
2886
2887         mmf_return_if_fail(hcamcorder && hcamcorder->sub_context && hcamcorder->sub_context->info_image);
2888
2889         _mmcam_dbg_log("START");
2890
2891         info = hcamcorder->sub_context->info_image;
2892
2893         vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &(info->sound_status));
2894
2895         _mmcam_dbg_log("DONE : sound status %d", info->sound_status);
2896
2897         return;
2898 }