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