Updated to version 0.7.16 from tizendev
[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/video/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, GstSample *sample1, GstSample *sample2, GstSample *sample3, 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",
475                                        "format", G_TYPE_STRING, sc->format_name,
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",
676                                        "format", G_TYPE_STRING, sc->format_name,
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, GstSample *sample)
1006 {
1007         GstCaps *caps = NULL;
1008     GstMapInfo mapinfo = GST_MAP_INFO_INIT;
1009         const GstStructure *structure;
1010
1011         mmf_return_if_fail(capture_data && sample);
1012
1013     caps = gst_sample_get_caps(sample);
1014         if (caps == NULL) {
1015                 _mmcam_dbg_err("failed to get caps");
1016                 goto GET_FAILED;
1017         }
1018
1019         structure = gst_caps_get_structure(caps, 0);
1020         if (caps == NULL) {
1021                 _mmcam_dbg_err("failed to get structure");
1022                 goto GET_FAILED;
1023         }
1024
1025     gst_buffer_map(gst_sample_get_buffer(sample), &mapinfo, GST_MAP_READ);
1026     capture_data->data = mapinfo.data;
1027         capture_data->format = pixtype;
1028         gst_structure_get_int(structure, "width", &capture_data->width);
1029         gst_structure_get_int(structure, "height", &capture_data->height);
1030     capture_data->length = mapinfo.size;
1031     gst_buffer_unmap(gst_sample_get_buffer(sample), &mapinfo);
1032
1033          _mmcam_dbg_warn("buffer data[%p],size[%dx%d],length[%d],format[%d]",
1034                          capture_data->data, capture_data->width, capture_data->height,
1035                          capture_data->length, capture_data->format);
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, GstSample *sample1, GstSample *sample2, GstSample *sample3, 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     GstMapInfo mapinfo1;
1132     GstMapInfo mapinfo2;
1133     GstMapInfo mapinfo3;
1134
1135         mmf_attrs_t *attrs = NULL;
1136         mmf_attribute_t *item_screennail = NULL;
1137         mmf_attribute_t *item_exif_raw_data = NULL;
1138
1139         mmf_return_if_fail(hcamcorder);
1140
1141         sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1142         mmf_return_if_fail(sc && sc->info_image);
1143
1144         info = sc->info_image;
1145
1146         /* get current state */
1147         current_state = _mmcamcorder_get_state((MMHandleType)hcamcorder);
1148
1149         _mmcam_dbg_err("START - current state %d", current_state);
1150
1151         MMTA_ACUM_ITEM_BEGIN("            MSL capture callback", FALSE);
1152
1153         /* check capture state */
1154         if (info->type == _MMCamcorder_MULTI_SHOT && info->capture_send_count > 0) {
1155                 mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL, "capture-break-cont-shot", &stop_cont_shot, NULL);
1156         }
1157
1158         if (!info->capturing || stop_cont_shot) {
1159                 _mmcam_dbg_warn("stop command[%d] or not capturing state[%d]. skip this...",
1160                                 stop_cont_shot, info->capturing);
1161
1162                 MMTA_ACUM_ITEM_END("            MSL capture callback", FALSE);
1163
1164                 /*free GstBuffer*/
1165                 if (sample1) {
1166                     gst_caps_unref(gst_sample_get_caps(sample1));
1167                     gst_buffer_unref(gst_sample_get_buffer(sample1));
1168                         gst_sample_unref(sample1);
1169                 }
1170                 if (sample2) {
1171             gst_caps_unref(gst_sample_get_caps(sample2));
1172             gst_buffer_unref(gst_sample_get_buffer(sample2));
1173             gst_sample_unref(sample2);
1174                 }
1175                 if (sample3) {
1176             gst_caps_unref(gst_sample_get_caps(sample3));
1177             gst_buffer_unref(gst_sample_get_buffer(sample3));
1178             gst_sample_unref(sample3);
1179                 }
1180
1181                 return;
1182         }
1183
1184         /* check command lock to block capture callback if capture start API is not returned
1185            wait for 2 seconds at worst case */
1186         try_lock_count = 0;
1187         do {
1188                 _mmcam_dbg_log("Try command LOCK");
1189                 if (_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
1190                         _mmcam_dbg_log("command LOCK OK");
1191                         _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
1192                         break;
1193                 }
1194
1195                 if (try_lock_count++ < TRY_LOCK_MAX_COUNT) {
1196                         _mmcam_dbg_warn("command LOCK Failed, retry...[count %d]", try_lock_count);
1197                         usleep(TRY_LOCK_TIME);
1198                 } else {
1199                         _mmcam_dbg_err("failed to lock command LOCK");
1200                         break;
1201                 }
1202         } while (TRUE);
1203
1204         if (current_state < MM_CAMCORDER_STATE_RECORDING) {
1205                 /* play capture sound here if multi capture
1206                    or preview format is ITLV(because of AF and flash control in plugin) */
1207                 if (info->type == _MMCamcorder_MULTI_SHOT) {
1208                         __ta__("                _mmcamcorder_sound_play",
1209                         _mmcamcorder_sound_play((MMHandleType)hcamcorder);
1210                         );
1211                 } else if (!info->played_capture_sound) {
1212                         __ta__("                _mmcamcorder_sound_solo_play",
1213                         _mmcamcorder_sound_solo_play((MMHandleType)hcamcorder, _MMCAMCORDER_FILEPATH_CAPTURE_SND, FALSE);
1214                         );
1215                 }
1216         }
1217
1218         /* init capture data */
1219         memset((void *)&dest, 0x0, sizeof(MMCamcorderCaptureDataType));
1220         memset((void *)&thumb, 0x0, sizeof(MMCamcorderCaptureDataType));
1221         memset((void *)&scrnail, 0x0, sizeof(MMCamcorderCaptureDataType));
1222
1223         /* Prepare main, thumbnail buffer */
1224     pixtype = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample1));
1225         if (pixtype == MM_PIXEL_FORMAT_INVALID) {
1226                 _mmcam_dbg_err("Unsupported pixel type");
1227
1228                 MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INTERNAL);
1229
1230                 goto error;
1231         }
1232
1233         /* Main image buffer */
1234     gst_buffer_map(gst_sample_get_buffer(sample1), &mapinfo1, GST_MAP_READ);
1235     if (sample1 && mapinfo1.data && (mapinfo1.size !=0)) {
1236         __mmcamcorder_get_capture_data_from_buffer(&dest, pixtype, sample1);
1237         } else {
1238                 _mmcam_dbg_err("Sample1 has wrong pointer. (sample1=%p)",sample1);
1239                 MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INTERNAL);
1240         gst_buffer_unmap(gst_sample_get_buffer(sample1), &mapinfo1);
1241                 goto error;
1242         }
1243
1244         /* Encode JPEG */
1245         if (sc->internal_encode) {
1246 #ifdef _MMCAMCORDER_MAKE_THUMBNAIL_INTERNAL_ENCODE
1247                 int thumb_width = 0;
1248                 int thumb_height = 0;
1249                 int thumb_length = 0;
1250                 unsigned char *thumb_raw_data = NULL;
1251 #endif /* _MMCAMCORDER_MAKE_THUMBNAIL_INTERNAL_ENCODE */
1252
1253                 mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
1254                                             MMCAM_IMAGE_ENCODER_QUALITY, &capture_quality,
1255                                             NULL);
1256                 _mmcam_dbg_log("Start Internal Encode - capture_quality %d", capture_quality);
1257
1258                 __ta__("                _mmcamcorder_encode_jpeg:MAIN",
1259         ret = _mmcamcorder_encode_jpeg(mapinfo1.data, dest.width, dest.height,
1260                                                pixtype, dest.length, capture_quality, &(dest.data), &(dest.length));
1261                 );
1262
1263         if (!ret) {
1264                         _mmcam_dbg_err("_mmcamcorder_encode_jpeg failed");
1265
1266                         MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INTERNAL);
1267
1268                         goto error;
1269                 }
1270
1271                 /* set format */
1272                 dest.format = MM_PIXEL_FORMAT_ENCODED;
1273
1274                 _mmcam_dbg_log("Done Internal Encode - data %p, length %d", dest.data, dest.length);
1275
1276 #ifdef _MMCAMCORDER_MAKE_THUMBNAIL_INTERNAL_ENCODE
1277                 /* make thumbnail image */
1278                 _mmcam_dbg_log("Make thumbnail image");
1279
1280                 if (dest.width > THUMBNAIL_WIDTH) {
1281                         float img_ratio = (float)dest.width / (float)dest.height;
1282
1283                         _mmcam_dbg_log("image ratio %f , default ratio %f", img_ratio, THUMBNAIL_DEFAULT_RATIO);
1284
1285                         if (img_ratio > THUMBNAIL_DEFAULT_RATIO) {
1286                                 thumb_height = THUMBNAIL_HEIGHT;
1287                                 thumb_width = (thumb_height * dest.width) / dest.height;
1288                         } else {
1289                                 thumb_width = THUMBNAIL_WIDTH;
1290                                 thumb_height = (thumb_width * dest.height) / dest.width;
1291                         }
1292
1293                         _mmcam_dbg_log("need to resize : thumbnail size %dx%d", thumb_width, thumb_height);
1294
1295             if (!_mmcamcorder_resize_frame(mapinfo1.data, dest.width, dest.height, GST_BUFFER_SIZE(buffer1), pixtype,
1296                                                        &thumb_raw_data, &thumb_width, &thumb_height, &thumb_length)) {
1297                                 thumb_raw_data = NULL;
1298                                 _mmcam_dbg_warn("_mmcamcorder_resize_frame failed. skip thumbnail making...");
1299                         }
1300                 } else {
1301                         thumb_width = dest.width;
1302                         thumb_height = dest.height;
1303
1304                         _mmcam_dbg_log("NO need to resize : thumbnail size %dx%d", thumb_width, thumb_height);
1305
1306             thumb_raw_data = mapinfo1.data;
1307                 }
1308
1309                 if (thumb_raw_data) {
1310                         __ta__("                _mmcamcorder_encode_jpeg:THUMBNAIL",
1311                         ret = _mmcamcorder_encode_jpeg(thumb_raw_data, thumb_width, thumb_height,
1312                                                        pixtype, thumb_length, THUMBNAIL_JPEG_QUALITY, &(thumb.data), &(thumb.length));
1313                         );
1314                         if (ret) {
1315                                 _mmcam_dbg_log("encode THUMBNAIL done - data %p, length %d", thumb.data, thumb.length);
1316
1317                                 thumb.width = thumb_width;
1318                                 thumb.height = thumb_height;
1319                                 thumb.format = MM_PIXEL_FORMAT_ENCODED;
1320                         } else {
1321                                 _mmcam_dbg_warn("failed to encode THUMBNAIL");
1322                         }
1323
1324             if (thumb_raw_data != mapinfo1.data) {
1325                                 free(thumb_raw_data);
1326                                 thumb_raw_data = NULL;
1327                                 _mmcam_dbg_log("release thumb_raw_data");
1328                         }
1329                 } else {
1330                         _mmcam_dbg_warn("thumb_raw_data is NULL");
1331                 }
1332 #endif /* _MMCAMCORDER_MAKE_THUMBNAIL_INTERNAL_ENCODE */
1333         gst_buffer_unmap(gst_sample_get_buffer(sample1), &mapinfo1);
1334         } else {
1335         gst_buffer_map(gst_sample_get_buffer(sample2), &mapinfo2, GST_MAP_READ);
1336                 /* Thumbnail image buffer */
1337         if (sample2 && mapinfo2.data && (mapinfo2.size !=0)) {
1338                         _mmcam_dbg_log("Thumnail (sample2=%p)",sample2);
1339
1340             pixtype_sub = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample2));
1341             __mmcamcorder_get_capture_data_from_buffer(&thumb, pixtype_sub, sample2);
1342                 } else {
1343                         _mmcam_dbg_log("Sample2 has wrong pointer. Not Error. (sample2=%p)",sample2);
1344                 }
1345         gst_buffer_unmap(gst_sample_get_buffer(sample2), &mapinfo2);
1346         }
1347
1348         /* Screennail image buffer */
1349         attrs = (mmf_attrs_t*)MMF_CAMCORDER_ATTRS(hcamcorder);
1350         mm_attrs_get_index((MMHandleType)attrs, MMCAM_CAPTURED_SCREENNAIL, &attr_index);
1351         item_screennail = &attrs->items[attr_index];
1352
1353     gst_buffer_map(gst_sample_get_buffer(sample3), &mapinfo3, GST_MAP_READ);
1354     if (sample3 && mapinfo3.data && mapinfo3.size != 0) {
1355         _mmcam_dbg_log("Screennail (sample3=%p,size=%d)", sample3, mapinfo3.size);
1356
1357         pixtype_sub = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample3));
1358         __mmcamcorder_get_capture_data_from_buffer(&scrnail, pixtype_sub, sample3);
1359
1360                 /* Set screennail attribute for application */
1361                 ret = mmf_attribute_set_data(item_screennail, &scrnail, sizeof(scrnail));
1362                 _mmcam_dbg_log("Screennail set attribute data %p, size %d, ret %x", &scrnail, sizeof(scrnail), ret);
1363         } else {
1364                 _mmcam_dbg_log("Sample3 has wrong pointer. Not Error. (sample3=%p)",sample3);
1365                 mmf_attribute_set_data(item_screennail, NULL, 0);
1366         }
1367     gst_buffer_unmap(gst_sample_get_buffer(sample3), &mapinfo3);
1368
1369         /* commit screennail data */
1370         mmf_attribute_commit(item_screennail);
1371
1372         /* create EXIF info */
1373         __ta__("                    mm_exif_create_exif_info",
1374         ret = mm_exif_create_exif_info(&(hcamcorder->exif_info));
1375         );
1376         if (ret != MM_ERROR_NONE) {
1377                 _mmcam_dbg_err("Failed to create exif_info [%x], but keep going...", ret);
1378         } else {
1379                 /* add basic exif info */
1380                 _mmcam_dbg_log("add basic exif info");
1381                 __ta__("                    __mmcamcorder_set_exif_basic_info",
1382                 ret = __mmcamcorder_set_exif_basic_info((MMHandleType)hcamcorder, dest.width, dest.height);
1383                 );
1384                 if (ret != MM_ERROR_NONE) {
1385                         _mmcam_dbg_warn("Failed set_exif_basic_info [%x], but keep going...", ret);
1386                         ret = MM_ERROR_NONE;
1387                 }
1388         }
1389
1390         /* get attribute item for EXIF data */
1391         mm_attrs_get_index((MMHandleType)attrs, MMCAM_CAPTURED_EXIF_RAW_DATA, &attr_index);
1392         item_exif_raw_data = &attrs->items[attr_index];
1393
1394         /* set EXIF data to attribute */
1395         if (hcamcorder->exif_info && hcamcorder->exif_info->data) {
1396                 exif_raw_data = (unsigned char *)malloc(hcamcorder->exif_info->size);
1397                 if (exif_raw_data) {
1398                         memcpy(exif_raw_data, hcamcorder->exif_info->data, hcamcorder->exif_info->size);
1399                         mmf_attribute_set_data(item_exif_raw_data, exif_raw_data, hcamcorder->exif_info->size);
1400                         _mmcam_dbg_log("set EXIF raw data %p, size %d", exif_raw_data, hcamcorder->exif_info->size);
1401                 } else {
1402                         _mmcam_dbg_warn("failed to alloc for EXIF, size %d", hcamcorder->exif_info->size);
1403                 }
1404         } else {
1405                 _mmcam_dbg_warn("failed to create EXIF. set EXIF as NULL");
1406                 mmf_attribute_set_data(item_exif_raw_data, NULL, 0);
1407         }
1408
1409         /* commit EXIF data */
1410         mmf_attribute_commit(item_exif_raw_data);
1411
1412         /* get tag-enable and provide-exif */
1413         mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL, MMCAM_TAG_ENABLE, &tag_enable, NULL);
1414         MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "provide-exif", &provide_exif);
1415
1416         /* Set extra data for JPEG if tag enabled and doesn't provide EXIF */
1417         if (dest.format == MM_PIXEL_FORMAT_ENCODED &&
1418             tag_enable && !provide_exif) {
1419                 mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
1420                                             MMCAM_IMAGE_ENCODER, &codectype,
1421                                             NULL);
1422                 _mmcam_dbg_log("codectype %d", codectype);
1423
1424                 switch (codectype) {
1425                 case MM_IMAGE_CODEC_JPEG:
1426                 case MM_IMAGE_CODEC_SRW:
1427                 case MM_IMAGE_CODEC_JPEG_SRW:
1428                         __ta__( "                __mmcamcorder_set_jpeg_data",
1429                         ret = __mmcamcorder_set_jpeg_data((MMHandleType)hcamcorder, &dest, &thumb);
1430                         );
1431                         if (ret != MM_ERROR_NONE) {
1432                                 _mmcam_dbg_err("Error on setting extra data to jpeg");
1433                                 MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, ret);
1434                                 goto error;
1435                         }
1436                         break;
1437                 default:
1438                         _mmcam_dbg_err("The codectype is not supported. (%d)", codectype);
1439
1440                         MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INTERNAL);
1441
1442                         goto error;
1443                 }
1444         }
1445
1446         /* Handle Capture Callback */
1447         _MMCAMCORDER_LOCK_VCAPTURE_CALLBACK(hcamcorder);
1448
1449         if (hcamcorder->vcapture_cb) {
1450                 _mmcam_dbg_log("APPLICATION CALLBACK START");
1451                 MMTA_ACUM_ITEM_BEGIN("                Application capture callback", 0);
1452                 if (thumb.data) {
1453                         ret = hcamcorder->vcapture_cb(&dest, &thumb, hcamcorder->vcapture_cb_param);
1454                 } else {
1455                         ret = hcamcorder->vcapture_cb(&dest, NULL, hcamcorder->vcapture_cb_param);
1456                 }
1457                 MMTA_ACUM_ITEM_END("                Application capture callback", 0);
1458                 _mmcam_dbg_log("APPLICATION CALLBACK END");
1459         } else {
1460                 _mmcam_dbg_err("Capture callback is NULL.");
1461
1462                 MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
1463
1464                 goto err_release_exif;
1465         }
1466
1467         /* Set capture count */
1468         count = ++(info->capture_send_count);
1469         send_captured_message = TRUE;
1470
1471 err_release_exif:
1472         _MMCAMCORDER_UNLOCK_VCAPTURE_CALLBACK(hcamcorder);
1473
1474         /* init screennail and EXIF raw data */
1475         __ta__("                init attributes:scrnl and EXIF",
1476         mmf_attribute_set_data(item_screennail, NULL, 0);
1477         mmf_attribute_commit(item_screennail);
1478         if (exif_raw_data) {
1479                 free(exif_raw_data);
1480                 exif_raw_data = NULL;
1481
1482                 mmf_attribute_set_data(item_exif_raw_data, NULL, 0);
1483                 mmf_attribute_commit(item_exif_raw_data);
1484         }
1485         );
1486
1487         /* Release jpeg data */
1488         if (pixtype == MM_PIXEL_FORMAT_ENCODED) {
1489                 __ta__("                __mmcamcorder_release_jpeg_data",
1490                 __mmcamcorder_release_jpeg_data((MMHandleType)hcamcorder, &dest);
1491                 );
1492         }
1493
1494 error:
1495         /* Check end condition and set proper value */
1496         if (info->hdr_capture_mode != MM_CAMCORDER_HDR_ON_AND_ORIGINAL ||
1497             (info->hdr_capture_mode == MM_CAMCORDER_HDR_ON_AND_ORIGINAL && count == 2)) {
1498                 __mmcamcorder_init_stillshot_info((MMHandleType)hcamcorder);
1499         }
1500
1501         /* release internal allocated data */
1502         if (sc->internal_encode) {
1503                 if (dest.data) {
1504                         free(dest.data);
1505                         dest.data = NULL;
1506                         dest.length = 0;
1507                         _mmcam_dbg_log("release internal encoded data MAIN");
1508                 }
1509                 if (thumb.data) {
1510                         free(thumb.data);
1511                         thumb.data = NULL;
1512                         thumb.length = 0;
1513                         _mmcam_dbg_log("release internal encoded data THUMB");
1514                 }
1515         }
1516
1517         /*free GstBuffer*/
1518     if (sample1) {
1519         gst_caps_unref(gst_sample_get_caps(sample1));
1520         gst_buffer_unref(gst_sample_get_buffer(sample1));
1521         gst_sample_unref(sample1);
1522     }
1523     if (sample2) {
1524         gst_caps_unref(gst_sample_get_caps(sample2));
1525         gst_buffer_unref(gst_sample_get_buffer(sample2));
1526         gst_sample_unref(sample2);
1527     }
1528     if (sample3) {
1529         gst_caps_unref(gst_sample_get_caps(sample3));
1530         gst_buffer_unref(gst_sample_get_buffer(sample3));
1531         gst_sample_unref(sample3);
1532     }
1533
1534         /* destroy exif info */
1535         __ta__("                mm_exif_destory_exif_info",
1536         mm_exif_destory_exif_info(hcamcorder->exif_info);
1537         );
1538         hcamcorder->exif_info = NULL;
1539
1540         /* send captured message */
1541         if (send_captured_message) {
1542                 MMTA_ACUM_ITEM_BEGIN("                CAPTURED MESSAGE DELAY", FALSE);
1543
1544                 if (info->hdr_capture_mode != MM_CAMCORDER_HDR_ON_AND_ORIGINAL) {
1545                         MMCamcorderStateType current_state = MM_CAMCORDER_STATE_NONE;
1546
1547                         mm_camcorder_get_state((MMHandleType)hcamcorder, &current_state);
1548
1549                         /* Send CAPTURED message and count - capture success */
1550                         if (current_state >= MM_CAMCORDER_STATE_RECORDING) {
1551                                 MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_VIDEO_SNAPSHOT_CAPTURED, count);
1552                         } else {
1553                                 MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_CAPTURED, count);
1554                         }
1555                 } else if (info->hdr_capture_mode == MM_CAMCORDER_HDR_ON_AND_ORIGINAL && count == 2) {
1556                         /* send captured message only once in HDR and Original Capture mode */
1557                         MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_CAPTURED, 1);
1558                 }
1559         }
1560
1561         MMTA_ACUM_ITEM_END( "            MSL capture callback", FALSE );
1562
1563         _mmcam_dbg_err("END");
1564
1565         return;
1566 }
1567
1568
1569 static gboolean __mmcamcorder_encodesink_handoff_callback(GstElement *fakesink, GstBuffer *buffer, GstPad *pad, gpointer u_data)
1570 {
1571         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1572         _MMCamcorderSubContext *sc = NULL;
1573
1574         mmf_return_val_if_fail(hcamcorder, FALSE);
1575
1576         sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1577         mmf_return_val_if_fail(sc && sc->element, FALSE);
1578
1579         _mmcam_dbg_log("");
1580         /* FIXME. How could you get a thumbnail? */
1581
1582     __mmcamcorder_image_capture_cb(fakesink, gst_sample_new(buffer, gst_pad_get_current_caps(pad), NULL, NULL), NULL, NULL, u_data);
1583
1584         if (sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst) {
1585                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_SINK].gst, "signal-handoffs", FALSE);
1586                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1587         }
1588
1589         return TRUE;
1590 }
1591
1592
1593 /* Take a picture with capture mode */
1594 int _mmcamcorder_set_resize_property(MMHandleType handle, int capture_width, int capture_height)
1595 {
1596         int ELEMENT_CROP = 0;
1597         int ELEMENT_FILTER = 0;
1598
1599         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1600         _MMCamcorderSubContext *sc = NULL;
1601
1602         _mmcam_dbg_log("");
1603
1604         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1605
1606         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1607         mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1608
1609         ELEMENT_CROP = _MMCAMCORDER_ENCSINK_ICROP;
1610         ELEMENT_FILTER = _MMCAMCORDER_ENCSINK_IFILT;
1611
1612         /*TODO: this is not needed now. */
1613
1614         return MM_ERROR_NONE;
1615 }
1616
1617
1618 int __mmcamcorder_set_exif_basic_info(MMHandleType handle, int image_width, int image_height)
1619 {
1620         int ret = MM_ERROR_NONE;
1621         int value;
1622         int str_val_len = 0;
1623         int gps_enable = TRUE;
1624         int cntl = 0;
1625         int cnts = 0;
1626         double f_latitude = INVALID_GPS_VALUE;
1627         double f_longitude = INVALID_GPS_VALUE;
1628         double f_altitude = INVALID_GPS_VALUE;
1629         char *str_value = NULL;
1630 #ifdef WRITE_EXIF_MAKER_INFO /* FIXME */
1631         char *maker = NULL;
1632 #endif
1633         char *user_comment = NULL;
1634         char *err_name = NULL;
1635         ExifData *ed = NULL;
1636         ExifLong config;
1637         ExifLong ExifVersion;
1638         static ExifShort eshort[20];
1639         static ExifLong elong[10];
1640
1641         GstCameraControl *control = NULL;
1642         GstCameraControlExifInfo avsys_exif_info;
1643
1644         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1645         _MMCamcorderSubContext *sc = NULL;
1646
1647         _mmcam_dbg_log("");
1648
1649         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1650
1651         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1652         mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1653
1654         CLEAR(avsys_exif_info);
1655
1656         if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
1657                 _mmcam_dbg_err("Can't cast Video source into camera control. Skip camera control values...");
1658         } else {
1659                 control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
1660                 /* get device information */
1661                 __ta__("                        gst_camera_control_get_exif_info",
1662                 gst_camera_control_get_exif_info(control, &avsys_exif_info);
1663                 );
1664         }
1665
1666         /* get ExifData from exif info */
1667         __ta__("                        mm_exif_get_exif_from_info",
1668         ed = mm_exif_get_exif_from_info(hcamcorder->exif_info);
1669         );
1670         if (ed == NULL || ed->ifd == NULL) {
1671                 _mmcam_dbg_err("get exif data error!!(%p, %p)", ed, (ed ? ed->ifd : NULL));
1672                 return MM_ERROR_INVALID_HANDLE;
1673         }
1674
1675         /* Receive attribute info */
1676
1677         /* START INSERT IFD_0 */
1678
1679         /*0. EXIF_TAG_EXIF_VERSION */
1680         ExifVersion = MM_EXIF_VERSION;
1681         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXIF_VERSION,
1682                                     EXIF_FORMAT_UNDEFINED, 4, (unsigned char *)&ExifVersion);
1683         if (ret != MM_ERROR_NONE) {
1684                 EXIF_SET_ERR(ret, EXIF_TAG_EXIF_VERSION);
1685         }
1686
1687         /*1. EXIF_TAG_IMAGE_WIDTH */ /*EXIF_TAG_PIXEL_X_DIMENSION*/
1688         value = image_width;
1689
1690         exif_set_long((unsigned char *)&elong[cntl], exif_data_get_byte_order(ed), value);
1691         ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH,
1692                                     EXIF_FORMAT_LONG, 1, (unsigned char *)&elong[cntl]);
1693         if (ret != MM_ERROR_NONE) {
1694                 EXIF_SET_ERR(ret, EXIF_TAG_IMAGE_WIDTH);
1695         }
1696
1697         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION,
1698                                     EXIF_FORMAT_LONG, 1, (unsigned char *)&elong[cntl++]);
1699         if (ret != MM_ERROR_NONE) {
1700                 EXIF_SET_ERR(ret, EXIF_TAG_PIXEL_X_DIMENSION);
1701         }
1702         _mmcam_dbg_log("width[%d]", value);
1703
1704         /*2. EXIF_TAG_IMAGE_LENGTH*/ /*EXIF_TAG_PIXEL_Y_DIMENSION*/
1705         value = image_height;
1706
1707         exif_set_long((unsigned char *)&elong[cntl], exif_data_get_byte_order (ed), value);
1708         ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH,
1709                                     EXIF_FORMAT_LONG, 1, (unsigned char *)&elong[cntl]);
1710         if (ret != MM_ERROR_NONE) {
1711                 EXIF_SET_ERR(ret, EXIF_TAG_IMAGE_LENGTH);
1712         }
1713
1714         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION,
1715                                     EXIF_FORMAT_LONG, 1, (unsigned char *)&elong[cntl++]);
1716         if (ret != MM_ERROR_NONE) {
1717                 EXIF_SET_ERR(ret, EXIF_TAG_PIXEL_Y_DIMENSION);
1718         }
1719         _mmcam_dbg_log("height[%d]", value);
1720
1721         /*4. EXIF_TAG_DATE_TIME */
1722
1723         /*12. EXIF_TAG_DATE_TIME_ORIGINAL */
1724
1725         /*13. EXIF_TAG_DATE_TIME_DIGITIZED*/
1726         {
1727                 unsigned char *b;
1728                 time_t t;
1729                 struct tm tm;
1730
1731                 b = malloc(20 * sizeof(unsigned char));
1732                 if (b == NULL) {
1733                         _mmcam_dbg_err("failed to alloc b");
1734                         ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
1735                         EXIF_SET_ERR(ret, EXIF_TAG_DATE_TIME);
1736                 }
1737
1738                 memset(b, '\0', 20);
1739
1740                 t = time(NULL);
1741                 tzset();
1742                 localtime_r(&t, &tm);
1743
1744                 snprintf((char *)b, 20, "%04i:%02i:%02i %02i:%02i:%02i",
1745                          tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
1746                          tm.tm_hour, tm.tm_min, tm.tm_sec);
1747
1748                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_DATE_TIME, EXIF_FORMAT_ASCII, 20, b);
1749                 if (ret != MM_ERROR_NONE) {
1750                         if (ret == MM_ERROR_CAMCORDER_LOW_MEMORY) {
1751                                 free(b);
1752                         }
1753                         EXIF_SET_ERR(ret, EXIF_TAG_DATE_TIME);
1754                 }
1755
1756                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL, EXIF_FORMAT_ASCII, 20, b);
1757                 if (ret != MM_ERROR_NONE) {
1758                         if (ret == MM_ERROR_CAMCORDER_LOW_MEMORY) {
1759                                 free(b);
1760                         }
1761                         EXIF_SET_ERR(ret, EXIF_TAG_DATE_TIME_ORIGINAL);
1762                 }
1763
1764                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_DIGITIZED, EXIF_FORMAT_ASCII, 20, b);
1765                 if (ret != MM_ERROR_NONE) {
1766                         if (ret == MM_ERROR_CAMCORDER_LOW_MEMORY) {
1767                                 free(b);
1768                         }
1769                         EXIF_SET_ERR(ret, EXIF_TAG_DATE_TIME_DIGITIZED);
1770                 }
1771
1772                 free(b);
1773         }
1774
1775 #ifdef WRITE_EXIF_MAKER_INFO /* FIXME */
1776         /*5. EXIF_TAG_MAKE */
1777         maker = strdup(MM_MAKER_NAME);
1778         if (maker) {
1779                 _mmcam_dbg_log("maker [%s]", maker);
1780                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_MAKE,
1781                                             EXIF_FORMAT_ASCII, strlen(maker), (unsigned char *)maker);
1782                 free(maker);
1783                 if (ret != MM_ERROR_NONE) {
1784                         EXIF_SET_ERR(ret, EXIF_TAG_MAKE);
1785                 }
1786         } else {
1787                 ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
1788                 EXIF_SET_ERR(ret, EXIF_TAG_MAKE);
1789         }
1790
1791         /*6. EXIF_TAG_MODEL */
1792         _mmcamcorder_conf_get_value_string(hcamcorder->conf_main,
1793                                            CONFIGURE_CATEGORY_MAIN_GENERAL,
1794                                            "ModelName",
1795                                            &str_value);
1796         _mmcam_dbg_log("model_name [%s]", str_value);
1797         if (str_value) {
1798                 char *model = strdup(str_value);
1799                 mm_exif_set_add_entry(ed,EXIF_IFD_0,EXIF_TAG_MODEL,EXIF_FORMAT_ASCII,strlen(model)+1, (unsigned char*)model);
1800                 free(model);
1801                 str_value = NULL;
1802                 if (ret != MM_ERROR_NONE) {
1803                         EXIF_SET_ERR(ret, EXIF_TAG_MODEL);
1804                 }
1805         } else {
1806                 _mmcam_dbg_warn("failed to get model name");
1807         }
1808 #endif
1809         /*6. EXIF_TAG_IMAGE_DESCRIPTION */
1810         mm_camcorder_get_attributes(handle, NULL, MMCAM_TAG_IMAGE_DESCRIPTION, &str_value, &str_val_len, NULL);
1811         _mmcam_dbg_log("desctiption [%s]", str_value);
1812         if (str_value && str_val_len > 0) {
1813                 char *description = strdup(str_value);
1814                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_IMAGE_DESCRIPTION,
1815                                             EXIF_FORMAT_ASCII, strlen(description), (unsigned char *)description);
1816                 free(description);
1817                 str_value = NULL;
1818                 str_val_len = 0;
1819                 if (ret != MM_ERROR_NONE) {
1820                         EXIF_SET_ERR(ret, EXIF_TAG_IMAGE_DESCRIPTION);
1821                 }
1822         } else {
1823                 _mmcam_dbg_warn("failed to get description");
1824         }
1825
1826         /*7. EXIF_TAG_SOFTWARE*/
1827 /*
1828         if (control != NULL) {
1829                 char software[50] = {0,};
1830                 unsigned int len = 0;
1831
1832                 len = snprintf(software, sizeof(software), "%x.%x ", avsys_exif_info.software_used>>8,(avsys_exif_info.software_used & 0xff));
1833                 _mmcam_dbg_log("software [%s], len [%d]", software, len);
1834                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_SOFTWARE,
1835                                             EXIF_FORMAT_ASCII, len, software);
1836                 if (ret != MM_ERROR_NONE) {
1837                         EXIF_SET_ERR(ret, EXIF_TAG_SOFTWARE);
1838                 }
1839         }
1840 */
1841
1842         /*8. EXIF_TAG_ORIENTATION */
1843         mm_camcorder_get_attributes(handle, NULL, MMCAM_TAG_ORIENTATION, &value, NULL);
1844         _mmcam_dbg_log("get orientation [%d]",value);
1845         if (value == 0) {
1846                 value = MM_EXIF_ORIENTATION;
1847         }
1848
1849         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), value);
1850         ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_ORIENTATION,
1851                                     EXIF_FORMAT_SHORT, 1, (unsigned char*)&eshort[cnts++]);
1852         if (ret != MM_ERROR_NONE) {
1853                 EXIF_SET_ERR(ret, EXIF_TAG_ORIENTATION);
1854         }
1855
1856         /* START INSERT EXIF_IFD */
1857
1858         /*3. User Comment*/
1859         /*FIXME : get user comment from real user */
1860         user_comment = strdup(MM_USER_COMMENT);
1861         if (user_comment) {
1862                 _mmcam_dbg_log("user_comment=%s",user_comment);
1863                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_USER_COMMENT,
1864                                             EXIF_FORMAT_ASCII, strlen(user_comment), (unsigned char *)user_comment);
1865                 free(user_comment);
1866                 if (ret != MM_ERROR_NONE) {
1867                         EXIF_SET_ERR(ret, EXIF_TAG_USER_COMMENT);
1868                 }
1869         } else {
1870                 ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
1871                 EXIF_SET_ERR(ret, EXIF_TAG_USER_COMMENT);
1872         }
1873
1874         /*9. EXIF_TAG_COLOR_SPACE */
1875         if (control != NULL) {
1876                 exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), avsys_exif_info.colorspace);
1877                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_COLOR_SPACE,
1878                                             EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
1879                 if (ret != MM_ERROR_NONE) {
1880                         EXIF_SET_ERR(ret, EXIF_TAG_COLOR_SPACE);
1881                 }
1882         }
1883
1884         /*10. EXIF_TAG_COMPONENTS_CONFIGURATION */
1885         if (control != NULL) {
1886                 config = avsys_exif_info.component_configuration;
1887                 _mmcam_dbg_log("EXIF_TAG_COMPONENTS_CONFIGURATION [%4x] ",config);
1888                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_COMPONENTS_CONFIGURATION,
1889                                             EXIF_FORMAT_UNDEFINED, 4, (unsigned char *)&config);
1890                 if (ret != MM_ERROR_NONE) {
1891                         EXIF_SET_ERR(ret, EXIF_TAG_COMPONENTS_CONFIGURATION);
1892                 }
1893         }
1894
1895         /*11. EXIF_TAG_COMPRESSED_BITS_PER_PIXEL */
1896         /* written  the device_info */
1897
1898         /*12. EXIF_TAG_DATE_TIME_ORIGINAL */
1899         /*13. EXIF_TAG_DATE_TIME_DIGITIZED*/
1900
1901         /*14. EXIF_TAG_EXPOSURE_TIME*/
1902         if (avsys_exif_info.exposure_time_numerator && avsys_exif_info.exposure_time_denominator) {
1903                 unsigned char *b = NULL;
1904                 ExifRational rData;
1905
1906                 _mmcam_dbg_log("EXIF_TAG_EXPOSURE_TIME numerator [%d], denominator [%d]",
1907                                avsys_exif_info.exposure_time_numerator, avsys_exif_info.exposure_time_denominator)
1908
1909                 b = malloc(sizeof(ExifRational));
1910                 if (b) {
1911                         rData.numerator = avsys_exif_info.exposure_time_numerator;
1912                         rData.denominator = avsys_exif_info.exposure_time_denominator;
1913
1914                         exif_set_rational(b, exif_data_get_byte_order(ed), rData);
1915                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_TIME,
1916                                                     EXIF_FORMAT_RATIONAL, 1, b);
1917                         free(b);
1918                         if (ret != MM_ERROR_NONE) {
1919                                 EXIF_SET_ERR(ret, EXIF_TAG_EXPOSURE_TIME);
1920                         }
1921                 } else {
1922                         _mmcam_dbg_warn("malloc failed.");
1923                 }
1924         } else {
1925                 _mmcam_dbg_log("Skip set EXIF_TAG_EXPOSURE_TIME numerator [%d], denominator [%d]",
1926                                avsys_exif_info.exposure_time_numerator, avsys_exif_info.exposure_time_denominator);
1927         }
1928
1929         /*15. EXIF_TAG_FNUMBER */
1930         if (avsys_exif_info.aperture_f_num_numerator && avsys_exif_info.aperture_f_num_denominator) {
1931                 unsigned char *b = NULL;
1932                 ExifRational rData;
1933
1934                 _mmcam_dbg_log("EXIF_TAG_FNUMBER numerator [%d], denominator [%d]",
1935                                avsys_exif_info.aperture_f_num_numerator, avsys_exif_info.aperture_f_num_denominator);
1936
1937                 b = malloc(sizeof(ExifRational));
1938                 if (b) {
1939                         rData.numerator = avsys_exif_info.aperture_f_num_numerator;
1940                         rData.denominator = avsys_exif_info.aperture_f_num_denominator;
1941                         exif_set_rational(b, exif_data_get_byte_order(ed), rData);
1942                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FNUMBER,
1943                                                     EXIF_FORMAT_RATIONAL, 1, b);
1944                         free(b);
1945                         if(ret != MM_ERROR_NONE) {
1946                                 EXIF_SET_ERR(ret, EXIF_TAG_FNUMBER);
1947                         }
1948                 } else {
1949                         _mmcam_dbg_warn( "malloc failed." );
1950                 }
1951         } else {
1952                 _mmcam_dbg_log("Skip set EXIF_TAG_FNUMBER numerator [%d], denominator [%d]",
1953                                avsys_exif_info.aperture_f_num_numerator, avsys_exif_info.aperture_f_num_denominator);
1954         }
1955
1956         /*16. EXIF_TAG_EXPOSURE_PROGRAM*/
1957         /*FIXME*/
1958         value = MM_EXPOSURE_PROGRAM;
1959         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), value);
1960         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_PROGRAM,
1961                                     EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
1962         if (ret != MM_ERROR_NONE) {
1963                 EXIF_SET_ERR(ret, EXIF_TAG_EXPOSURE_PROGRAM);
1964         }
1965
1966         /*17. EXIF_TAG_ISO_SPEED_RATINGS*/
1967         if (avsys_exif_info.iso) {
1968                 _mmcam_dbg_log("EXIF_TAG_ISO_SPEED_RATINGS [%d]", avsys_exif_info.iso);
1969                 exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), avsys_exif_info.iso);
1970                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS,
1971                                             EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
1972                 if (ret != MM_ERROR_NONE) {
1973                         EXIF_SET_ERR(ret, EXIF_TAG_ISO_SPEED_RATINGS);
1974                 }
1975         }
1976
1977         /*18. EXIF_TAG_SHUTTER_SPEED_VALUE*/
1978         if (avsys_exif_info.shutter_speed_numerator && avsys_exif_info.shutter_speed_denominator) {
1979                 unsigned char *b = NULL;
1980                 ExifSRational rsData;
1981
1982                 _mmcam_dbg_log("EXIF_TAG_SHUTTER_SPEED_VALUE numerator [%d], denominator [%d]",
1983                                avsys_exif_info.shutter_speed_numerator, avsys_exif_info.shutter_speed_denominator);
1984
1985                 b = malloc(sizeof(ExifSRational));
1986                 if (b) {
1987                         rsData.numerator = avsys_exif_info.shutter_speed_numerator;
1988                         rsData.denominator = avsys_exif_info.shutter_speed_denominator;
1989                         exif_set_srational(b, exif_data_get_byte_order(ed), rsData);
1990                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SHUTTER_SPEED_VALUE,
1991                                                     EXIF_FORMAT_SRATIONAL, 1, b);
1992                         free(b);
1993                         if (ret != MM_ERROR_NONE) {
1994                                 EXIF_SET_ERR(ret, EXIF_TAG_SHUTTER_SPEED_VALUE);
1995                         }
1996                 } else {
1997                         _mmcam_dbg_warn("malloc failed.");
1998                 }
1999         } else {
2000                 _mmcam_dbg_log("Skip set EXIF_TAG_SHUTTER_SPEED_VALUE numerator [%d], denominator [%d]",
2001                                avsys_exif_info.shutter_speed_numerator, avsys_exif_info.shutter_speed_denominator);
2002         }
2003
2004         /*19. EXIF_TAG_APERTURE_VALUE*/
2005         if (avsys_exif_info.aperture_in_APEX) {
2006                 unsigned char *b = NULL;
2007                 ExifRational rData;
2008
2009                 _mmcam_dbg_log("EXIF_TAG_APERTURE_VALUE [%d]", avsys_exif_info.aperture_in_APEX);
2010
2011                 b = malloc(sizeof(ExifRational));
2012                 if (b) {
2013                         rData.numerator = avsys_exif_info.aperture_in_APEX;
2014                         rData.denominator = 1;
2015                         exif_set_rational(b, exif_data_get_byte_order(ed), rData);
2016                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_APERTURE_VALUE,
2017                                                     EXIF_FORMAT_RATIONAL, 1, b);
2018                         free(b);
2019                         if(ret != MM_ERROR_NONE) {
2020                                 EXIF_SET_ERR(ret, EXIF_TAG_APERTURE_VALUE);
2021                         }
2022                 } else {
2023                         _mmcam_dbg_warn("malloc failed.");
2024                 }
2025         } else {
2026                 _mmcam_dbg_log("Skip set EXIF_TAG_APERTURE_VALUE [%d]", avsys_exif_info.aperture_in_APEX);
2027         }
2028
2029         /*20. EXIF_TAG_BRIGHTNESS_VALUE*/
2030         if (avsys_exif_info.brigtness_numerator && avsys_exif_info.brightness_denominator) {
2031                 unsigned char *b = NULL;
2032                 ExifSRational rsData;
2033
2034                 _mmcam_dbg_log("EXIF_TAG_BRIGHTNESS_VALUE numerator [%d], denominator [%d]",
2035                                avsys_exif_info.brigtness_numerator, avsys_exif_info.brightness_denominator);
2036
2037                 b = malloc(sizeof(ExifSRational));
2038                 if (b) {
2039                         rsData.numerator = avsys_exif_info.brigtness_numerator;
2040                         rsData.denominator = avsys_exif_info.brightness_denominator;
2041                         exif_set_srational(b, exif_data_get_byte_order(ed), rsData);
2042                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_BRIGHTNESS_VALUE,
2043                                                     EXIF_FORMAT_SRATIONAL, 1, b);
2044                         free(b);
2045                         if (ret != MM_ERROR_NONE) {
2046                                 EXIF_SET_ERR(ret, EXIF_TAG_BRIGHTNESS_VALUE);
2047                         }
2048                 } else {
2049                         _mmcam_dbg_warn( "malloc failed." );
2050                 }
2051         } else {
2052                 _mmcam_dbg_log("Skip set EXIF_TAG_BRIGHTNESS_VALUE numerator [%d], denominatorr [%d]",
2053                                avsys_exif_info.brigtness_numerator, avsys_exif_info.brightness_denominator);
2054         }
2055
2056         /*21. EXIF_TAG_EXPOSURE_BIAS_VALUE*/
2057         value = 0;
2058         MMCamAttrsInfo info;
2059         mm_camcorder_get_attribute_info(handle, MMCAM_FILTER_BRIGHTNESS, &info);
2060
2061         ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_BRIGHTNESS, &value, NULL);
2062         if (ret == MM_ERROR_NONE) {
2063                 unsigned char *b = NULL;
2064                 ExifSRational rsData;
2065
2066                 _mmcam_dbg_log("EXIF_TAG_BRIGHTNESS_VALUE %d",value);
2067
2068                 b = malloc(sizeof(ExifSRational));
2069                 if (b) {
2070                         if( info.int_range.min < info.int_range.max) {
2071                                 rsData.numerator = (value - 4) * 5;
2072                                 rsData.denominator = 10;
2073                         }
2074                         else {
2075                                 rsData.numerator = 0;
2076                                 rsData.denominator = 10;
2077                         }
2078                         exif_set_srational(b, exif_data_get_byte_order(ed), rsData);
2079                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_BIAS_VALUE,
2080                                                     EXIF_FORMAT_SRATIONAL, 1, b);
2081                         free(b);
2082                         if (ret != MM_ERROR_NONE) {
2083                                 EXIF_SET_ERR(ret, EXIF_TAG_EXPOSURE_BIAS_VALUE);
2084                         }
2085                 } else {
2086                         _mmcam_dbg_warn("malloc failed.");
2087                 }
2088         } else {
2089                 _mmcam_dbg_log("failed to get MMCAM_FILTER_BRIGHTNESS [%x]", ret);
2090         }
2091
2092         /*22  EXIF_TAG_MAX_APERTURE_VALUE*/
2093 /*
2094         if (avsys_exif_info.max_lens_aperture_in_APEX) {
2095                 unsigned char *b = NULL;
2096                 ExifRational rData;
2097
2098                 _mmcam_dbg_log("EXIF_TAG_MAX_APERTURE_VALUE [%d]", avsys_exif_info.max_lens_aperture_in_APEX);
2099
2100                 b = malloc(sizeof(ExifRational));
2101                 if (b) {
2102                         rData.numerator = avsys_exif_info.max_lens_aperture_in_APEX;
2103                         rData.denominator = 1;
2104                         exif_set_rational(b, exif_data_get_byte_order(ed), rData);
2105                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_MAX_APERTURE_VALUE,
2106                                                     EXIF_FORMAT_RATIONAL, 1, b);
2107                         free(b);
2108                         if (ret != MM_ERROR_NONE) {
2109                                 EXIF_SET_ERR(ret, EXIF_TAG_MAX_APERTURE_VALUE);
2110                         }
2111                 } else {
2112                         _mmcam_dbg_warn("failed to alloc for MAX aperture value");
2113                 }
2114         }
2115 */
2116
2117         /*23. EXIF_TAG_SUBJECT_DISTANCE*/
2118         /* defualt : none */
2119
2120         /*24. EXIF_TAG_METERING_MODE */
2121         if (control != NULL) {
2122                 exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed),avsys_exif_info.metering_mode);
2123                 _mmcam_dbg_log("EXIF_TAG_METERING_MODE [%d]", avsys_exif_info.metering_mode);
2124                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_METERING_MODE,
2125                                             EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
2126                 if (ret != MM_ERROR_NONE) {
2127                         EXIF_SET_ERR(ret, EXIF_TAG_METERING_MODE);
2128                 }
2129         }
2130
2131         /*25. EXIF_TAG_LIGHT_SOURCE*/
2132
2133         /*26. EXIF_TAG_FLASH*/
2134         if (control != NULL) {
2135                 exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order (ed),avsys_exif_info.flash);
2136                 _mmcam_dbg_log("EXIF_TAG_FLASH [%d]", avsys_exif_info.flash);
2137                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH,
2138                                             EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
2139                 if (ret != MM_ERROR_NONE) {
2140                         EXIF_SET_ERR(ret, EXIF_TAG_FLASH);
2141                 }
2142         }
2143
2144         /*27. EXIF_TAG_FOCAL_LENGTH*/
2145         if (avsys_exif_info.focal_len_numerator && avsys_exif_info.focal_len_denominator) {
2146                 unsigned char *b = NULL;
2147                 ExifRational rData;
2148
2149                 _mmcam_dbg_log("EXIF_TAG_FOCAL_LENGTH numerator [%d], denominator [%d]",
2150                                avsys_exif_info.focal_len_numerator, avsys_exif_info.focal_len_denominator);
2151
2152                 b = malloc(sizeof(ExifRational));
2153                 if (b) {
2154                         rData.numerator = avsys_exif_info.focal_len_numerator;
2155                         rData.denominator = avsys_exif_info.focal_len_denominator;
2156                         exif_set_rational(b, exif_data_get_byte_order(ed), rData);
2157                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH,
2158                                                     EXIF_FORMAT_RATIONAL, 1, b);
2159                         free(b);
2160                         if (ret != MM_ERROR_NONE) {
2161                                 EXIF_SET_ERR(ret, EXIF_TAG_FOCAL_LENGTH);
2162                         }
2163                 } else {
2164                         _mmcam_dbg_warn("malloc failed.");
2165                 }
2166         } else {
2167                 _mmcam_dbg_log("Skip set EXIF_TAG_FOCAL_LENGTH numerator [%d], denominator [%d]",
2168                                avsys_exif_info.focal_len_numerator, avsys_exif_info.focal_len_denominator);
2169         }
2170
2171         /*28. EXIF_TAG_SENSING_METHOD*/
2172         /*FIXME*/
2173         value = MM_SENSING_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_SENSING_METHOD,
2176                                     EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
2177         if (ret != MM_ERROR_NONE) {
2178                 EXIF_SET_ERR(ret, EXIF_TAG_SENSING_METHOD);
2179         }
2180
2181         /*29. EXIF_TAG_FILE_SOURCE*/
2182 /*
2183         value = MM_FILE_SOURCE;
2184         exif_set_long(&elong[cntl], exif_data_get_byte_order(ed),value);
2185         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FILE_SOURCE,
2186                                     EXIF_FORMAT_UNDEFINED, 4, (unsigned char *)&elong[cntl++]);
2187         if (ret != MM_ERROR_NONE) {
2188                 EXIF_SET_ERR(ret, EXIF_TAG_FILE_SOURCE);
2189         }
2190 */
2191
2192         /*30. EXIF_TAG_SCENE_TYPE*/
2193 /*
2194         value = MM_SCENE_TYPE;
2195         exif_set_long(&elong[cntl], exif_data_get_byte_order(ed),value);
2196         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SCENE_TYPE,
2197                                     EXIF_FORMAT_UNDEFINED, 4, (unsigned char *)&elong[cntl++]);
2198         if (ret != MM_ERROR_NONE) {
2199                 EXIF_SET_ERR(ret, EXIF_TAG_SCENE_TYPE);
2200         }
2201 */
2202
2203         /*31. EXIF_TAG_EXPOSURE_MODE*/
2204         /*FIXME*/
2205         value = MM_EXPOSURE_MODE;
2206         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed),value);
2207         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_MODE,
2208                                     EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
2209         if (ret != MM_ERROR_NONE) {
2210                 EXIF_SET_ERR(ret, EXIF_TAG_EXPOSURE_MODE);
2211         }
2212
2213
2214         /*32. EXIF_TAG_WHITE_BALANCE*/
2215         ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_WB, &value, NULL);
2216         if (ret == MM_ERROR_NONE) {
2217                 int set_value = 0;
2218                 _mmcam_dbg_log("WHITE BALANCE [%d]", value);
2219         
2220                 if (value == MM_CAMCORDER_WHITE_BALANCE_AUTOMATIC) {
2221                         set_value = 0;
2222                 } else {
2223                         set_value = 1;
2224                 }
2225
2226                 exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), set_value);
2227                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_WHITE_BALANCE,
2228                                             EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
2229                 if (ret != MM_ERROR_NONE) {
2230                         EXIF_SET_ERR(ret, EXIF_TAG_WHITE_BALANCE);
2231                 }
2232         } else {
2233                 _mmcam_dbg_warn("failed to get white balance [%x]", ret);
2234         }
2235
2236         /*33. EXIF_TAG_DIGITAL_ZOOM_RATIO*/
2237 /*
2238         ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_CAMERA_DIGITAL_ZOOM, &value, NULL);
2239         if (ret == MM_ERROR_NONE) {
2240                 _mmcam_dbg_log("DIGITAL ZOOM [%d]", value);
2241
2242                 exif_set_long(&elong[cntl], exif_data_get_byte_order(ed), value);
2243                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_DIGITAL_ZOOM_RATIO,
2244                                             EXIF_FORMAT_LONG, 1, (unsigned char *)&elong[cntl++]);
2245                 if (ret != MM_ERROR_NONE) {
2246                         EXIF_SET_ERR(ret, EXIF_TAG_DIGITAL_ZOOM_RATIO);
2247                 }
2248         } else {
2249                 _mmcam_dbg_warn("failed to get digital zoom [%x]", ret);
2250         }
2251 */
2252
2253         /*34. EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM*/
2254         /*FIXME*/
2255 /*
2256         value = MM_FOCAL_LENGTH_35MMFILM;
2257         exif_set_short(&eshort[cnts], exif_data_get_byte_order(ed),value);
2258         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM,
2259                                     EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
2260         if (ret != MM_ERROR_NONE) {
2261                 EXIF_SET_ERR(ret, EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM);
2262         }
2263 */
2264
2265         /*35. EXIF_TAG_SCENE_CAPTURE_TYPE*/
2266         {
2267                 int scene_capture_type;
2268
2269                 ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_SCENE_MODE, &value, NULL);
2270                 if (ret == MM_ERROR_NONE) {
2271                         _mmcam_dbg_log("Scene mode(program mode) [%d]", value);
2272
2273                         if (value == MM_CAMCORDER_SCENE_MODE_NORMAL) {
2274                                 scene_capture_type = 0; /* standard */
2275                         } else if (value == MM_CAMCORDER_SCENE_MODE_PORTRAIT) {
2276                                 scene_capture_type = 2; /* portrait */
2277                         } else if (value == MM_CAMCORDER_SCENE_MODE_LANDSCAPE) {
2278                                 scene_capture_type = 1; /* landscape */
2279                         } else if (value == MM_CAMCORDER_SCENE_MODE_NIGHT_SCENE) {
2280                                 scene_capture_type = 3; /* night scene */
2281                         } else {
2282                                 scene_capture_type = 4; /* Others */
2283                         }
2284
2285                         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), scene_capture_type);
2286                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SCENE_CAPTURE_TYPE,
2287                                                     EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
2288                         if (ret != MM_ERROR_NONE) {
2289                                 EXIF_SET_ERR(ret, EXIF_TAG_SCENE_CAPTURE_TYPE);
2290                         }
2291                 } else {
2292                         _mmcam_dbg_warn("failed to get scene mode [%x]", ret);
2293                 }
2294         }
2295
2296         /*36. EXIF_TAG_GAIN_CONTROL*/
2297         /*FIXME*/
2298 /*
2299         value = MM_GAIN_CONTROL;
2300         exif_set_long(&elong[cntl], exif_data_get_byte_order(ed), value);
2301         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_GAIN_CONTROL,
2302                                     EXIF_FORMAT_LONG, 1, (unsigned char *)&elong[cntl++]);
2303         if (ret != MM_ERROR_NONE) {
2304                 EXIF_SET_ERR(ret, EXIF_TAG_GAIN_CONTROL);
2305         }
2306 */
2307
2308
2309         /*37. EXIF_TAG_CONTRAST */
2310         {
2311                 type_int_range *irange = NULL;
2312                 int level = 0;
2313
2314                 _mmcamcorder_conf_get_value_int_range(hcamcorder->conf_ctrl,
2315                                                       CONFIGURE_CATEGORY_CTRL_EFFECT,
2316                                                       "Contrast",
2317                                                       &irange);
2318                 if (irange != NULL) {
2319                         mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_CONTRAST, &value, NULL);
2320
2321                         _mmcam_dbg_log("CONTRAST currentt [%d], default [%d]", value, irange->default_value);
2322
2323                         if (value == irange->default_value) {
2324                                 level = MM_VALUE_NORMAL;
2325                         } else if (value < irange->default_value) {
2326                                 level = MM_VALUE_LOW;
2327                         } else {
2328                                 level = MM_VALUE_HARD;
2329                         }
2330
2331                         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), level);
2332                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_CONTRAST,
2333                                                     EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
2334                         if (ret != MM_ERROR_NONE) {
2335                                 EXIF_SET_ERR(ret, EXIF_TAG_CONTRAST);
2336                         }
2337                 } else {
2338                         _mmcam_dbg_warn("failed to get range of contrast");
2339                 }
2340         }
2341
2342         /*38. EXIF_TAG_SATURATION*/
2343         {
2344                 type_int_range *irange = NULL;
2345                 int level = 0;
2346
2347                 _mmcamcorder_conf_get_value_int_range(hcamcorder->conf_ctrl,
2348                                                       CONFIGURE_CATEGORY_CTRL_EFFECT,
2349                                                       "Saturation",
2350                                                       &irange);
2351                 if (irange != NULL) {
2352                         mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_SATURATION, &value, NULL);
2353
2354                         _mmcam_dbg_log("SATURATION current [%d], default [%d]", value, irange->default_value);
2355
2356                         if (value == irange->default_value) {
2357                                 level = MM_VALUE_NORMAL;
2358                         } else if (value < irange->default_value) {
2359                                 level = MM_VALUE_LOW;
2360                         } else {
2361                                 level=MM_VALUE_HARD;
2362                         }
2363
2364                         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), level);
2365                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SATURATION,
2366                                                     EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
2367                         if (ret != MM_ERROR_NONE) {
2368                                 EXIF_SET_ERR(ret, EXIF_TAG_SATURATION);
2369                         }
2370                 } else {
2371                         _mmcam_dbg_warn("failed to get range of saturation");
2372                 }
2373         }
2374
2375         /*39. EXIF_TAG_SHARPNESS*/
2376         {
2377                 type_int_range *irange = NULL;
2378                 int level = 0;
2379
2380                 _mmcamcorder_conf_get_value_int_range(hcamcorder->conf_ctrl,
2381                                                       CONFIGURE_CATEGORY_CTRL_EFFECT,
2382                                                       "Sharpness",
2383                                                       &irange);
2384                 if (irange != NULL) {
2385                         mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_SHARPNESS, &value, NULL);
2386
2387                         _mmcam_dbg_log("SHARPNESS current [%d], default [%d]", value, irange->default_value);
2388
2389                         if (value == irange->default_value) {
2390                                 level = MM_VALUE_NORMAL;
2391                         } else if (value < irange->default_value) {
2392                                 level = MM_VALUE_LOW;
2393                         } else {
2394                                 level = MM_VALUE_HARD;
2395                         }
2396
2397                         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), level);
2398                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SHARPNESS,
2399                                                     EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
2400                         if (ret != MM_ERROR_NONE) {
2401                                 EXIF_SET_ERR(ret, EXIF_TAG_SHARPNESS);
2402                         }
2403                 } else {
2404                         _mmcam_dbg_warn("failed to get range of sharpness");
2405                 }
2406         }
2407
2408         /*40. EXIF_TAG_SUBJECT_DISTANCE_RANGE*/
2409         /*FIXME*/
2410         value = MM_SUBJECT_DISTANCE_RANGE;
2411         _mmcam_dbg_log("DISTANCE_RANGE [%d]", value);
2412         exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), value);
2413         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SUBJECT_DISTANCE_RANGE,
2414                                     EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
2415         if (ret != MM_ERROR_NONE) {
2416                 EXIF_SET_ERR(ret, EXIF_TAG_SUBJECT_DISTANCE_RANGE);
2417         }
2418
2419         /* GPS information */
2420         ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_TAG_GPS_ENABLE, &gps_enable, NULL);
2421         if (ret == MM_ERROR_NONE && gps_enable) {
2422                 ExifByte GpsVersion[4]={2,2,0,0};
2423
2424                 _mmcam_dbg_log("Tag for GPS is ENABLED.");
2425
2426                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_VERSION_ID,
2427                                             EXIF_FORMAT_BYTE, 4, (unsigned char *)&GpsVersion);
2428                 if (ret != MM_ERROR_NONE) {
2429                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_VERSION_ID);
2430                 }
2431
2432                 /*41. Latitude*/
2433                 ret = mm_camcorder_get_attributes(handle, &err_name,
2434                                                   MMCAM_TAG_LATITUDE, &f_latitude,
2435                                                   MMCAM_TAG_LONGITUDE, &f_longitude,
2436                                                   MMCAM_TAG_ALTITUDE, &f_altitude, NULL);
2437                 if (ret != MM_ERROR_NONE) {
2438                         _mmcam_dbg_err("failed to get gps info [%x][%s]", ret, err_name);
2439                         SAFE_FREE(err_name);
2440                         goto exit;
2441                 }
2442
2443                 _mmcam_dbg_log("f_latitude [%f]", f_latitude);
2444                 if (f_latitude != INVALID_GPS_VALUE) {
2445                         unsigned char *b = NULL;
2446                         unsigned int deg;
2447                         unsigned int min;
2448                         unsigned int sec;
2449                         ExifRational rData;
2450
2451                         if (f_latitude < 0) {
2452                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF,
2453                                                             EXIF_FORMAT_ASCII, 2, (unsigned char *)"S");
2454                                 if (ret != MM_ERROR_NONE) {
2455                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_LATITUDE_REF);
2456                                 }
2457                                 f_latitude = -f_latitude;
2458                         } else if (f_latitude > 0) {
2459                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF,
2460                                                             EXIF_FORMAT_ASCII, 2, (unsigned char *)"N");
2461                                 if (ret != MM_ERROR_NONE) {
2462                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_LATITUDE_REF);
2463                                 }
2464                         }
2465
2466                         deg = (unsigned int)(f_latitude);
2467                         min = (unsigned int)((f_latitude-deg)*60);
2468                         sec = (unsigned int)(((f_latitude-deg)*3600)-min*60);
2469
2470                         _mmcam_dbg_log("f_latitude deg[%d], min[%d], sec[%d]", deg, min, sec);
2471                         b = malloc(3 * sizeof(ExifRational));
2472                         if (b) {
2473                                 rData.numerator = deg;
2474                                 rData.denominator = 1;
2475                                 exif_set_rational(b, exif_data_get_byte_order(ed), rData);
2476                                 rData.numerator = min;
2477                                 exif_set_rational(b+8, exif_data_get_byte_order(ed), rData);
2478                                 rData.numerator = sec;
2479                                 exif_set_rational(b+16, exif_data_get_byte_order(ed), rData);
2480
2481                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE,
2482                                                             EXIF_FORMAT_RATIONAL, 3, (unsigned char *)b);
2483                                 free(b);
2484                                 if (ret != MM_ERROR_NONE) {
2485                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_LATITUDE);
2486                                 }
2487                         } else {
2488                                 _mmcam_dbg_warn("malloc failed");
2489                         }
2490                 }
2491
2492                 /*42. Longitude*/
2493                 _mmcam_dbg_log("f_longitude [%f]", f_longitude);
2494                 if (f_longitude != INVALID_GPS_VALUE) {
2495                         unsigned char *b = NULL;
2496                         unsigned int deg;
2497                         unsigned int min;
2498                         unsigned int sec;
2499                         ExifRational rData;
2500
2501                         if (f_longitude < 0) {
2502                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF,
2503                                                             EXIF_FORMAT_ASCII, 2, (unsigned char *)"W");
2504                                 if (ret != MM_ERROR_NONE) {
2505                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_LONGITUDE_REF);
2506                                 }
2507                                 f_longitude = -f_longitude;
2508                         } else if (f_longitude > 0) {
2509                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF,
2510                                                             EXIF_FORMAT_ASCII, 2, (unsigned char *)"E");
2511                                 if (ret != MM_ERROR_NONE) {
2512                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_LONGITUDE_REF);
2513                                 }
2514                         }
2515
2516                         deg = (unsigned int)(f_longitude);
2517                         min = (unsigned int)((f_longitude-deg)*60);
2518                         sec = (unsigned int)(((f_longitude-deg)*3600)-min*60);
2519
2520                         _mmcam_dbg_log("f_longitude deg[%d], min[%d], sec[%d]", deg, min, sec);
2521                         b = malloc(3 * sizeof(ExifRational));
2522                         if (b) {
2523                                 rData.numerator = deg;
2524                                 rData.denominator = 1;
2525                                 exif_set_rational(b, exif_data_get_byte_order(ed), rData);
2526                                 rData.numerator = min;
2527                                 exif_set_rational(b+8, exif_data_get_byte_order(ed), rData);
2528                                 rData.numerator = sec;
2529                                 exif_set_rational(b+16, exif_data_get_byte_order(ed), rData);
2530                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE,
2531                                                             EXIF_FORMAT_RATIONAL, 3, (unsigned char *)b);
2532                                 free(b);
2533                                 if (ret != MM_ERROR_NONE) {
2534                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_LONGITUDE);
2535                                 }
2536                         } else {
2537                                 _mmcam_dbg_warn("malloc failed");
2538                         }
2539                 }
2540
2541                 /*43. Altitude*/
2542                 _mmcam_dbg_log("f_altitude [%f]", f_altitude);
2543                 if (f_altitude != INVALID_GPS_VALUE) {
2544                         ExifByte alt_ref = 0;
2545                         unsigned char *b = NULL;
2546                         ExifRational rData;
2547                         b = malloc(sizeof(ExifRational));
2548                         if (b) {
2549                                 if (f_altitude < 0) {
2550                                         alt_ref = 1;
2551                                         f_altitude = -f_altitude;
2552                                 }
2553
2554                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_ALTITUDE_REF,
2555                                                             EXIF_FORMAT_BYTE, 1, (unsigned char *)&alt_ref);
2556                                 if (ret != MM_ERROR_NONE) {
2557                                         _mmcam_dbg_err("error [%x], tag [%x]", ret, EXIF_TAG_GPS_ALTITUDE_REF);
2558                                         if (ret == MM_ERROR_CAMCORDER_LOW_MEMORY) {
2559                                                 free(b);
2560                                                 b = NULL;
2561                                                 goto exit;
2562                                         }
2563                                 }
2564
2565                                 rData.numerator = (unsigned int)(f_altitude + 0.5)*100;
2566                                 rData.denominator = 100;
2567                                 exif_set_rational(b, exif_data_get_byte_order(ed), rData);
2568                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_ALTITUDE,
2569                                                             EXIF_FORMAT_RATIONAL, 1, (unsigned char *)b);
2570                                 free(b);
2571                                 if (ret != MM_ERROR_NONE) {
2572                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_ALTITUDE);
2573                                 }
2574                         } else {
2575                                 _mmcam_dbg_warn("malloc failed");
2576                         }
2577                 }
2578
2579                 /*44. EXIF_TAG_GPS_TIME_STAMP*/
2580                 {
2581                         double gps_timestamp = INVALID_GPS_VALUE;
2582                         mm_camcorder_get_attributes(handle, NULL, "tag-gps-time-stamp", &gps_timestamp, NULL);
2583                         _mmcam_dbg_log("Gps timestamp [%f]", gps_timestamp);
2584                         if (gps_timestamp > 0.0) {
2585                                 unsigned char *b = NULL;
2586                                 unsigned int hour;
2587                                 unsigned int min;
2588                                 unsigned int microsec;
2589                                 ExifRational rData;
2590
2591                                 hour = (unsigned int)(gps_timestamp / 3600);
2592                                 min = (unsigned int)((gps_timestamp - 3600 * hour) / 60);
2593                                 microsec = (unsigned int)(((double)((double)gps_timestamp -(double)(3600 * hour)) -(double)(60 * min)) * 1000000);
2594
2595                                 _mmcam_dbg_log("Gps timestamp hour[%d], min[%d], microsec[%d]", hour, min, microsec);
2596                                 b = malloc(3 * sizeof(ExifRational));
2597                                 if (b) {
2598                                         rData.numerator = hour;
2599                                         rData.denominator = 1;
2600                                         exif_set_rational(b, exif_data_get_byte_order(ed), rData);
2601
2602                                         rData.numerator = min;
2603                                         rData.denominator = 1;
2604                                         exif_set_rational(b + 8, exif_data_get_byte_order(ed), rData);
2605
2606                                         rData.numerator = microsec;
2607                                         rData.denominator = 1000000;
2608                                         exif_set_rational(b + 16, exif_data_get_byte_order(ed), rData);
2609
2610                                         ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_TIME_STAMP,
2611                                                                     EXIF_FORMAT_RATIONAL, 3, b);
2612                                         free(b);
2613                                         if (ret != MM_ERROR_NONE) {
2614                                                 EXIF_SET_ERR(ret, EXIF_TAG_GPS_TIME_STAMP);
2615                                         }
2616                                 } else {
2617                                         _mmcam_dbg_warn( "malloc failed." );
2618                                 }
2619                         }
2620                 }
2621
2622                 /*45. EXIF_TAG_GPS_DATE_STAMP*/
2623                 {
2624                         unsigned char *date_stamp = NULL;
2625                         int date_stamp_len = 0;
2626
2627                         mm_camcorder_get_attributes(handle, NULL, "tag-gps-date-stamp", &date_stamp, &date_stamp_len, NULL);
2628
2629                         if (date_stamp) {
2630                                 _mmcam_dbg_log("Date stamp [%s]", date_stamp);
2631
2632                                 /* cause it should include NULL char */
2633                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_DATE_STAMP,
2634                                                             EXIF_FORMAT_ASCII, date_stamp_len + 1, date_stamp);
2635                                 if (ret != MM_ERROR_NONE) {
2636                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_DATE_STAMP);
2637                                 }
2638                         }
2639                 }
2640
2641                 /*46. EXIF_TAG_GPS_PROCESSING_METHOD */
2642                 {
2643                         unsigned char *processing_method = NULL;
2644                         int processing_method_len = 0;
2645
2646                         mm_camcorder_get_attributes(handle, NULL, "tag-gps-processing-method", &processing_method, &processing_method_len, NULL);
2647
2648                         if (processing_method) {
2649                                 _mmcam_dbg_log("Processing method [%s]", processing_method);
2650
2651                                 ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_PROCESSING_METHOD,
2652                                                             EXIF_FORMAT_UNDEFINED, processing_method_len, processing_method);
2653                                 if (ret != MM_ERROR_NONE) {
2654                                         EXIF_SET_ERR(ret, EXIF_TAG_GPS_PROCESSING_METHOD);
2655                                 }
2656                         }
2657                 }
2658         } else {
2659                 _mmcam_dbg_log( "Tag for GPS is DISABLED." );
2660         }
2661
2662
2663         /*47. EXIF_TAG_MAKER_NOTE*/
2664         ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_MAKER_NOTE,
2665                                     EXIF_FORMAT_UNDEFINED, 8, (unsigned char *)"SAMSUNG");
2666         if (ret != MM_ERROR_NONE) {
2667                 EXIF_SET_ERR(ret, EXIF_TAG_MAKER_NOTE);
2668         }
2669
2670         /* create and link samsung maker note */
2671         ret = mm_exif_mnote_create(ed);
2672         if (ret != MM_ERROR_NONE){
2673                 EXIF_SET_ERR(ret, EXIF_TAG_MAKER_NOTE);
2674         } else {
2675                 _mmcam_dbg_log("Samsung makernote created");
2676
2677                 /* add samsung maker note entries (param : data, tag, index, subtag index1, subtag index2) */
2678                 ret = mm_exif_mnote_set_add_entry(ed, MNOTE_SAMSUNG_TAG_MNOTE_VERSION, 0, _MNOTE_VALUE_NONE, _MNOTE_VALUE_NONE);
2679                 if (ret != MM_ERROR_NONE) {
2680                         _mmcam_dbg_err("mm_exif_mnote_set_add_entry error! [%x]", ret);
2681                 }
2682         /*
2683                 ret = mm_exif_mnote_set_add_entry(ed, MNOTE_SAMSUNG_TAG_DEVICE_ID, 2, _MNOTE_VALUE_NONE, _MNOTE_VALUE_NONE);
2684                 if (ret != MM_ERROR_NONE) {
2685                         _mmcam_dbg_err("mm_exif_mnote_set_add_entry error! [%x]", ret);
2686                 }
2687
2688                 ret = mm_exif_mnote_set_add_entry(ed, MNOTE_SAMSUNG_TAG_SERIAL_NUM, _MNOTE_VALUE_NONE, _MNOTE_VALUE_NONE, _MNOTE_VALUE_NONE);
2689                 if (ret != MM_ERROR_NONE) {
2690                         _mmcam_dbg_err("mm_exif_mnote_set_add_entry error! [%x]", ret);
2691                 }
2692
2693                 ret = mm_exif_mnote_set_add_entry(ed, MNOTE_SAMSUNG_TAG_COLOR_SPACE, 1, _MNOTE_VALUE_NONE, _MNOTE_VALUE_NONE);
2694                 if (ret != MM_ERROR_NONE) {
2695                         _mmcam_dbg_err("mm_exif_mnote_set_add_entry error! [%x]", ret);
2696                 }
2697         */
2698                 ret = mm_exif_mnote_set_add_entry(ed, MNOTE_SAMSUNG_TAG_FACE_DETECTION, 0, _MNOTE_VALUE_NONE, _MNOTE_VALUE_NONE);
2699                 if (ret != MM_ERROR_NONE) {
2700                         _mmcam_dbg_err("mm_exif_mnote_set_add_entry error! ret=%x", ret);
2701                 }
2702         /*
2703                 ret = mm_exif_mnote_set_add_entry(ed, MNOTE_SAMSUNG_TAG_MODEL_ID, _MNOTE_VALUE_NONE, 3, 2);
2704                 if (ret != MM_ERROR_NONE) {
2705                         _mmcam_dbg_err("mm_exif_mnote_set_add_entry error! [%x]", ret);
2706                 }
2707         */
2708         }
2709
2710         _mmcam_dbg_log("");
2711
2712         ret = mm_exif_set_exif_to_info(hcamcorder->exif_info, ed);
2713         if (ret != MM_ERROR_NONE) {
2714                 _mmcam_dbg_err("mm_exif_set_exif_to_info err!! [%x]", ret);
2715         }
2716
2717 exit:
2718         _mmcam_dbg_log("finished!! [%x]", ret);
2719
2720         if (ed) {
2721                 exif_data_unref (ed);
2722         }
2723
2724         return ret;
2725 }
2726
2727
2728 static void __sound_status_changed_cb(keynode_t* node, void *data)
2729 {
2730         mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)data;
2731         _MMCamcorderImageInfo *info = NULL;
2732
2733         mmf_return_if_fail(hcamcorder && hcamcorder->sub_context && hcamcorder->sub_context->info_image);
2734
2735         _mmcam_dbg_log("START");
2736
2737         info = hcamcorder->sub_context->info_image;
2738
2739         __ta__("        GET_IN_CB:VCONFKEY_SETAPPL_SOUND_STATUS_BOOL",
2740         vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &(info->sound_status));
2741         );
2742
2743         _mmcam_dbg_log("DONE : sound status %d", info->sound_status);
2744
2745         return;
2746 }
2747
2748
2749 static void __volume_level_changed_cb(void *data)
2750 {
2751         mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)data;
2752         _MMCamcorderImageInfo *info = NULL;
2753
2754         mmf_return_if_fail(hcamcorder && hcamcorder->sub_context && hcamcorder->sub_context->info_image);
2755
2756         _mmcam_dbg_log("START");
2757
2758         info = hcamcorder->sub_context->info_image;
2759
2760         __ta__("        GET_IN_CB:mm_sound_volume_get_value",
2761         mm_sound_volume_get_value(VOLUME_TYPE_MEDIA, &info->volume_level);
2762         );
2763
2764         _mmcam_dbg_log("DONE : volume level %d", info->volume_level);
2765
2766         return;
2767 }