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