Update code for encoded preview setting
[platform/core/multimedia/libmm-camcorder.git] / src / mm_camcorder_videorec.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 <gst/video/cameracontrol.h>
26 #include <gst/app/gstappsrc.h>
27 #include "mm_camcorder_internal.h"
28 #include "mm_camcorder_videorec.h"
29
30 /*---------------------------------------------------------------------------------------
31 |    GLOBAL VARIABLE DEFINITIONS for internal                                                                                   |
32 ---------------------------------------------------------------------------------------*/
33 #define _MMCAMCORDER_LOCATION_INFO              /* for add gps information */
34 #define MAX_ERROR_MESSAGE_LEN                   128
35
36 /*---------------------------------------------------------------------------------------
37 |    LOCAL VARIABLE DEFINITIONS for internal                                                                                    |
38 ---------------------------------------------------------------------------------------*/
39 #define _MMCAMCORDER_MINIMUM_FRAME              5
40 #define _MMCAMCORDER_RETRIAL_COUNT              10
41 #define _MMCAMCORDER_FRAME_WAIT_TIME    200000  /* ms */
42 #define _OFFSET_COMPOSITION_MATRIX              40L
43 #define _GOP_GEN_INTERVAL                               1000000000      /*nano seconds*/
44 #define _MMCAMCORDER_VIDEO_MINIMUM_SPACE        (_MMCAMCORDER_MINIMUM_SPACE << 1)      /* byte */
45
46 /*---------------------------------------------------------------------------------------
47 |    LOCAL FUNCTION PROTOTYPES:                                                                                                                 |
48 ---------------------------------------------------------------------------------------*/
49 /* STATIC INTERNAL FUNCTION */
50 static gboolean __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data);
51 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
52 static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
53 static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
54 static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
55 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
56 static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat);
57 static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle);
58
59 /*=======================================================================================
60 |  FUNCTION DEFINITIONS                                                                 |
61 =======================================================================================*/
62 /*---------------------------------------------------------------------------------------
63 |    GLOBAL FUNCTION DEFINITIONS:                                                       |
64 ---------------------------------------------------------------------------------------*/
65 static gboolean __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data)
66 {
67         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
68         _MMCamcorderSubContext *sc = NULL;
69
70         GstBuffer *buffer = gst_sample_get_buffer(sample);
71         mmf_return_val_if_fail(buffer, FALSE);
72         mmf_return_val_if_fail(gst_buffer_n_memory(buffer), FALSE);
73         mmf_return_val_if_fail(hcamcorder, FALSE);
74
75         sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
76         mmf_return_val_if_fail(sc, FALSE);
77
78         /*
79         _mmcam_dbg_log("ENTER - push_encoding_buffer %d, buffer %p, MALLOCDATA %p, size %d",
80                 sc->info_video->push_encoding_buffer, buffer, GST_BUFFER_MALLOCDATA(buffer), GST_BUFFER_SIZE(buffer));
81         */
82
83         /* push buffer in appsrc to encode */
84         if (sc->info_video->push_encoding_buffer == PUSH_ENCODING_BUFFER_RUN &&
85             sc->info_video->record_dual_stream &&
86             sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst) {
87                 GstFlowReturn ret = 0;
88                 GstClock *pipe_clock = NULL;
89
90                 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst) {
91                         if (sc->info_video->is_firstframe) {
92                                 sc->info_video->is_firstframe = FALSE;
93                                 pipe_clock = GST_ELEMENT_CLOCK(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst);
94                                 if (pipe_clock) {
95                                         gst_object_ref(pipe_clock);
96                                         sc->info_video->base_video_ts = GST_BUFFER_PTS(buffer) - (gst_clock_get_time(pipe_clock) - GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst)->base_time);
97                                         gst_object_unref(pipe_clock);
98                                 }
99                         }
100                 } else {
101                         if (sc->info_video->is_firstframe) {
102                                 sc->info_video->is_firstframe = FALSE;
103                                 sc->info_video->base_video_ts = GST_BUFFER_PTS(buffer);
104                         }
105                 }
106
107                 GST_BUFFER_PTS(buffer) = GST_BUFFER_PTS(buffer) - sc->info_video->base_video_ts;
108                 GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer);
109
110                 ret = gst_app_src_push_buffer((GstAppSrc *)sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, buffer);
111                 if (ret != GST_FLOW_OK && ret != GST_FLOW_FLUSHING) {
112                         _mmcam_dbg_err("gst_app_src_push_buffer failed [0x%x]", ret);
113                         gst_buffer_unref(buffer);
114                         buffer = NULL;
115                 }
116
117                 /*_mmcam_dbg_log("push buffer result : 0x%x", ret);*/
118         } else {
119                 _mmcam_dbg_warn("unref video buffer immediately - push encoding buffer %d",
120                         sc->info_video->push_encoding_buffer);
121
122                 gst_buffer_unref(buffer);
123                 buffer = NULL;
124         }
125
126         return TRUE;
127 }
128
129
130 int _mmcamcorder_create_recorder_pipeline(MMHandleType handle)
131 {
132         int i = 0;
133         int err = MM_ERROR_NONE;
134         const char* gst_element_rsink_name = NULL;
135
136         GstBus *bus = NULL;
137         GstPad *srcpad = NULL;
138         GstPad *sinkpad = NULL;
139
140         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
141         _MMCamcorderSubContext *sc = NULL;
142
143         type_element *RecordsinkElement = NULL;
144
145         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
146
147         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
148         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
149         mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
150
151         _mmcam_dbg_warn("start");
152
153         err = _mmcamcorder_check_videocodec_fileformat_compatibility(handle);
154         if (err != MM_ERROR_NONE)
155                 return err;
156
157         /* Main pipeline */
158         if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst) {
159                 _mmcam_dbg_log("pipeline is exist so need to remove pipeline _MMCAMCORDER_ENCODE_MAIN_PIPE = %p",
160                         sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst);
161                 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
162         }
163
164         _MMCAMCORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCODE_MAIN_PIPE, "recorder_pipeline", err);
165
166         /* get audio disable */
167         mm_camcorder_get_attributes(handle, NULL,
168                 MMCAM_AUDIO_DISABLE, &sc->audio_disable,
169                 NULL);
170
171         _mmcam_dbg_log("MMCAM_AUDIO_DISABLE %d, is_modified_rate %d",
172                 sc->audio_disable, sc->is_modified_rate);
173
174         sc->audio_disable |= sc->is_modified_rate;
175
176         if (sc->audio_disable == FALSE) {
177                 /* create audiosrc bin */
178                 err = _mmcamcorder_create_audiosrc_bin((MMHandleType)hcamcorder);
179                 if (err != MM_ERROR_NONE)
180                         return err;
181         }
182
183         err = _mmcamcorder_create_encodesink_bin((MMHandleType)hcamcorder, MM_CAMCORDER_ENCBIN_PROFILE_VIDEO);
184         if (err != MM_ERROR_NONE)
185                 return err;
186
187         if (sc->audio_disable == FALSE) {
188                 gst_bin_add(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
189                         sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
190         }
191
192         /* add element and encodesink bin to encode main pipeline */
193         gst_bin_add_many(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
194                 sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst,
195                 sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst,
196                 sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst,
197                 NULL);
198
199         /* Link each element : appsrc - capsfilter - encodesink bin */
200         srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, "src");
201         sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "sink");
202         _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
203
204         srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "src");
205         sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "video_sink0");
206         _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
207
208         if (sc->audio_disable == FALSE) {
209                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
210                 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
211                 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
212         }
213
214         _mmcamcorder_conf_get_element(handle, hcamcorder->conf_main,
215                 CONFIGURE_CATEGORY_MAIN_RECORD,
216                 "RecordsinkElement",
217                 &RecordsinkElement);
218         _mmcamcorder_conf_get_value_element_name(RecordsinkElement, &gst_element_rsink_name);
219
220         if (!gst_element_rsink_name) {
221                 _mmcam_dbg_err("failed to get recordsink name");
222                 err = MM_ERROR_CAMCORDER_INTERNAL;
223                 goto pipeline_creation_error;
224         }
225
226         /* set data probe function */
227
228         /* register message cb */
229
230         /* set data probe functions */
231         if (sc->audio_disable == FALSE) {
232                 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "sink");
233                 MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
234                         __mmcamcorder_audioque_dataprobe, hcamcorder);
235                 gst_object_unref(sinkpad);
236                 sinkpad = NULL;
237
238                 /* for voice mute */
239                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, "src");
240                 MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
241                         __mmcamcorder_audio_dataprobe_audio_mute, hcamcorder);
242                 gst_object_unref(srcpad);
243                 srcpad = NULL;
244
245                 if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst) {
246                         srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "src");
247                         MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
248                                 __mmcamcorder_eventprobe_monitor, hcamcorder);
249                         gst_object_unref(srcpad);
250                         srcpad = NULL;
251                 }
252         }
253
254         if (sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst) {
255                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "src");
256                 MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
257                         __mmcamcorder_eventprobe_monitor, hcamcorder);
258                 gst_object_unref(srcpad);
259                 srcpad = NULL;
260         }
261
262         if (sc->audio_disable) {
263                 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC].gst, "sink");
264                 MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
265                         __mmcamcorder_video_dataprobe_audio_disable, hcamcorder);
266                 gst_object_unref(sinkpad);
267                 sinkpad = NULL;
268         }
269
270         if (!strcmp(gst_element_rsink_name, "filesink")) {
271                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC].gst, "src");
272                 MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
273                         __mmcamcorder_video_dataprobe_record, hcamcorder);
274                 gst_object_unref(srcpad);
275                 srcpad = NULL;
276
277                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
278                 MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
279                         __mmcamcorder_audio_dataprobe_check, hcamcorder);
280                 gst_object_unref(srcpad);
281                 srcpad = NULL;
282         }
283
284         sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "sink");
285         MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
286                 __mmcamcorder_muxed_dataprobe, hcamcorder);
287         MMCAMCORDER_ADD_EVENT_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
288                 __mmcamcorder_eventprobe_monitor, hcamcorder);
289         gst_object_unref(sinkpad);
290         sinkpad = NULL;
291
292         bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst));
293
294         /* register pipeline message callback */
295         hcamcorder->encode_pipeline_cb_event_id = gst_bus_add_watch(bus, (GstBusFunc)_mmcamcorder_pipeline_cb_message, hcamcorder);
296
297         /* set sync handler */
298         gst_bus_set_sync_handler(bus, _mmcamcorder_encode_pipeline_bus_sync_callback, (gpointer)hcamcorder, NULL);
299
300         gst_object_unref(bus);
301         bus = NULL;
302
303         return MM_ERROR_NONE;
304
305 pipeline_creation_error:
306         for (i = _MMCAMCORDER_AUDIOSRC_BIN ; i <= _MMCAMCORDER_ENCSINK_SINK ; i++)
307                 _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, i);
308
309         _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_ENCODE_MAIN_PIPE);
310         return err;
311 }
312
313
314 int _mmcamcorder_remove_audio_pipeline(MMHandleType handle)
315 {
316         GstPad *srcpad = NULL;
317         GstPad *sinkpad = NULL;
318         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
319         _MMCamcorderSubContext *sc = NULL;
320
321         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
322
323         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
324         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
325         mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
326
327         _mmcam_dbg_log("");
328
329         if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst != NULL) {
330                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
331                 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
332                 _MM_GST_PAD_UNLINK_UNREF(srcpad, sinkpad);
333
334                 /* release audiosrc bin */
335                 gst_bin_remove(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
336                         sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
337
338                 /*
339                         To avoid conflicting between old elements and newly created elements,
340                         I clean element handles here. Real elements object will be finalized as the 'unref' process goes on.
341                         This is a typical problem of unref. Even though I unref bin here, it takes much time to finalize each elements.
342                         So I clean handles first, make them unref later. Audio recording, however, isn't needed this process.
343                         It's because the pipeline of audio recording destroys at the same time,
344                         and '_mmcamcorder_element_release_noti' will perfom removing handle.
345                 */
346                 _mmcamcorder_remove_element_handle(handle, (void *)sc->encode_element, _MMCAMCORDER_AUDIOSRC_BIN, _MMCAMCORDER_AUDIOSRC_VOL);
347
348                 _mmcam_dbg_log("Audio pipeline removed");
349         }
350
351         return MM_ERROR_NONE;
352 }
353
354
355 int _mmcamcorder_remove_encode_pipeline(MMHandleType handle)
356 {
357         GstPad *reqpad = NULL;
358         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
359         _MMCamcorderSubContext *sc = NULL;
360 #ifdef _MMCAMCORDER_MM_RM_SUPPORT
361         int ret = MM_ERROR_NONE;
362 #endif /* _MMCAMCORDER_MM_RM_SUPPORT */
363
364         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
365
366         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
367         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
368         mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
369
370         _mmcam_dbg_log("");
371
372         if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst != NULL) {
373                 /* release request pad */
374                 reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "audio");
375                 if (reqpad) {
376                         gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
377                         gst_object_unref(reqpad);
378                         reqpad = NULL;
379                 }
380
381                 reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "video");
382                 if (reqpad) {
383                         gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
384                         gst_object_unref(reqpad);
385                         reqpad = NULL;
386                 }
387
388                 /* release encode main pipeline */
389                 gst_object_unref(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst);
390
391                 /*
392                         To avoid conflicting between old elements and newly created elements,
393                         I clean element handles here. Real elements object will be finalized as the 'unref' process goes on.
394                         This is a typical problem of unref. Even though I unref bin here, it takes much time to finalize each elements.
395                         So I clean handles first, make them unref later. Audio recording, however, isn't needed this process.
396                         It's because the pipeline of audio recording destroys at the same time,
397                         and '_mmcamcorder_element_release_noti' will perfom removing handle.
398                 */
399                 /* _mmcamcorder_remove_element_handle(handle, (void *)sc->encode_element,
400                         _MMCAMCORDER_ENCODE_MAIN_PIPE, _MMCAMCORDER_ENCSINK_SINK); */
401
402                 _mmcam_dbg_warn("Encoder pipeline removed");
403
404 #ifdef _MMCAMCORDER_MM_RM_SUPPORT
405                 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
406
407                 _mmcam_dbg_warn("lock resource - cb calling %d", hcamcorder->is_release_cb_calling);
408
409                 if (hcamcorder->is_release_cb_calling == FALSE) {
410                         /* release resource */
411                         ret = mm_resource_manager_mark_for_release(hcamcorder->resource_manager,
412                                         hcamcorder->video_encoder_resource);
413                         if (ret == MM_RESOURCE_MANAGER_ERROR_NONE)
414                                 hcamcorder->video_encoder_resource = NULL;
415
416                         _mmcam_dbg_warn("mark resource for release 0x%x", ret);
417
418                         ret = mm_resource_manager_commit(hcamcorder->resource_manager);
419
420                         _mmcam_dbg_warn("commit resource release 0x%x", ret);
421                 }
422
423                 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
424
425                 _mmcam_dbg_warn("unlock resource");
426 #endif /* _MMCAMCORDER_MM_RM_SUPPORT */
427         }
428
429         return MM_ERROR_NONE;
430 }
431
432
433 int _mmcamcorder_remove_recorder_pipeline(MMHandleType handle)
434 {
435         int ret = MM_ERROR_NONE;
436         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
437         _MMCamcorderSubContext *sc = NULL;
438
439         GstBus *bus = NULL;
440
441         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
442         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
443         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
444
445         _mmcam_dbg_log("start");
446
447         if (!sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst) {
448                 _mmcam_dbg_warn("pipeline is not existed.");
449                 return MM_ERROR_NONE;
450         }
451
452         _mmcamcorder_remove_all_handlers((MMHandleType)hcamcorder, _MMCAMCORDER_HANDLER_VIDEOREC);
453
454         ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_NULL);
455         if (ret != MM_ERROR_NONE) {
456                 _mmcam_dbg_err("Faile to change encode main pipeline [0x%x]", ret);
457                 return ret;
458         }
459
460         bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst));
461
462         /* remove audio pipeline first */
463         ret = _mmcamcorder_remove_audio_pipeline(handle);
464         if (ret != MM_ERROR_NONE) {
465                 _mmcam_dbg_err("Fail to remove audio pipeline");
466                 return ret;
467         }
468
469         ret = _mmcamcorder_remove_encode_pipeline(handle);
470         if (ret != MM_ERROR_NONE) {
471                 _mmcam_dbg_err("Fail to remove encoder pipeline");
472                 return ret;
473         }
474
475         /* Remove pipeline message callback */
476         if (hcamcorder->encode_pipeline_cb_event_id != 0) {
477                 g_source_remove(hcamcorder->encode_pipeline_cb_event_id);
478                 hcamcorder->encode_pipeline_cb_event_id = 0;
479         }
480
481         /* Remove remained message */
482         if (bus) {
483                 GstMessage *gst_msg = NULL;
484                 while ((gst_msg = gst_bus_pop(bus)) != NULL) {
485                         _mmcamcorder_pipeline_cb_message(bus, gst_msg, (gpointer)hcamcorder);
486                         gst_message_unref(gst_msg);
487                         gst_msg = NULL;
488                 }
489                 gst_object_unref(bus);
490                 bus = NULL;
491         }
492
493         _mmcam_dbg_log("done");
494
495         return ret;
496 }
497
498
499 int _mmcamcorder_video_command(MMHandleType handle, int command)
500 {
501         int size = 0;
502         int fileformat = 0;
503         int count = 0;
504         int gop_interval = 0;
505         int ret = MM_ERROR_NONE;
506         double motion_rate = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE;
507         char *err_name = NULL;
508         char *target_filename = NULL;
509         GstCameraControl *CameraControl = NULL;
510
511         gint fps = 0;
512         GstElement *pipeline = NULL;
513
514         _MMCamcorderVideoInfo *info = NULL;
515         _MMCamcorderSubContext *sc = NULL;
516         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
517
518         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
519
520         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
521         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
522         mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
523         mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
524
525         info = sc->info_video;
526
527         _mmcam_dbg_log("Command(%d)", command);
528
529         pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
530
531         switch (command) {
532         case _MMCamcorder_CMD_RECORD:
533         {
534                 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) != MM_CAMCORDER_STATE_PAUSED) {
535                         /**
536                          * start recording
537                          */
538                         gboolean storage_validity = FALSE;
539                         guint imax_size = 0;
540                         guint imax_time = 0;
541                         int root_directory_length = 0;
542
543                         /* Recording */
544                         _mmcam_dbg_log("Record Start - dual stream %d", info->support_dual_stream);
545
546 #ifdef _MMCAMCORDER_MM_RM_SUPPORT
547                         _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
548
549                         /* prepare resource manager for H/W encoder */
550                         if (hcamcorder->video_encoder_resource == NULL) {
551                                 ret = mm_resource_manager_mark_for_acquire(hcamcorder->resource_manager,
552                                                 MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_ENCODER,
553                                                 MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
554                                                 &hcamcorder->video_encoder_resource);
555                                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
556                                         _mmcam_dbg_err("could not prepare for encoder resource");
557                                         ret = MM_ERROR_RESOURCE_INTERNAL;
558                                         _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
559                                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
560                                 }
561                         } else {
562                                 _mmcam_dbg_log("encoder already acquired");
563                         }
564
565                         /* acquire resources */
566                         ret = mm_resource_manager_commit(hcamcorder->resource_manager);
567                         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
568                                 _mmcam_dbg_err("could not acquire resources");
569                                 ret = MM_ERROR_RESOURCE_INTERNAL;
570                                 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
571                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
572                         }
573
574                         _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
575 #endif /* _MMCAMCORDER_MM_RM_SUPPORT */
576
577                         /* init record_dual_stream */
578                         info->record_dual_stream = FALSE;
579
580                         ret = mm_camcorder_get_attributes(handle, &err_name,
581                                 MMCAM_CAMERA_FPS, &fps,
582                                 MMCAM_CAMERA_WIDTH, &(info->preview_width),
583                                 MMCAM_CAMERA_HEIGHT, &(info->preview_height),
584                                 MMCAM_VIDEO_WIDTH, &(info->video_width),
585                                 MMCAM_VIDEO_HEIGHT, &(info->video_height),
586                                 MMCAM_FILE_FORMAT, &fileformat,
587                                 MMCAM_TARGET_FILENAME, &target_filename, &size,
588                                 MMCAM_TARGET_MAX_SIZE, &imax_size,
589                                 MMCAM_TARGET_TIME_LIMIT, &imax_time,
590                                 MMCAM_FILE_FORMAT, &(info->fileformat),
591                                 MMCAM_CAMERA_RECORDING_MOTION_RATE, &motion_rate,
592                                 MMCAM_ROOT_DIRECTORY, &hcamcorder->root_directory, &root_directory_length,
593                                 NULL);
594                         if (ret != MM_ERROR_NONE) {
595                                 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, ret);
596                                 SAFE_FREE(err_name);
597                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
598                         }
599
600                         if (!target_filename && !hcamcorder->mstream_cb) {
601                                 _mmcam_dbg_err("filename is not set and muxed stream cb is NULL");
602                                 ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
603                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
604                         }
605
606                         /* set max size */
607                         if (imax_size <= 0)
608                                 info->max_size = 0; /* do not check */
609                         else
610                                 info->max_size = ((guint64)imax_size) << 10; /* to byte */
611
612                         /* set max time */
613                         if (imax_time <= 0)
614                                 info->max_time = 0; /* do not check */
615                         else
616                                 info->max_time = (guint64)((double)imax_time * (double)1000 * motion_rate); /* to millisecond */
617
618                         ret = _mmcamcorder_get_storage_validity(hcamcorder, target_filename,
619                                 _MMCAMCORDER_VIDEO_MINIMUM_SPACE, &storage_validity);
620                         if (ret != MM_ERROR_NONE) {
621                                 _mmcam_dbg_err("storage validation failed[0x%x]:%d", ret, storage_validity);
622                                 return ret;
623                         }
624
625                         _mmcamcorder_adjust_recording_max_size(target_filename, &info->max_size);
626
627                         g_mutex_lock(&hcamcorder->task_thread_lock);
628                         if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst == NULL &&
629                             hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) {
630                                 /* Play record start sound */
631                                 _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_START, FALSE);
632                         }
633                         g_mutex_unlock(&hcamcorder->task_thread_lock);
634
635                         _mmcam_dbg_warn("video size [%dx%d]", info->video_width, info->video_height);
636
637                         if (info->video_width == 0 || info->video_height == 0) {
638                                 _mmcam_dbg_warn("video size is invalid [%dx%d] use preview size [%dx%d]",
639                                         info->video_width, info->video_height, info->preview_width, info->preview_height);
640                                 info->video_width = info->preview_width;
641                                 info->video_height = info->preview_height;
642                         }
643
644                         if (info->support_dual_stream) {
645                                 _mmcam_dbg_warn("DUAL STREAM MODE");
646
647                                 info->record_dual_stream = TRUE;
648
649                                 /* No need to restart preview */
650                                 info->restart_preview = FALSE;
651
652                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-width", info->video_width);
653                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-height", info->video_height);
654                         } else if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
655                                 info->preview_width == info->video_width &&
656                                 info->preview_height == info->video_height) {
657                                 _mmcam_dbg_log("H264 preview mode and same resolution");
658
659                                 /* No need to restart preview */
660                                 info->restart_preview = FALSE;
661                         } else {
662                                 /* always need to restart preview  */
663                                 info->restart_preview = TRUE;
664                         }
665
666                         /* set recording hint */
667                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", TRUE);
668
669                         if (info->restart_preview) {
670                                 /* stop preview and set new size */
671                                 _mmcam_dbg_log("restart preview");
672
673                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
674                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
675                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
676
677                                 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
678
679                                 /* check decoder recreation */
680                                 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
681                                         _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
682                                         ret = MM_ERROR_CAMCORDER_INTERNAL;
683                                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
684                                 }
685
686                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
687                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
688                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
689
690                                 if (ret != MM_ERROR_NONE)
691                                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
692
693                                 if (!_mmcamcorder_set_camera_resolution(handle, info->video_width, info->video_height)) {
694                                         ret = MM_ERROR_CAMCORDER_INTERNAL;
695                                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
696                                 }
697
698                                 /* Start preview again with new setting */
699                                 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
700                                 if (ret != MM_ERROR_NONE)
701                                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
702
703                                 if (motion_rate < 1.0) {
704                                         _mmcam_dbg_warn("wait for stabilization of frame");
705                                         usleep(300000);
706                                 }
707                         } else {
708                                 _mmcam_dbg_log("no need to restart preview");
709                         }
710
711                         _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
712                                 CONFIGURE_CATEGORY_MAIN_RECORD,
713                                 "DropVideoFrame",
714                                 &(sc->drop_vframe));
715
716                         _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
717                                 CONFIGURE_CATEGORY_MAIN_RECORD,
718                                 "PassFirstVideoFrame",
719                                 &(sc->pass_first_vframe));
720
721                         _mmcam_dbg_log("Drop video frame count[%d], Pass fisrt video frame count[%d]",
722                                 sc->drop_vframe, sc->pass_first_vframe);
723
724                         info->record_drop_count = (guint)motion_rate;
725                         info->record_motion_rate = motion_rate;
726                         if (sc->is_modified_rate)
727                                 info->record_timestamp_ratio = (_MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE/motion_rate);
728                         else
729                                 info->record_timestamp_ratio = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE;
730
731                         _mmcam_dbg_warn("recording fps %d, motion rate %f, timestamp_ratio %f",
732                                 fps, info->record_motion_rate, info->record_timestamp_ratio);
733
734                         /* set push buffer flag */
735                         info->push_encoding_buffer = PUSH_ENCODING_BUFFER_INIT;
736                         info->base_video_ts = 0;
737
738                         /* connect video stream cb signal */
739                         /*130826 Connect video stream cb for handling fast record frame cb*/
740                         if (info->record_dual_stream) {
741                                 if (_mmcamcorder_connect_video_stream_cb_signal((MMHandleType)hcamcorder) != MM_ERROR_NONE)
742                                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
743                         }
744
745                         /* start video stream */
746                         if (info->record_dual_stream) {
747                                 CameraControl =  GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
748                                 if (CameraControl) {
749                                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
750
751                                         _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_START");
752                                         gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_START);
753
754                                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
755                                 } else {
756                                         _mmcam_dbg_err("could not get camera control");
757                                 }
758                         }
759
760                         /* check pre-created encode pipeline */
761                         g_mutex_lock(&hcamcorder->task_thread_lock);
762                         if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst == NULL &&
763                             hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) {
764                                 /* create encoding pipeline */
765                                 ret = _mmcamcorder_video_prepare_record((MMHandleType)hcamcorder);
766                                 if (ret != MM_ERROR_NONE) {
767                                         g_mutex_unlock(&hcamcorder->task_thread_lock);
768                                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
769                                 }
770                         }
771                         g_mutex_unlock(&hcamcorder->task_thread_lock);
772
773                         /* check recording start sound */
774                         _mmcamcorder_sound_solo_play_wait(handle);
775
776                         /**< To fix video recording hanging
777                                 1. use gst_element_set_start_time() instead of gst_pipeline_set_new_stream_time()
778                                 2. Set (GstClockTime)1 instead of (GstClockTime)0. Because of strict check in gstreamer 0.25,
779                                  basetime wouldn't change if you set (GstClockTime)0.
780                                 3. Move set start time position below PAUSED of pipeline.
781                         */
782                         /*
783                         gst_element_set_start_time(GST_ELEMENT(sc->element[_MMCAMCORDER_MAIN_PIPE].gst), (GstClockTime)1);
784                         gst_element_set_start_time(GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst), (GstClockTime)1);
785                         */
786
787                         info->video_frame_count = 0;
788                         info->is_firstframe = TRUE;
789                         info->audio_frame_count = 0;
790                         info->filesize = 0;
791                         sc->ferror_send = FALSE;
792                         sc->ferror_count = 0;
793                         hcamcorder->error_occurs = FALSE;
794                         sc->bget_eos = FALSE;
795                         sc->muxed_stream_offset = 0;
796
797                         ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PLAYING);
798                         if (ret != MM_ERROR_NONE) {
799                                 /* stop video stream */
800                                 if (info->record_dual_stream) {
801                                         CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
802                                         if (CameraControl) {
803                                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
804
805                                                 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
806                                                 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
807
808                                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
809                                         } else {
810                                                 _mmcam_dbg_err("failed to get camera control");
811                                         }
812                                 }
813
814                                 /* Remove recorder pipeline and recording file which size maybe zero */
815                                 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
816                                 if (info->filename) {
817                                         _mmcam_dbg_log("file delete(%s)", info->filename);
818                                         unlink(info->filename);
819                                 }
820                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
821                         }
822
823                         /*set the GOP so that video record will get a new key frame*/
824                         if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) {
825                                 if (mm_camcorder_get_attributes(handle, NULL,
826                                         MMCAM_ENCODED_PREVIEW_GOP_INTERVAL, &gop_interval, NULL) == MM_ERROR_NONE)
827                                         _mmcamcorder_set_encoded_preview_gop_interval(handle, gop_interval);
828                                 else
829                                         _mmcam_dbg_err("get gop interval failed");
830                         }
831                 } else {
832                         /* Resume case */
833                         if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) {
834                                 if (mm_camcorder_get_attributes(handle, NULL,
835                                         MMCAM_ENCODED_PREVIEW_GOP_INTERVAL, &gop_interval, NULL) == MM_ERROR_NONE)
836                                         _mmcamcorder_set_encoded_preview_gop_interval(handle, gop_interval);
837                                 else
838                                         _mmcam_dbg_err("get gop interval failed");
839                         }
840
841                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", FALSE);
842
843                         _mmcam_dbg_log("Object property settings done");
844                 }
845         }
846                 break;
847         case _MMCamcorder_CMD_PAUSE:
848         {
849                 if (info->b_commiting) {
850                         _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
851                         return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
852                 }
853
854                 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
855                         if (sc->audio_disable) {
856                                 /* check only video frame */
857                                 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
858                                         break;
859                                 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
860                                         _mmcam_dbg_err("Pause fail, frame count %"G_GUINT64_FORMAT, info->video_frame_count);
861                                         return MM_ERROR_CAMCORDER_INVALID_CONDITION;
862                                 } else {
863                                         _mmcam_dbg_warn("Waiting for enough video frame, retrial[%d], frame %"G_GUINT64_FORMAT, count, info->video_frame_count);
864                                 }
865
866                                 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
867                         } else {
868                                 /* check both of video and audio frame */
869                                 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
870                                         break;
871                                 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
872                                         _mmcam_dbg_err("Pause fail, frame count VIDEO[%"G_GUINT64_FORMAT"], AUDIO [%"G_GUINT64_FORMAT"]",
873                                                 info->video_frame_count, info->audio_frame_count);
874                                         return MM_ERROR_CAMCORDER_INVALID_CONDITION;
875                                 } else {
876                                         _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%"G_GUINT64_FORMAT"], AUDIO [%"G_GUINT64_FORMAT"]",
877                                                 count, info->video_frame_count, info->audio_frame_count);
878                                 }
879
880                                 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
881                         }
882                 }
883
884                 /* block encodebin */
885                 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", TRUE);
886                 break;
887         }
888         case _MMCamcorder_CMD_CANCEL:
889         {
890                 if (info->b_commiting) {
891                         _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
892                         return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
893                 }
894
895                 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
896                         /* capturing */
897                         if (hcamcorder->capture_in_recording == FALSE) {
898                                 break;
899                         } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
900                                 _mmcam_dbg_err("Failed to Wait capture data");
901                                 hcamcorder->capture_in_recording = FALSE;
902                                 break;
903                         } else {
904                                 _mmcam_dbg_warn("Waiting for capture data - retrial [%d]", count);
905                         }
906
907                         usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
908                 }
909
910                 /* block push buffer */
911                 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
912
913                 ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
914                 if (ret != MM_ERROR_NONE)
915                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
916
917                 /* set recording hint */
918                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
919
920                 /* stop video stream */
921                 if (info->record_dual_stream) {
922                         CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
923                         if (CameraControl) {
924                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
925
926                                 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
927                                 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
928
929                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
930                         } else {
931                                 _mmcam_dbg_err("failed to get camera control");
932                         }
933                 }
934
935                 if (info->restart_preview) {
936                         /* restart preview */
937                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
938                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
939                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
940
941                         ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
942
943                         /* check decoder recreation */
944                         if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
945                                 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
946                                 ret = MM_ERROR_CAMCORDER_INTERNAL;
947                         }
948
949                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
950                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
951                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
952
953                         if (ret != MM_ERROR_NONE)
954                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
955
956                         /* reset restart_preview for inset window layout */
957                         info->restart_preview = FALSE;
958
959                         if (!_mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height)) {
960                                 ret = MM_ERROR_CAMCORDER_INTERNAL;
961                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
962                         }
963
964                         ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
965                         if (ret != MM_ERROR_NONE)
966                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
967                 }
968
969                 /* remove target file */
970                 if (info->filename) {
971                         _mmcam_dbg_log("file delete(%s)", info->filename);
972                         unlink(info->filename);
973                 }
974
975                 sc->isMaxsizePausing = FALSE;
976                 sc->isMaxtimePausing = FALSE;
977
978                 sc->display_interval = 0;
979                 sc->previous_slot_time = 0;
980                 info->video_frame_count = 0;
981                 info->audio_frame_count = 0;
982                 info->filesize = 0;
983                 hcamcorder->capture_in_recording = FALSE;
984                 break;
985         }
986         case _MMCamcorder_CMD_COMMIT:
987         {
988                 guint64 free_space;
989
990                 if (info->b_commiting) {
991                         _mmcam_dbg_err("now on commiting previous file!!(command : %d)", command);
992                         return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
993                 } else {
994                         _mmcam_dbg_log("_MMCamcorder_CMD_COMMIT : start");
995                         info->b_commiting = TRUE;
996                         sc->bget_eos = FALSE;
997                 }
998
999                 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
1000                         if (sc->audio_disable) {
1001                                 /* check only video frame */
1002                                 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
1003                                     hcamcorder->capture_in_recording == FALSE) {
1004                                         break;
1005                                 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
1006                                         _mmcam_dbg_err("Commit fail, frame count is %"G_GUINT64_FORMAT", capturing %d",
1007                                                 info->video_frame_count, hcamcorder->capture_in_recording);
1008
1009                                         if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
1010                                                 _mmcam_dbg_warn("video frames are enough. keep going...");
1011                                         } else {
1012                                                 info->b_commiting = FALSE;
1013                                                 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1014                                         }
1015                                 } else {
1016                                         _mmcam_dbg_warn("Waiting for enough video frame, retrial [%d], frame %"G_GUINT64_FORMAT", capturing %d",
1017                                                 count, info->video_frame_count, hcamcorder->capture_in_recording);
1018                                 }
1019                         } else {
1020                                 /* check both of video and audio frame */
1021                                 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
1022                                     info->audio_frame_count &&
1023                                     hcamcorder->capture_in_recording == FALSE) {
1024                                         break;
1025                                 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
1026                                         _mmcam_dbg_err("Commit fail, VIDEO[%"G_GUINT64_FORMAT"], AUDIO [%"G_GUINT64_FORMAT"], capturing %d",
1027                                                 info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
1028
1029                                         if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
1030                                                 _mmcam_dbg_warn("video/audio frames are enough. keep going...");
1031                                         } else {
1032                                                 info->b_commiting = FALSE;
1033                                                 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1034                                         }
1035
1036                                         return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1037                                 } else {
1038                                         _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%"G_GUINT64_FORMAT"], AUDIO [%"G_GUINT64_FORMAT"], capturing %d",
1039                                                 count, info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
1040                                 }
1041                         }
1042
1043                         if (hcamcorder->capture_in_recording) {
1044                                 gint64 end_time = g_get_monotonic_time() + (200 * G_TIME_SPAN_MILLISECOND);
1045                                 if (!_MMCAMCORDER_CMD_WAIT_UNTIL(handle, end_time))
1046                                         _mmcam_dbg_warn("timeout");
1047                         } else {
1048                                 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
1049                         }
1050                 }
1051
1052                 /* block push buffer */
1053                 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
1054                 _mmcam_dbg_log("block push buffer to appsrc");
1055
1056                 _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
1057                 if (free_space < _MMCAMCORDER_MINIMUM_SPACE) {
1058                         _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT out of storage [%" G_GUINT64_FORMAT "]", free_space);
1059                         ret = MM_ERROR_OUT_OF_STORAGE;
1060                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
1061                 }
1062
1063                 if (sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst != NULL) {
1064                         if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, gst_event_new_eos())) {
1065                                 _mmcam_dbg_warn("VIDEO: send eos to appsrc done");
1066                         } else {
1067                                 _mmcam_dbg_err("VIDEO: send EOS failed");
1068                                 info->b_commiting = FALSE;
1069                                 ret = MM_ERROR_CAMCORDER_INTERNAL;
1070                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1071                         }
1072                 } else {
1073                         _mmcam_dbg_err("No video stream source");
1074                         info->b_commiting = FALSE;
1075                         ret = MM_ERROR_CAMCORDER_INTERNAL;
1076                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
1077                 }
1078
1079                 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst != NULL) {
1080                         if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos())) {
1081                                 _mmcam_dbg_warn("AUDIO: send eos to audiosrc done");
1082                         } else {
1083                                 _mmcam_dbg_err("AUDIO: send EOS failed");
1084                                 info->b_commiting = FALSE;
1085                                 ret = MM_ERROR_CAMCORDER_INTERNAL;
1086                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1087                         }
1088                 } else {
1089                         _mmcam_dbg_log("No audio stream");
1090                 }
1091
1092                 /* sc */
1093                 sc->display_interval = 0;
1094                 sc->previous_slot_time = 0;
1095
1096                 /* Wait EOS */
1097                 _mmcam_dbg_log("Start to wait EOS");
1098                 ret = _mmcamcorder_get_eos_message(handle);
1099                 if (ret != MM_ERROR_NONE) {
1100                         info->b_commiting = FALSE;
1101                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
1102                 }
1103
1104                 /* reset flag */
1105                 hcamcorder->capture_in_recording = FALSE;
1106         }
1107                 break;
1108         default:
1109                 ret =  MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
1110                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1111         }
1112
1113         return MM_ERROR_NONE;
1114
1115 _ERR_CAMCORDER_VIDEO_COMMAND:
1116         if (command == _MMCamcorder_CMD_RECORD)
1117                 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1118
1119         return ret;
1120 }
1121
1122
1123 int _mmcamcorder_video_handle_eos(MMHandleType handle)
1124 {
1125         int ret = MM_ERROR_NONE;
1126         int enabletag = 0;
1127         guint64 file_size = 0;
1128
1129         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1130         _MMCamcorderSubContext *sc = NULL;
1131         _MMCamcorderVideoInfo *info = NULL;
1132         _MMCamcorderMsgItem msg;
1133         MMCamRecordingReport *report = NULL;
1134
1135         mmf_return_val_if_fail(hcamcorder, FALSE);
1136
1137         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1138         mmf_return_val_if_fail(sc, FALSE);
1139         mmf_return_val_if_fail(sc->info_video, FALSE);
1140
1141         info = sc->info_video;
1142
1143         _mmcam_dbg_err("");
1144
1145         /* Play record stop sound */
1146         _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, FALSE);
1147
1148         /* remove blocking part */
1149         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1150
1151         mm_camcorder_get_attributes(handle, NULL,
1152                 MMCAM_RECORDER_TAG_ENABLE, &enabletag,
1153                 NULL);
1154
1155         ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1156         if (ret != MM_ERROR_NONE)
1157                 _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline failed. error[%x]", ret);
1158
1159         /* set recording hint */
1160         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
1161
1162         /* stop video stream */
1163         if (info->record_dual_stream) {
1164                 GstCameraControl *control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
1165                 if (control) {
1166                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
1167
1168                         _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
1169                         gst_camera_control_set_record_command(control, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
1170
1171                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
1172                 } else {
1173                         _mmcam_dbg_err("failed to get camera control");
1174                 }
1175         }
1176
1177         if (enabletag && !(sc->ferror_send)) {
1178                 ret = __mmcamcorder_add_metadata((MMHandleType)hcamcorder, info->fileformat);
1179                 _mmcam_dbg_log("Writing location information [%s] !!", ret ? "SUCCEEDED" : "FAILED");
1180         }
1181
1182         /* Check file size */
1183         if (info->max_size > 0) {
1184                 _mmcamcorder_get_file_size(info->filename, &file_size);
1185                 _mmcam_dbg_log("MAX size %"G_GUINT64_FORMAT" byte - created filesize %"G_GUINT64_FORMAT" byte",
1186                                            info->max_size, file_size);
1187
1188                 if (file_size > info->max_size) {
1189                         _MMCamcorderMsgItem message;
1190                         _mmcam_dbg_err("File size is greater than max size !!");
1191                         message.id = MM_MESSAGE_CAMCORDER_ERROR;
1192                         message.param.code = MM_ERROR_CAMCORDER_FILE_SIZE_OVER;
1193                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &message);
1194                 }
1195         }
1196
1197         if (info->restart_preview) {
1198                 /* block queue */
1199                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1200                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
1201                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
1202
1203                 _mmcam_dbg_log("Set state of pipeline as READY");
1204                 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY);
1205
1206                 /* check decoder recreation */
1207                 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
1208                         _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
1209                         ret = MM_ERROR_CAMCORDER_INTERNAL;
1210                 }
1211
1212                 /* unblock queue */
1213                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
1214                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
1215                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
1216
1217                 if (ret != MM_ERROR_NONE) {
1218                         msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1219                         msg.param.code = ret;
1220                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1221                         _mmcam_dbg_err("Failed to set state READY[%x]", ret);
1222                 }
1223
1224                 /* reset restart_preview for inset window layout */
1225                 info->restart_preview = FALSE;
1226
1227                 /* recover preview size */
1228                 if (!_mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height)) {
1229                         msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1230                         msg.param.code = MM_ERROR_CAMCORDER_INTERNAL;
1231                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1232                         _mmcam_dbg_err("Failed to set camera resolution %dx%d",
1233                                 info->preview_width, info->preview_height);
1234                 }
1235
1236                 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_PLAYING);
1237                 /* Do not return when error is occurred.
1238                    Recording file was created successfully, but starting pipeline failed */
1239                 if (ret != MM_ERROR_NONE) {
1240                         msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1241                         msg.param.code = ret;
1242                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1243                         _mmcam_dbg_err("Failed to set state PLAYING[%x]", ret);
1244                 }
1245         } else {
1246                 _mmcam_dbg_log("No need to restart preview");
1247         }
1248
1249         /* Send recording report to application */
1250         msg.id = MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED;
1251         report = (MMCamRecordingReport *)g_malloc(sizeof(MMCamRecordingReport));
1252         if (!report) {
1253                 _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
1254         } else {
1255                 report->recording_filename = g_strdup(info->filename);
1256                 msg.param.data = report;
1257                 msg.param.code = 1;
1258                 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1259         }
1260
1261         /* Finishing */
1262         sc->pipeline_time = 0;
1263         sc->pause_time = 0;
1264         sc->isMaxsizePausing = FALSE; /*In async function, this variable should set in callback function. */
1265         sc->isMaxtimePausing = FALSE;
1266         hcamcorder->error_occurs = FALSE;
1267
1268         info->video_frame_count = 0;
1269         info->audio_frame_count = 0;
1270         info->filesize = 0;
1271         info->b_commiting = FALSE;
1272
1273         /* check recording stop sound */
1274         _mmcamcorder_sound_solo_play_wait(handle);
1275
1276         _mmcam_dbg_err("_MMCamcorder_CMD_COMMIT : end");
1277
1278         return TRUE;
1279 }
1280
1281
1282 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1283 {
1284         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1285         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1286         GstMapInfo mapinfo;
1287         _MMCamcorderSubContext *sc = NULL;
1288         _MMCamcorderVideoInfo *videoinfo = NULL;
1289         _MMCamcorderMsgItem msg;
1290         guint64 buffer_size = 0;
1291         guint64 trailer_size = 0;
1292         guint64 max_size = 0;
1293
1294         mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1295         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1296         sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1297
1298         mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1299         videoinfo = sc->info_video;
1300
1301         /* get buffer size */
1302         if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) {
1303                 _mmcam_dbg_warn("map failed : buffer %p", buffer);
1304                 return GST_PAD_PROBE_OK;
1305         }
1306
1307         buffer_size = mapinfo.size;
1308         gst_buffer_unmap(buffer, &mapinfo);
1309
1310         /*_mmcam_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1311
1312         g_mutex_lock(&videoinfo->size_check_lock);
1313
1314         if (videoinfo->audio_frame_count == 0) {
1315                 videoinfo->filesize += buffer_size;
1316                 videoinfo->audio_frame_count++;
1317                 g_mutex_unlock(&videoinfo->size_check_lock);
1318                 return GST_PAD_PROBE_OK;
1319         }
1320
1321         if (sc->ferror_send || sc->isMaxsizePausing) {
1322                 _mmcam_dbg_warn("Recording is paused, drop frames");
1323                 g_mutex_unlock(&videoinfo->size_check_lock);
1324                 return GST_PAD_PROBE_DROP;
1325         }
1326
1327         /* get trailer size */
1328         if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1329                 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1330         else
1331                 trailer_size = 0;
1332
1333         /* check max size of recorded file */
1334         max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1335         if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1336                 GstState pipeline_state = GST_STATE_VOID_PENDING;
1337                 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1338                 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1339                 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1340                         " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1341                         videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1342
1343                 if (!sc->isMaxsizePausing) {
1344                         sc->isMaxsizePausing = TRUE;
1345                         gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1346                         if (pipeline_state == GST_STATE_PLAYING)
1347                                 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1348
1349                         msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1350                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1351                 }
1352
1353                 g_mutex_unlock(&videoinfo->size_check_lock);
1354
1355                 return FALSE;
1356         }
1357
1358         videoinfo->filesize += buffer_size;
1359         videoinfo->audio_frame_count++;
1360
1361         g_mutex_unlock(&videoinfo->size_check_lock);
1362
1363         return GST_PAD_PROBE_OK;
1364 }
1365
1366
1367 static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1368 {
1369         gint ret = 0;
1370         guint vq_size = 0;
1371         guint aq_size = 0;
1372         guint64 free_space = 0;
1373         guint64 buffer_size = 0;
1374         guint64 trailer_size = 0;
1375         guint64 queued_buffer = 0;
1376         guint64 max_size = 0;
1377         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1378         GstMapInfo mapinfo;
1379         storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE;
1380
1381         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1382         _MMCamcorderMsgItem msg;
1383         _MMCamcorderSubContext *sc = NULL;
1384         _MMCamcorderVideoInfo *videoinfo = NULL;
1385
1386         mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1387         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1388
1389         sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1390         mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1391         videoinfo = sc->info_video;
1392
1393         /*_mmcam_dbg_log("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1394         if (sc->ferror_send) {
1395                 _mmcam_dbg_warn("file write error, drop frames");
1396                 return GST_PAD_PROBE_DROP;
1397         }
1398
1399         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
1400         buffer_size = mapinfo.size;
1401         gst_buffer_unmap(buffer, &mapinfo);
1402
1403         videoinfo->video_frame_count++;
1404         if (videoinfo->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) {
1405                 /* _mmcam_dbg_log("Pass minimum frame: info->video_frame_count: %" G_GUINT64_FORMAT " ",
1406                         info->video_frame_count); */
1407                 g_mutex_lock(&videoinfo->size_check_lock);
1408                 videoinfo->filesize += buffer_size;
1409                 g_mutex_unlock(&videoinfo->size_check_lock);
1410                 return GST_PAD_PROBE_OK;
1411         }
1412
1413         /* get trailer size */
1414         if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1415                 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1416         else
1417                 trailer_size = 0;
1418
1419         /* check free space */
1420         ret = _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
1421         if (ret != 0) {
1422                 _mmcam_dbg_err("Error occured. [%d]", ret);
1423                 if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
1424                         sc->ferror_send = TRUE;
1425
1426                         msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1427                         msg.param.code = MM_ERROR_FILE_READ;
1428
1429                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1430                 } else {
1431                         sc->ferror_count++;
1432                 }
1433
1434                 return GST_PAD_PROBE_DROP; /* skip this buffer */
1435         }
1436
1437         if (free_space == 0) {
1438                 /* check storage state */
1439                 storage_get_state(hcamcorder->storage_info.id, &storage_state);
1440
1441                 _mmcam_dbg_warn("storage state %d", storage_state);
1442
1443                 if (storage_state == STORAGE_STATE_REMOVED ||
1444                         storage_state == STORAGE_STATE_UNMOUNTABLE) {
1445                         _mmcam_dbg_err("storage was removed!");
1446
1447                         _MMCAMCORDER_LOCK(hcamcorder);
1448
1449                         if (sc->ferror_send == FALSE) {
1450                                 _mmcam_dbg_err("OUT_OF_STORAGE error");
1451
1452                                 sc->ferror_send = TRUE;
1453
1454                                 _MMCAMCORDER_UNLOCK(hcamcorder);
1455
1456                                 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1457                                 msg.param.code = MM_ERROR_OUT_OF_STORAGE;
1458
1459                                 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1460                         } else {
1461                                 _MMCAMCORDER_UNLOCK(hcamcorder);
1462                                 _mmcam_dbg_warn("error was already sent");
1463                         }
1464
1465                         return GST_PAD_PROBE_DROP;
1466                 }
1467         }
1468
1469         /* get queued buffer size */
1470         if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst)
1471                 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "current-level-bytes", &aq_size);
1472
1473         if (sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst)
1474                 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "current-level-bytes", &vq_size);
1475
1476         queued_buffer = aq_size + vq_size;
1477
1478         if (free_space < (_MMCAMCORDER_MINIMUM_SPACE + buffer_size + trailer_size + queued_buffer)) {
1479                 _mmcam_dbg_warn("No more space for recording!!! Recording is paused.");
1480                 _mmcam_dbg_warn("Free Space : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]," \
1481                         " buffer size : [%" G_GUINT64_FORMAT "], queued buffer size : [%" G_GUINT64_FORMAT "]", \
1482                         free_space, trailer_size, buffer_size, queued_buffer);
1483
1484                 if (!sc->isMaxsizePausing) {
1485                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1486                         sc->isMaxsizePausing = TRUE;
1487
1488                         msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
1489                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1490                 }
1491
1492                 return GST_PAD_PROBE_DROP;
1493         }
1494
1495         g_mutex_lock(&videoinfo->size_check_lock);
1496
1497         /* check max size of recorded file */
1498         max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1499         if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1500                 GstState pipeline_state = GST_STATE_VOID_PENDING;
1501                 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1502                 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1503                 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1504                         " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1505                         videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1506
1507                 if (!sc->isMaxsizePausing) {
1508                         sc->isMaxsizePausing = TRUE;
1509                         gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1510                         if (pipeline_state == GST_STATE_PLAYING)
1511                                 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1512
1513                         msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1514                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1515                 }
1516
1517                 g_mutex_unlock(&videoinfo->size_check_lock);
1518
1519                 return GST_PAD_PROBE_DROP;
1520         }
1521
1522         videoinfo->filesize += (guint64)buffer_size;
1523
1524         /*
1525         _mmcam_dbg_log("filesize %lld Byte, ", videoinfo->filesize);
1526         */
1527
1528         g_mutex_unlock(&videoinfo->size_check_lock);
1529
1530         return GST_PAD_PROBE_OK;
1531 }
1532
1533
1534 static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1535 {
1536         guint64 trailer_size = 0;
1537         guint64 rec_pipe_time = 0;
1538         unsigned int remained_time = 0;
1539
1540         GstClockTime b_time;
1541
1542         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1543         _MMCamcorderMsgItem msg;
1544         _MMCamcorderSubContext *sc = NULL;
1545         _MMCamcorderVideoInfo *videoinfo = NULL;
1546
1547         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1548
1549         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1550         mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1551
1552         sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1553         mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1554         mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1555
1556         videoinfo = sc->info_video;
1557
1558         b_time = GST_BUFFER_PTS(buffer);
1559
1560         rec_pipe_time = GST_TIME_AS_MSECONDS(b_time);
1561
1562         if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1563                 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1564         else
1565                 trailer_size = 0;
1566
1567         /* check max time */
1568         if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1569                 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1570                         rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1571
1572                 if (!sc->isMaxtimePausing) {
1573                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1574
1575                         sc->isMaxtimePausing = TRUE;
1576
1577                         msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1578                         msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1579                         msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1580                         msg.param.recording_status.remained_time = 0;
1581                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1582
1583                         msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1584                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1585                 }
1586
1587                 return GST_PAD_PROBE_DROP;
1588         }
1589
1590         /* calculate remained time can be recorded */
1591         if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1592                 remained_time = videoinfo->max_time - rec_pipe_time;
1593         } else if (videoinfo->max_size > 0) {
1594                 long double max_size = (long double)videoinfo->max_size;
1595                 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1596
1597                 remained_time = (unsigned int)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1598         }
1599
1600         msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1601         msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1602         msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1603         msg.param.recording_status.remained_time = remained_time;
1604         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1605
1606         /*
1607         _mmcam_dbg_log("time [%" GST_TIME_FORMAT "], size [%d]",
1608                 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1609         */
1610
1611         if (videoinfo->record_timestamp_ratio != _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1612                 guint record_motion_rate = (guint)videoinfo->record_motion_rate;
1613
1614                 /*
1615                 _mmcam_dbg_log("record_motion_rate %d, videoinfo->record_drop_count %d",
1616                         record_motion_rate, videoinfo->record_drop_count);
1617                 */
1618
1619                 /* drop some frame if fast motion */
1620                 if (videoinfo->record_motion_rate > _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1621                         if (record_motion_rate != (videoinfo->record_drop_count++)) {
1622                                 /*
1623                                 _mmcam_dbg_warn("drop frame");
1624                                 */
1625                                 return GST_PAD_PROBE_DROP;
1626                         }
1627
1628                         videoinfo->record_drop_count = 1;
1629                         /*
1630                         _mmcam_dbg_warn("pass frame");
1631                         */
1632                 }
1633
1634                 GST_BUFFER_PTS(buffer) = b_time * (videoinfo->record_timestamp_ratio);
1635                 GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer);
1636         }
1637
1638         return GST_PAD_PROBE_OK;
1639 }
1640
1641
1642 static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1643 {
1644         _MMCamcorderMsgItem msg;
1645         guint64 trailer_size = 0;
1646         guint64 rec_pipe_time = 0;
1647         _MMCamcorderSubContext *sc = NULL;
1648         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1649         _MMCamcorderVideoInfo *videoinfo = NULL;
1650         unsigned int remained_time = 0;
1651         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1652
1653         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1654         mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1655         sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1656
1657         mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1658         mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1659         mmf_return_val_if_fail(sc->element, GST_PAD_PROBE_OK);
1660
1661         videoinfo = sc->info_video;
1662
1663         if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) {
1664                 _mmcam_dbg_err("Buffer timestamp is invalid, check it");
1665                 return GST_PAD_PROBE_OK;
1666         }
1667
1668         rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer));
1669
1670         if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1671                 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1672         else
1673                 trailer_size = 0;
1674
1675         /* calculate remained time can be recorded */
1676         if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1677                 remained_time = videoinfo->max_time - rec_pipe_time;
1678         } else if (videoinfo->max_size > 0) {
1679                 long double max_size = (long double)videoinfo->max_size;
1680                 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1681
1682                 remained_time = (unsigned long long)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1683         }
1684
1685         if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1686                 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1687                         rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1688
1689                 if (!sc->isMaxtimePausing) {
1690                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1691
1692                         sc->isMaxtimePausing = TRUE;
1693
1694                         msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1695                         msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1696                         msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1697                         msg.param.recording_status.remained_time = 0;
1698                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1699
1700                         msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1701                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1702                 }
1703
1704                 return GST_PAD_PROBE_DROP;
1705         }
1706
1707         msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1708         msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1709         msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1710         msg.param.recording_status.remained_time = remained_time;
1711         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1712
1713         /*
1714         _mmcam_dbg_log("audio data probe :: time [%" GST_TIME_FORMAT "], size [%lld KB]",
1715                 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1716         */
1717
1718         return GST_PAD_PROBE_OK;
1719 }
1720
1721
1722 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1723 {
1724         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1725         double volume = 0.0;
1726         int format = 0;
1727         int channel = 0;
1728         int err = MM_ERROR_UNKNOWN;
1729         char *err_name = NULL;
1730         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1731         GstMapInfo mapinfo;
1732
1733         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1734         mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP);
1735
1736         /*_mmcam_dbg_log("AUDIO SRC time stamp : [%" GST_TIME_FORMAT "] \n", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1737         err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name,
1738                 MMCAM_AUDIO_VOLUME, &volume,
1739                 MMCAM_AUDIO_FORMAT, &format,
1740                 MMCAM_AUDIO_CHANNEL, &channel,
1741                 NULL);
1742         if (err != MM_ERROR_NONE) {
1743                 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
1744                 SAFE_FREE(err_name);
1745                 return err;
1746         }
1747
1748         memset(&mapinfo, 0x0, sizeof(GstMapInfo));
1749
1750         gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE);
1751
1752         /* Set audio stream NULL */
1753         if (volume == 0.0)
1754                 memset(mapinfo.data, 0, mapinfo.size);
1755
1756         /* CALL audio stream callback */
1757         if (hcamcorder->astream_cb && buffer && mapinfo.data && mapinfo.size > 0) {
1758                 MMCamcorderAudioStreamDataType stream;
1759
1760                 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE) {
1761                         _mmcam_dbg_warn("Not ready for stream callback");
1762                         gst_buffer_unmap(buffer, &mapinfo);
1763                         return GST_PAD_PROBE_OK;
1764                 }
1765
1766                 /*_mmcam_dbg_log("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
1767                         GST_BUFFER_DATA(buffer), width, height, format);*/
1768
1769                 stream.data = (void *)mapinfo.data;
1770                 stream.format = format;
1771                 stream.channel = channel;
1772                 stream.length = mapinfo.size;
1773                 stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano -> milli second */
1774
1775                 _MMCAMCORDER_LOCK_ASTREAM_CALLBACK(hcamcorder);
1776
1777                 if (hcamcorder->astream_cb)
1778                         hcamcorder->astream_cb(&stream, hcamcorder->astream_cb_param);
1779
1780                 _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(hcamcorder);
1781         }
1782
1783         gst_buffer_unmap(buffer, &mapinfo);
1784         return GST_PAD_PROBE_OK;
1785 }
1786
1787
1788 static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat)
1789 {
1790         gboolean bret = FALSE;
1791
1792         switch (fileformat) {
1793         case MM_FILE_FORMAT_3GP:
1794         case MM_FILE_FORMAT_MP4:
1795                 bret = __mmcamcorder_add_metadata_mp4(handle);
1796                 break;
1797         default:
1798                 _mmcam_dbg_warn("Unsupported fileformat to insert location info (%d)", fileformat);
1799                 break;
1800         }
1801
1802         return bret;
1803 }
1804
1805
1806 static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle)
1807 {
1808         FILE *f = NULL;
1809         guchar buf[4];
1810         guint64 udta_size = 0;
1811         gint64 current_pos = 0;
1812         gint64 moov_pos = 0;
1813         gint64 udta_pos = 0;
1814         gdouble longitude = 0;
1815         gdouble latitude = 0;
1816         gdouble altitude = 0;
1817         int err = 0;
1818         int orientation = 0;
1819         int gps_enable = 0;
1820         char *err_name = NULL;
1821         char err_msg[MAX_ERROR_MESSAGE_LEN] = {'\0',};
1822         _MMCamcorderLocationInfo location_info = {0, 0, 0};
1823         _MMCamcorderLocationInfo geo_info = {0, 0, 0};
1824
1825         _MMCamcorderVideoInfo *info = NULL;
1826         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1827         _MMCamcorderSubContext *sc = NULL;
1828
1829         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1830         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1831
1832         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1833         mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1834
1835         _mmcam_dbg_log("");
1836
1837         info = sc->info_video;
1838
1839         f = fopen64(info->filename, "rb+");
1840         if (f == NULL) {
1841                 strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN);
1842                 _mmcam_dbg_err("file open failed [%s]", err_msg);
1843                 return FALSE;
1844         }
1845
1846         mm_camcorder_get_attributes(handle, &err_name,
1847                 MMCAM_TAG_LATITUDE, &latitude,
1848                 MMCAM_TAG_LONGITUDE, &longitude,
1849                 MMCAM_TAG_ALTITUDE, &altitude,
1850                 MMCAM_TAG_VIDEO_ORIENTATION, &orientation,
1851                 MMCAM_TAG_GPS_ENABLE, &gps_enable,
1852                 NULL);
1853         if (err_name) {
1854                 _mmcam_dbg_warn("Get tag attrs fail. (%s:%x)", err_name, err);
1855                 SAFE_FREE(err_name);
1856         }
1857
1858         location_info.longitude = _mmcamcorder_double_to_fix(longitude);
1859         location_info.latitude = _mmcamcorder_double_to_fix(latitude);
1860         location_info.altitude = _mmcamcorder_double_to_fix(altitude);
1861         geo_info.longitude = longitude *10000;
1862         geo_info.latitude = latitude *10000;
1863         geo_info.altitude = altitude *10000;
1864         /* find udta container.
1865            if, there are udta container, write loci box after that
1866            else, make udta container and write loci box. */
1867         if (_mmcamcorder_find_fourcc(f, MMCAM_FOURCC('u', 'd', 't', 'a'), TRUE)) {
1868                 size_t nread = 0;
1869
1870                 _mmcam_dbg_log("find udta container");
1871
1872                 /* read size */
1873                 if (fseek(f, -8L, SEEK_CUR) != 0)
1874                         goto fail;
1875
1876                 udta_pos = ftello(f);
1877                 if (udta_pos < 0)
1878                         goto ftell_fail;
1879
1880                 nread = fread(&buf, sizeof(char), sizeof(buf), f);
1881
1882                 _mmcam_dbg_log("recorded file fread %zu", nread);
1883
1884                 udta_size = _mmcamcorder_get_container_size(buf);
1885
1886                 /* goto end of udta and write 'loci' box */
1887                 if (fseek(f, (udta_size-4L), SEEK_CUR) != 0)
1888                         goto fail;
1889
1890                 if (gps_enable) {
1891                         if (!_mmcamcorder_write_loci(f, location_info)) {
1892                                 _mmcam_dbg_err("failed to write loci");
1893                                 goto fail;
1894                         }
1895
1896                         if (!_mmcamcorder_write_geodata(f, geo_info)) {
1897                                 _mmcam_dbg_err("failed to write geodata");
1898                                 goto fail;
1899                         }
1900                 }
1901
1902                 current_pos = ftello(f);
1903                 if (current_pos < 0)
1904                         goto ftell_fail;
1905
1906                 if (!_mmcamcorder_update_size(f, udta_pos, current_pos))
1907                         goto fail;
1908         } else {
1909                 _mmcam_dbg_log("No udta container");
1910                 if (fseek(f, 0, SEEK_END) != 0)
1911                         goto fail;
1912
1913                 if (!_mmcamcorder_write_udta(f, gps_enable, location_info, geo_info)) {
1914                         _mmcam_dbg_err("failed to write udta");
1915                         goto fail;
1916                 }
1917         }
1918
1919         /* find moov container.
1920            update moov container size. */
1921         if ((current_pos = ftello(f)) < 0)
1922                 goto ftell_fail;
1923
1924         if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('m', 'o', 'o', 'v'), TRUE)) {
1925                 gint64 internal_pos = ftello(f);
1926
1927                 _mmcam_dbg_log("found moov container");
1928                 if (fseek(f, -8L, SEEK_CUR) != 0)
1929                         goto fail;
1930
1931                 moov_pos = ftello(f);
1932                 if (moov_pos < 0)
1933                         goto ftell_fail;
1934
1935                 if (!_mmcamcorder_update_size(f, moov_pos, current_pos))
1936                         goto fail;
1937
1938                 /* add orientation info */
1939                 if (fseeko(f, internal_pos, SEEK_SET) < 0) {
1940                         _mmcam_dbg_err("fseeko failed : errno %d", errno);
1941                         goto fail;
1942                 }
1943
1944                 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'r', 'a', 'k'), FALSE)) {
1945                         _mmcam_dbg_err("failed to find [trak] tag");
1946                         goto fail;
1947                 }
1948
1949                 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'k', 'h', 'd'), FALSE)) {
1950                         _mmcam_dbg_err("failed to find [tkhd] tag");
1951                         goto fail;
1952                 }
1953
1954                 _mmcam_dbg_log("found [tkhd] tag");
1955
1956                 /* seek to start position of composition matrix */
1957                 if (fseek(f, _OFFSET_COMPOSITION_MATRIX, SEEK_CUR) == 0) {
1958                         /* update composition matrix for orientation */
1959                         _mmcamcorder_update_composition_matrix(f, orientation);
1960                 } else {
1961                         _mmcam_dbg_err("fseek failed : errno %d", errno);
1962                         goto fail;
1963                 }
1964         } else {
1965                 _mmcam_dbg_err("No 'moov' container");
1966                 goto fail;
1967         }
1968
1969         fclose(f);
1970         return TRUE;
1971
1972 fail:
1973         fclose(f);
1974         return FALSE;
1975
1976 ftell_fail:
1977         _mmcam_dbg_err("ftell() returns negative value.");
1978         fclose(f);
1979         return FALSE;
1980 }
1981
1982
1983 int _mmcamcorder_connect_video_stream_cb_signal(MMHandleType handle)
1984 {
1985         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1986         _MMCamcorderSubContext *sc = NULL;
1987
1988         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1989
1990         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1991         mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1992
1993         /* check video source element */
1994         if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
1995                 _mmcam_dbg_warn("connect video stream cb signal to _MMCAMCORDER_VIDEOSRC_SRC");
1996                 MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst,
1997                         _MMCAMCORDER_HANDLER_VIDEOREC, "video-stream-cb",
1998                         G_CALLBACK(__mmcamcorder_video_stream_cb),
1999                         hcamcorder);
2000                 return MM_ERROR_NONE;
2001         } else {
2002                 _mmcam_dbg_err("videosrc element is not created yet");
2003                 return MM_ERROR_CAMCORDER_NOT_INITIALIZED;
2004         }
2005 }
2006
2007
2008 int _mmcamcorder_video_prepare_record(MMHandleType handle)
2009 {
2010         int ret = MM_ERROR_NONE;
2011         int size = 0;
2012         char *temp_filename = NULL;
2013
2014         _MMCamcorderVideoInfo *info = NULL;
2015         _MMCamcorderSubContext *sc = NULL;
2016         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2017
2018         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2019
2020         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2021         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2022         mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2023
2024         info = sc->info_video;
2025
2026         _mmcam_dbg_warn("start");
2027
2028         /* create encoding pipeline */
2029         ret = _mmcamcorder_create_recorder_pipeline((MMHandleType)hcamcorder);
2030         if (ret != MM_ERROR_NONE)
2031                 goto _ERR_PREPARE_RECORD;
2032
2033         SAFE_G_FREE(info->filename);
2034
2035         mm_camcorder_get_attributes(handle, NULL,
2036                 MMCAM_TARGET_FILENAME, &temp_filename, &size,
2037                 NULL);
2038         if (temp_filename) {
2039                 info->filename = g_strdup(temp_filename);
2040                 if (!info->filename) {
2041                         _mmcam_dbg_err("strdup[src:%p] was failed", temp_filename);
2042                         goto _ERR_PREPARE_RECORD;
2043                 }
2044
2045                 _mmcam_dbg_log("Record file name [%s]", info->filename);
2046                 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
2047         } else {
2048                 _mmcam_dbg_log("Recorded data will be written in [%s]", _MMCamcorder_FILENAME_NULL);
2049                 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", _MMCamcorder_FILENAME_NULL);
2050         }
2051
2052         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", 0);
2053
2054         /* Adjust display FPS */
2055         sc->display_interval = 0;
2056         sc->previous_slot_time = 0;
2057
2058         ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PAUSED);
2059         if (ret != MM_ERROR_NONE)
2060                 goto _ERR_PREPARE_RECORD;
2061
2062         _mmcam_dbg_warn("done");
2063
2064         return ret;
2065
2066 _ERR_PREPARE_RECORD:
2067         /* Remove recorder pipeline and recording file which size maybe zero */
2068         _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
2069         if (info && info->filename) {
2070                 _mmcam_dbg_log("file delete(%s)", info->filename);
2071                 unlink(info->filename);
2072         }
2073
2074         return ret;
2075 }