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