Fix coverity issue
[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_MURPHY_SUPPORT
361         int ret = MM_ERROR_NONE;
362         MMCamcorderResourceManager *resource_manager = NULL;
363 #endif /* _MMCAMCORDER_MURPHY_SUPPORT */
364
365         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
366
367         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
368         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
369         mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
370
371         _mmcam_dbg_log("");
372
373         if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst != NULL) {
374                 /* release request pad */
375                 reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "audio");
376                 if (reqpad) {
377                         gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
378                         gst_object_unref(reqpad);
379                         reqpad = NULL;
380                 }
381
382                 reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "video");
383                 if (reqpad) {
384                         gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
385                         gst_object_unref(reqpad);
386                         reqpad = NULL;
387                 }
388
389                 /* release encode main pipeline */
390                 gst_object_unref(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst);
391
392                 /*
393                         To avoid conflicting between old elements and newly created elements,
394                         I clean element handles here. Real elements object will be finalized as the 'unref' process goes on.
395                         This is a typical problem of unref. Even though I unref bin here, it takes much time to finalize each elements.
396                         So I clean handles first, make them unref later. Audio recording, however, isn't needed this process.
397                         It's because the pipeline of audio recording destroys at the same time,
398                         and '_mmcamcorder_element_release_noti' will perfom removing handle.
399                 */
400                 /* _mmcamcorder_remove_element_handle(handle, (void *)sc->encode_element,
401                         _MMCAMCORDER_ENCODE_MAIN_PIPE, _MMCAMCORDER_ENCSINK_SINK); */
402
403                 _mmcam_dbg_warn("Encoder pipeline removed");
404
405 #ifdef _MMCAMCORDER_MURPHY_SUPPORT
406                 resource_manager = &hcamcorder->resource_manager_sub;
407
408                 _mmcam_dbg_warn("lock resource - cb calling %d", resource_manager->is_release_cb_calling);
409
410                 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
411
412                 if (resource_manager->is_release_cb_calling == FALSE) {
413                         /* release resource */
414                         ret = _mmcamcorder_resource_manager_release(resource_manager);
415
416                         _mmcam_dbg_warn("release resource 0x%x", ret);
417
418                         if (resource_manager->acquire_remain < resource_manager->acquire_count) {
419                                 /* wait for resource release */
420                                 gint64 end_time = g_get_monotonic_time() + (__MMCAMCORDER_RESOURCE_WAIT_TIME * G_TIME_SPAN_SECOND);
421                                 _mmcam_dbg_log("resource is not released all. wait for signal...");
422                                 _MMCAMCORDER_RESOURCE_WAIT_UNTIL(hcamcorder, end_time);
423                         }
424                 }
425
426                 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
427
428                 _mmcam_dbg_warn("unlock resource");
429 #endif /* _MMCAMCORDER_MURPHY_SUPPORT */
430         }
431
432         return MM_ERROR_NONE;
433 }
434
435
436 int _mmcamcorder_remove_recorder_pipeline(MMHandleType handle)
437 {
438         int ret = MM_ERROR_NONE;
439         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
440         _MMCamcorderSubContext *sc = NULL;
441
442         GstBus *bus = NULL;
443
444         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
445         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
446         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
447
448         _mmcam_dbg_log("start");
449
450         if (!sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst) {
451                 _mmcam_dbg_warn("pipeline is not existed.");
452                 return MM_ERROR_NONE;
453         }
454
455         _mmcamcorder_remove_all_handlers((MMHandleType)hcamcorder, _MMCAMCORDER_HANDLER_VIDEOREC);
456
457         ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_NULL);
458         if (ret != MM_ERROR_NONE) {
459                 _mmcam_dbg_err("Faile to change encode main pipeline [0x%x]", ret);
460                 return ret;
461         }
462
463         bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst));
464
465         /* remove audio pipeline first */
466         ret = _mmcamcorder_remove_audio_pipeline(handle);
467         if (ret != MM_ERROR_NONE) {
468                 _mmcam_dbg_err("Fail to remove audio pipeline");
469                 return ret;
470         }
471
472         ret = _mmcamcorder_remove_encode_pipeline(handle);
473         if (ret != MM_ERROR_NONE) {
474                 _mmcam_dbg_err("Fail to remove encoder pipeline");
475                 return ret;
476         }
477
478         /* Remove pipeline message callback */
479         if (hcamcorder->encode_pipeline_cb_event_id != 0) {
480                 g_source_remove(hcamcorder->encode_pipeline_cb_event_id);
481                 hcamcorder->encode_pipeline_cb_event_id = 0;
482         }
483
484         /* Remove remained message */
485         if (bus) {
486                 GstMessage *gst_msg = NULL;
487                 while ((gst_msg = gst_bus_pop(bus)) != NULL) {
488                         _mmcamcorder_pipeline_cb_message(bus, gst_msg, (gpointer)hcamcorder);
489                         gst_message_unref(gst_msg);
490                         gst_msg = NULL;
491                 }
492                 gst_object_unref(bus);
493                 bus = NULL;
494         }
495
496         _mmcam_dbg_log("done");
497
498         return ret;
499 }
500
501
502 int _mmcamcorder_video_command(MMHandleType handle, int command)
503 {
504         int size = 0;
505         int fileformat = 0;
506         int count = 0;
507         int ret = MM_ERROR_NONE;
508         double motion_rate = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE;
509         char *err_name = NULL;
510         char *temp_filename = NULL;
511         GstCameraControl *CameraControl = NULL;
512         GstCameraControlChannel *CameraControlChannel = NULL;
513         const GList *controls = NULL;
514         const GList *item = NULL;
515
516         gint fps = 0;
517         GstElement *pipeline = NULL;
518
519         _MMCamcorderVideoInfo *info = NULL;
520         _MMCamcorderSubContext *sc = NULL;
521         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
522
523         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
524
525         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
526         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
527         mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
528         mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
529
530         info = sc->info_video;
531
532         _mmcam_dbg_log("Command(%d)", command);
533
534         pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
535
536         switch (command) {
537         case _MMCamcorder_CMD_RECORD:
538         {
539                 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) != MM_CAMCORDER_STATE_PAUSED) {
540                         /**
541                          * start recording
542                          */
543                         guint imax_size = 0;
544                         guint imax_time = 0;
545                         int ret_free_space = 0;
546                         char *dir_name = NULL;
547                         guint64 free_space = 0;
548                         int file_system_type = 0;
549                         int root_directory_length = 0;
550
551                         /* Recording */
552                         _mmcam_dbg_log("Record Start - dual stream %d", info->support_dual_stream);
553
554 #ifdef _MMCAMCORDER_MURPHY_SUPPORT
555                         /* check connection */
556                         ret = _mmcamcorder_resource_check_connection(&hcamcorder->resource_manager_sub);
557                         if (ret != MM_ERROR_NONE)
558                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
559
560                         /* create resource set */
561                         ret = _mmcamcorder_resource_create_resource_set(&hcamcorder->resource_manager_sub);
562                         if (ret != MM_ERROR_NONE)
563                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
564
565                         hcamcorder->resource_manager_sub.acquire_count = 0;
566
567                         /* prepare resource manager for H/W encoder */
568                         ret = _mmcamcorder_resource_manager_prepare(&hcamcorder->resource_manager_sub, MM_CAMCORDER_RESOURCE_TYPE_VIDEO_ENCODER);
569                         if (ret != MM_ERROR_NONE) {
570                                 _mmcam_dbg_err("could not prepare for video_encoder resource");
571                                 ret = MM_ERROR_CAMCORDER_INTERNAL;
572                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
573                         }
574
575                         /* acquire resources */
576                         _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
577
578                         ret = _mmcamcorder_resource_manager_acquire(&hcamcorder->resource_manager_sub);
579                         if (ret != MM_ERROR_NONE) {
580                                 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
581                                 _mmcam_dbg_err("could not acquire resource");
582                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
583                         }
584
585                         if (hcamcorder->resource_manager_sub.acquire_remain > 0) {
586                                 gint64 end_time = 0;
587
588                                 _mmcam_dbg_warn("wait for resource state change");
589
590                                 /* wait for resource state change */
591                                 end_time = g_get_monotonic_time() + (__MMCAMCORDER_RESOURCE_WAIT_TIME * G_TIME_SPAN_SECOND);
592
593                                 if (_MMCAMCORDER_RESOURCE_WAIT_UNTIL(hcamcorder, end_time)) {
594                                         _mmcam_dbg_warn("signal received");
595                                 } else {
596                                         _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
597                                         _mmcam_dbg_err("timeout");
598                                         ret = MM_ERROR_RESOURCE_INTERNAL;
599                                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
600                                 }
601                         } else {
602                                 _mmcam_dbg_log("already acquired");
603                         }
604
605                         _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
606 #endif /* _MMCAMCORDER_MURPHY_SUPPORT */
607
608                         /* init record_dual_stream */
609                         info->record_dual_stream = FALSE;
610
611                         ret = mm_camcorder_get_attributes(handle, &err_name,
612                                 MMCAM_CAMERA_FPS, &fps,
613                                 MMCAM_CAMERA_WIDTH, &(info->preview_width),
614                                 MMCAM_CAMERA_HEIGHT, &(info->preview_height),
615                                 MMCAM_VIDEO_WIDTH, &(info->video_width),
616                                 MMCAM_VIDEO_HEIGHT, &(info->video_height),
617                                 MMCAM_FILE_FORMAT, &fileformat,
618                                 MMCAM_TARGET_FILENAME, &temp_filename, &size,
619                                 MMCAM_TARGET_MAX_SIZE, &imax_size,
620                                 MMCAM_TARGET_TIME_LIMIT, &imax_time,
621                                 MMCAM_FILE_FORMAT, &(info->fileformat),
622                                 MMCAM_CAMERA_RECORDING_MOTION_RATE, &motion_rate,
623                                 MMCAM_ROOT_DIRECTORY, &hcamcorder->root_directory, &root_directory_length,
624                                 NULL);
625                         if (ret != MM_ERROR_NONE) {
626                                 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, ret);
627                                 SAFE_FREE(err_name);
628                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
629                         }
630
631                         if (!temp_filename && !hcamcorder->mstream_cb) {
632                                 _mmcam_dbg_err("filename is not set and muxed stream cb is NULL");
633                                 ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
634                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
635                         }
636
637                         /* set max size */
638                         if (imax_size <= 0)
639                                 info->max_size = 0; /* do not check */
640                         else
641                                 info->max_size = ((guint64)imax_size) << 10; /* to byte */
642
643                         /* set max time */
644                         if (imax_time <= 0)
645                                 info->max_time = 0; /* do not check */
646                         else
647                                 info->max_time = (guint64)((double)imax_time * (double)1000 * motion_rate); /* to millisecond */
648
649                         dir_name = g_path_get_dirname(temp_filename);
650                         if (dir_name) {
651                                 ret = _mmcamcorder_get_storage_info(dir_name, hcamcorder->root_directory, &hcamcorder->storage_info);
652                                 if (ret != 0) {
653                                         _mmcam_dbg_err("get storage info failed");
654                                         g_free(dir_name);
655                                         dir_name = NULL;
656                                         return MM_ERROR_OUT_OF_STORAGE;
657                                 }
658
659                                 ret_free_space = _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
660
661                                 _mmcam_dbg_warn("current space - %s [%" G_GUINT64_FORMAT "]", dir_name, free_space);
662
663                                 if (_mmcamcorder_get_file_system_type(dir_name, &file_system_type) == 0) {
664                                         /* MSDOS_SUPER_MAGIC : 0x4d44 */
665                                         if (file_system_type == MSDOS_SUPER_MAGIC &&
666                                             (info->max_size == 0 || info->max_size > FAT32_FILE_SYSTEM_MAX_SIZE)) {
667                                                 _mmcam_dbg_warn("FAT32 and too large max[%"G_GUINT64_FORMAT"], set max as %"G_GUINT64_FORMAT,
668                                                         info->max_size, FAT32_FILE_SYSTEM_MAX_SIZE);
669                                                 info->max_size = FAT32_FILE_SYSTEM_MAX_SIZE;
670                                         } else {
671                                                 _mmcam_dbg_warn("file system 0x%x, max size %"G_GUINT64_FORMAT,
672                                                         file_system_type, info->max_size);
673                                         }
674                                 } else {
675                                         _mmcam_dbg_warn("_mmcamcorder_get_file_system_type failed");
676                                 }
677
678                                 g_free(dir_name);
679                                 dir_name = NULL;
680                         } else {
681                                 _mmcam_dbg_err("failed to get directory name");
682                                 ret_free_space = -1;
683                         }
684
685                         if (temp_filename &&
686                                 (ret_free_space == -1 || free_space <= _MMCAMCORDER_VIDEO_MINIMUM_SPACE)) {
687                                 _mmcam_dbg_err("OUT of STORAGE [ret_free_space:%d or free space [%" G_GUINT64_FORMAT "] is smaller than [%d]",
688                                         ret_free_space, free_space, _MMCAMCORDER_VIDEO_MINIMUM_SPACE);
689                                 return MM_ERROR_OUT_OF_STORAGE;
690                         }
691
692                         g_mutex_lock(&hcamcorder->task_thread_lock);
693                         if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst == NULL &&
694                             hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) {
695                                 /* Play record start sound */
696                                 _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_START, FALSE);
697                         }
698                         g_mutex_unlock(&hcamcorder->task_thread_lock);
699
700                         _mmcam_dbg_warn("video size [%dx%d]", info->video_width, info->video_height);
701
702                         if (info->video_width == 0 || info->video_height == 0) {
703                                 _mmcam_dbg_warn("video size is invalid [%dx%d] use preview size [%dx%d]",
704                                         info->video_width, info->video_height, info->preview_width, info->preview_height);
705                                 info->video_width = info->preview_width;
706                                 info->video_height = info->preview_height;
707                         }
708
709                         if (info->support_dual_stream) {
710                                 _mmcam_dbg_warn("DUAL STREAM MODE");
711
712                                 info->record_dual_stream = TRUE;
713
714                                 /* No need to restart preview */
715                                 info->restart_preview = FALSE;
716
717                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-width", info->video_width);
718                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-height", info->video_height);
719                         } else if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
720                                 info->preview_width == info->video_width &&
721                                 info->preview_height == info->video_height) {
722                                 _mmcam_dbg_log("H264 preview mode and same resolution");
723
724                                 /* No need to restart preview */
725                                 info->restart_preview = FALSE;
726                         } else {
727                                 /* always need to restart preview  */
728                                 info->restart_preview = TRUE;
729                         }
730
731                         /* set recording hint */
732                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", TRUE);
733
734                         if (info->restart_preview) {
735                                 /* stop preview and set new size */
736                                 _mmcam_dbg_log("restart preview");
737
738                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
739                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
740                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
741
742                                 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
743
744                                 /* check decoder recreation */
745                                 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
746                                         _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
747                                         ret = MM_ERROR_CAMCORDER_INTERNAL;
748                                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
749                                 }
750
751                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
752                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
753                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
754
755                                 if (ret != MM_ERROR_NONE)
756                                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
757
758                                 if (!_mmcamcorder_set_camera_resolution(handle, info->video_width, info->video_height)) {
759                                         ret = MM_ERROR_CAMCORDER_INTERNAL;
760                                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
761                                 }
762
763                                 /* Start preview again with new setting */
764                                 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
765                                 if (ret != MM_ERROR_NONE)
766                                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
767
768                                 if (motion_rate < 1.0) {
769                                         _mmcam_dbg_warn("wait for stabilization of frame");
770                                         usleep(300000);
771                                 }
772                         } else {
773                                 _mmcam_dbg_log("no need to restart preview");
774                         }
775
776                         _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
777                                 CONFIGURE_CATEGORY_MAIN_RECORD,
778                                 "DropVideoFrame",
779                                 &(sc->drop_vframe));
780
781                         _mmcamcorder_conf_get_value_int(handle, hcamcorder->conf_main,
782                                 CONFIGURE_CATEGORY_MAIN_RECORD,
783                                 "PassFirstVideoFrame",
784                                 &(sc->pass_first_vframe));
785
786                         _mmcam_dbg_log("Drop video frame count[%d], Pass fisrt video frame count[%d]",
787                                 sc->drop_vframe, sc->pass_first_vframe);
788
789                         info->record_drop_count = (guint)motion_rate;
790                         info->record_motion_rate = motion_rate;
791                         if (sc->is_modified_rate)
792                                 info->record_timestamp_ratio = (_MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE/motion_rate);
793                         else
794                                 info->record_timestamp_ratio = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE;
795
796                         _mmcam_dbg_warn("recording fps %d, motion rate %f, timestamp_ratio %f",
797                                 fps, info->record_motion_rate, info->record_timestamp_ratio);
798
799                         /* set push buffer flag */
800                         info->push_encoding_buffer = PUSH_ENCODING_BUFFER_INIT;
801                         info->base_video_ts = 0;
802
803                         /* connect video stream cb signal */
804                         /*130826 Connect video stream cb for handling fast record frame cb*/
805                         if (info->record_dual_stream) {
806                                 if (_mmcamcorder_connect_video_stream_cb_signal((MMHandleType)hcamcorder) != MM_ERROR_NONE)
807                                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
808                         }
809
810                         /* start video stream */
811                         if (info->record_dual_stream) {
812                                 CameraControl =  GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
813                                 if (CameraControl) {
814                                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
815
816                                         _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_START");
817                                         gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_START);
818
819                                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
820                                 } else {
821                                         _mmcam_dbg_err("could not get camera control");
822                                 }
823                         }
824
825                         /* check pre-created encode pipeline */
826                         g_mutex_lock(&hcamcorder->task_thread_lock);
827                         if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst == NULL &&
828                             hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) {
829                                 /* create encoding pipeline */
830                                 ret = _mmcamcorder_video_prepare_record((MMHandleType)hcamcorder);
831                                 if (ret != MM_ERROR_NONE) {
832                                         g_mutex_unlock(&hcamcorder->task_thread_lock);
833                                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
834                                 }
835                         }
836                         g_mutex_unlock(&hcamcorder->task_thread_lock);
837
838                         /* check recording start sound */
839                         _mmcamcorder_sound_solo_play_wait(handle);
840
841                         /**< To fix video recording hanging
842                                 1. use gst_element_set_start_time() instead of gst_pipeline_set_new_stream_time()
843                                 2. Set (GstClockTime)1 instead of (GstClockTime)0. Because of strict check in gstreamer 0.25,
844                                  basetime wouldn't change if you set (GstClockTime)0.
845                                 3. Move set start time position below PAUSED of pipeline.
846                         */
847                         /*
848                         gst_element_set_start_time(GST_ELEMENT(sc->element[_MMCAMCORDER_MAIN_PIPE].gst), (GstClockTime)1);
849                         gst_element_set_start_time(GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst), (GstClockTime)1);
850                         */
851
852                         info->video_frame_count = 0;
853                         info->is_firstframe = TRUE;
854                         info->audio_frame_count = 0;
855                         info->filesize = 0;
856                         sc->ferror_send = FALSE;
857                         sc->ferror_count = 0;
858                         hcamcorder->error_occurs = FALSE;
859                         sc->bget_eos = FALSE;
860                         sc->muxed_stream_offset = 0;
861
862                         ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PLAYING);
863                         if (ret != MM_ERROR_NONE) {
864                                 /* stop video stream */
865                                 if (info->record_dual_stream) {
866                                         CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
867                                         if (CameraControl) {
868                                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
869
870                                                 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
871                                                 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
872
873                                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
874                                         } else {
875                                                 _mmcam_dbg_err("failed to get camera control");
876                                         }
877                                 }
878
879                                 /* Remove recorder pipeline and recording file which size maybe zero */
880                                 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
881                                 if (info->filename) {
882                                         _mmcam_dbg_log("file delete(%s)", info->filename);
883                                         unlink(info->filename);
884                                 }
885                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
886                         }
887
888                         /*set the camera control to create the GOP so that video record will get a new key frame*/
889                         if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
890                             GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
891                                 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
892                                 controls = gst_camera_control_list_channels(CameraControl);
893                                 if (controls != NULL) {
894                                         for (item = controls ; item && item->data ; item = item->next) {
895                                                 CameraControlChannel = item->data;
896                                                 _mmcam_dbg_log("CameraControlChannel->label %s", CameraControlChannel->label);
897                                                 if (!strcmp(CameraControlChannel->label, "new-gop")) {
898                                                         /* gst_camera_control_set_value(CameraControl, CameraControlChannel, 1); */
899                                                         break;
900                                                 }
901                                         }
902
903                                         if (item == NULL)
904                                                 _mmcam_dbg_warn("failed to find new-gop control channel");
905                                 }
906                         } else {
907                                 _mmcam_dbg_warn("Can't cast Video source into camera control or not H264 prevew format[%d]",
908                                         sc->info_image->preview_format);
909                         }
910                 } else {
911                         /* Resume case */
912
913                         if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 &&
914                             GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
915                                 /* generate and I-frame on resuming */
916                                 CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
917                                 controls = gst_camera_control_list_channels(CameraControl);
918                                 if (controls != NULL) {
919                                         for (item = controls ; item && item->data ; item = item->next) {
920                                                 CameraControlChannel = item->data;
921                                                 _mmcam_dbg_log("CameraControlChannel->label %s", CameraControlChannel->label);
922                                                 if (!strcmp(CameraControlChannel->label, "new-gop")) {
923                                                         /* gst_camera_control_set_value(CameraControl, CameraControlChannel, 1); */
924                                                         break;
925                                                 }
926                                         }
927
928                                         if (item == NULL)
929                                                 _mmcam_dbg_warn("failed to find new-gop control channel");
930                                 }
931                         }
932
933                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", FALSE);
934
935                         _mmcam_dbg_log("Object property settings done");
936                 }
937         }
938                 break;
939         case _MMCamcorder_CMD_PAUSE:
940         {
941                 if (info->b_commiting) {
942                         _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
943                         return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
944                 }
945
946                 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
947                         if (sc->audio_disable) {
948                                 /* check only video frame */
949                                 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
950                                         break;
951                                 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
952                                         _mmcam_dbg_err("Pause fail, frame count %llu", info->video_frame_count);
953                                         return MM_ERROR_CAMCORDER_INVALID_CONDITION;
954                                 } else {
955                                         _mmcam_dbg_warn("Waiting for enough video frame, retrial[%d], frame %llu", count, info->video_frame_count);
956                                 }
957
958                                 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
959                         } else {
960                                 /* check both of video and audio frame */
961                                 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
962                                         break;
963                                 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
964                                         _mmcam_dbg_err("Pause fail, frame count VIDEO[%llu], AUDIO [%llu]",
965                                                 info->video_frame_count, info->audio_frame_count);
966                                         return MM_ERROR_CAMCORDER_INVALID_CONDITION;
967                                 } else {
968                                         _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%llu], AUDIO [%llu]",
969                                                 count, info->video_frame_count, info->audio_frame_count);
970                                 }
971
972                                 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
973                         }
974                 }
975
976                 /* block encodebin */
977                 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", TRUE);
978                 break;
979         }
980         case _MMCamcorder_CMD_CANCEL:
981         {
982                 if (info->b_commiting) {
983                         _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
984                         return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
985                 }
986
987                 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
988                         /* capturing */
989                         if (hcamcorder->capture_in_recording == FALSE) {
990                                 break;
991                         } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
992                                 _mmcam_dbg_err("Failed to Wait capture data");
993                                 hcamcorder->capture_in_recording = FALSE;
994                                 break;
995                         } else {
996                                 _mmcam_dbg_warn("Waiting for capture data - retrial [%d]", count);
997                         }
998
999                         usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
1000                 }
1001
1002                 /* block push buffer */
1003                 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
1004
1005                 ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1006                 if (ret != MM_ERROR_NONE)
1007                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
1008
1009                 /* set recording hint */
1010                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
1011
1012                 /* stop video stream */
1013                 if (info->record_dual_stream) {
1014                         CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
1015                         if (CameraControl) {
1016                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
1017
1018                                 _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
1019                                 gst_camera_control_set_record_command(CameraControl, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
1020
1021                                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
1022                         } else {
1023                                 _mmcam_dbg_err("failed to get camera control");
1024                         }
1025                 }
1026
1027                 if (info->restart_preview) {
1028                         /* restart preview */
1029                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
1030                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1031                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
1032
1033                         ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
1034
1035                         /* check decoder recreation */
1036                         if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
1037                                 _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
1038                                 ret = MM_ERROR_CAMCORDER_INTERNAL;
1039                         }
1040
1041                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
1042                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
1043                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
1044
1045                         if (ret != MM_ERROR_NONE)
1046                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1047
1048                         /* reset restart_preview for inset window layout */
1049                         info->restart_preview = FALSE;
1050
1051                         if (!_mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height)) {
1052                                 ret = MM_ERROR_CAMCORDER_INTERNAL;
1053                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1054                         }
1055
1056                         ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
1057                         if (ret != MM_ERROR_NONE)
1058                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1059                 }
1060
1061                 /* remove target file */
1062                 if (info->filename) {
1063                         _mmcam_dbg_log("file delete(%s)", info->filename);
1064                         unlink(info->filename);
1065                 }
1066
1067                 sc->isMaxsizePausing = FALSE;
1068                 sc->isMaxtimePausing = FALSE;
1069
1070                 sc->display_interval = 0;
1071                 sc->previous_slot_time = 0;
1072                 info->video_frame_count = 0;
1073                 info->audio_frame_count = 0;
1074                 info->filesize = 0;
1075                 hcamcorder->capture_in_recording = FALSE;
1076                 break;
1077         }
1078         case _MMCamcorder_CMD_COMMIT:
1079         {
1080                 guint64 free_space;
1081
1082                 if (info->b_commiting) {
1083                         _mmcam_dbg_err("now on commiting previous file!!(command : %d)", command);
1084                         return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
1085                 } else {
1086                         _mmcam_dbg_log("_MMCamcorder_CMD_COMMIT : start");
1087                         info->b_commiting = TRUE;
1088                         sc->bget_eos = FALSE;
1089                 }
1090
1091                 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
1092                         if (sc->audio_disable) {
1093                                 /* check only video frame */
1094                                 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
1095                                     hcamcorder->capture_in_recording == FALSE) {
1096                                         break;
1097                                 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
1098                                         _mmcam_dbg_err("Commit fail, frame count is %llu, capturing %d",
1099                                                 info->video_frame_count, hcamcorder->capture_in_recording);
1100
1101                                         if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
1102                                                 _mmcam_dbg_warn("video frames are enough. keep going...");
1103                                         } else {
1104                                                 info->b_commiting = FALSE;
1105                                                 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1106                                         }
1107                                 } else {
1108                                         _mmcam_dbg_warn("Waiting for enough video frame, retrial [%d], frame %llu, capturing %d",
1109                                                 count, info->video_frame_count, hcamcorder->capture_in_recording);
1110                                 }
1111                         } else {
1112                                 /* check both of video and audio frame */
1113                                 if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME &&
1114                                     info->audio_frame_count &&
1115                                     hcamcorder->capture_in_recording == FALSE) {
1116                                         break;
1117                                 } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
1118                                         _mmcam_dbg_err("Commit fail, VIDEO[%llu], AUDIO [%llu], capturing %d",
1119                                                 info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
1120
1121                                         if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) {
1122                                                 _mmcam_dbg_warn("video/audio frames are enough. keep going...");
1123                                         } else {
1124                                                 info->b_commiting = FALSE;
1125                                                 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1126                                         }
1127
1128                                         return MM_ERROR_CAMCORDER_INVALID_CONDITION;
1129                                 } else {
1130                                         _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%llu], AUDIO [%llu], capturing %d",
1131                                                 count, info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording);
1132                                 }
1133                         }
1134
1135                         if (hcamcorder->capture_in_recording) {
1136                                 gint64 end_time = g_get_monotonic_time() + (200 * G_TIME_SPAN_MILLISECOND);
1137                                 if (!_MMCAMCORDER_CMD_WAIT_UNTIL(handle, end_time))
1138                                         _mmcam_dbg_warn("timeout");
1139                         } else {
1140                                 usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
1141                         }
1142                 }
1143
1144                 /* block push buffer */
1145                 info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP;
1146                 _mmcam_dbg_log("block push buffer to appsrc");
1147
1148                 _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
1149                 if (free_space < _MMCAMCORDER_MINIMUM_SPACE) {
1150                         _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT out of storage [%" G_GUINT64_FORMAT "]", free_space);
1151                         ret = MM_ERROR_OUT_OF_STORAGE;
1152                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
1153                 }
1154
1155                 if (sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst != NULL) {
1156                         if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, gst_event_new_eos())) {
1157                                 _mmcam_dbg_warn("VIDEO: send eos to appsrc done");
1158                         } else {
1159                                 _mmcam_dbg_err("VIDEO: send EOS failed");
1160                                 info->b_commiting = FALSE;
1161                                 ret = MM_ERROR_CAMCORDER_INTERNAL;
1162                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1163                         }
1164                 } else {
1165                         _mmcam_dbg_err("No video stream source");
1166                         info->b_commiting = FALSE;
1167                         ret = MM_ERROR_CAMCORDER_INTERNAL;
1168                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
1169                 }
1170
1171                 if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst != NULL) {
1172                         if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos())) {
1173                                 _mmcam_dbg_warn("AUDIO: send eos to audiosrc done");
1174                         } else {
1175                                 _mmcam_dbg_err("AUDIO: send EOS failed");
1176                                 info->b_commiting = FALSE;
1177                                 ret = MM_ERROR_CAMCORDER_INTERNAL;
1178                                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1179                         }
1180                 } else {
1181                         _mmcam_dbg_log("No audio stream");
1182                 }
1183
1184                 /* sc */
1185                 sc->display_interval = 0;
1186                 sc->previous_slot_time = 0;
1187
1188                 /* Wait EOS */
1189                 _mmcam_dbg_log("Start to wait EOS");
1190                 ret = _mmcamcorder_get_eos_message(handle);
1191                 if (ret != MM_ERROR_NONE) {
1192                         info->b_commiting = FALSE;
1193                         goto _ERR_CAMCORDER_VIDEO_COMMAND;
1194                 }
1195
1196                 /* reset flag */
1197                 hcamcorder->capture_in_recording = FALSE;
1198         }
1199                 break;
1200         default:
1201                 ret =  MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
1202                 goto _ERR_CAMCORDER_VIDEO_COMMAND;
1203         }
1204
1205         return MM_ERROR_NONE;
1206
1207 _ERR_CAMCORDER_VIDEO_COMMAND:
1208         if (command == _MMCamcorder_CMD_RECORD)
1209                 _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1210
1211         return ret;
1212 }
1213
1214
1215 int _mmcamcorder_video_handle_eos(MMHandleType handle)
1216 {
1217         int ret = MM_ERROR_NONE;
1218         int enabletag = 0;
1219         guint64 file_size = 0;
1220
1221         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1222         _MMCamcorderSubContext *sc = NULL;
1223         _MMCamcorderVideoInfo *info = NULL;
1224         _MMCamcorderMsgItem msg;
1225         MMCamRecordingReport *report = NULL;
1226
1227         mmf_return_val_if_fail(hcamcorder, FALSE);
1228
1229         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1230         mmf_return_val_if_fail(sc, FALSE);
1231         mmf_return_val_if_fail(sc->info_video, FALSE);
1232
1233         info = sc->info_video;
1234
1235         _mmcam_dbg_err("");
1236
1237         if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_FOCUS) {
1238                 /* Play record stop sound */
1239                 _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, FALSE);
1240         } else {
1241                 _mmcam_dbg_warn("Play stop sound through pulseaudio");
1242
1243                 _mmcamcorder_sound_init(handle);
1244
1245                 _mmcamcorder_sound_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_REC_STOP, TRUE);
1246
1247                 _mmcamcorder_sound_finalize(handle);
1248         }
1249
1250         /* remove blocking part */
1251         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1252
1253         mm_camcorder_get_attributes(handle, NULL,
1254                 MMCAM_RECORDER_TAG_ENABLE, &enabletag,
1255                 NULL);
1256
1257         ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
1258         if (ret != MM_ERROR_NONE)
1259                 _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline failed. error[%x]", ret);
1260
1261         /* set recording hint */
1262         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE);
1263
1264         /* stop video stream */
1265         if (info->record_dual_stream) {
1266                 GstCameraControl *control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
1267                 if (control) {
1268                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE);
1269
1270                         _mmcam_dbg_log("GST_CAMERA_CONTROL_RECORD_COMMAND_STOP");
1271                         gst_camera_control_set_record_command(control, GST_CAMERA_CONTROL_RECORD_COMMAND_STOP);
1272
1273                         MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
1274                 } else {
1275                         _mmcam_dbg_err("failed to get camera control");
1276                 }
1277         }
1278
1279         if (enabletag && !(sc->ferror_send)) {
1280                 ret = __mmcamcorder_add_metadata((MMHandleType)hcamcorder, info->fileformat);
1281                 _mmcam_dbg_log("Writing location information [%s] !!", ret ? "SUCCEEDED" : "FAILED");
1282         }
1283
1284         /* Check file size */
1285         if (info->max_size > 0) {
1286                 _mmcamcorder_get_file_size(info->filename, &file_size);
1287                 _mmcam_dbg_log("MAX size %lld byte - created filesize %lld byte",
1288                                            info->max_size, file_size);
1289
1290                 if (file_size > info->max_size) {
1291                         _MMCamcorderMsgItem message;
1292                         _mmcam_dbg_err("File size is greater than max size !!");
1293                         message.id = MM_MESSAGE_CAMCORDER_ERROR;
1294                         message.param.code = MM_ERROR_CAMCORDER_FILE_SIZE_OVER;
1295                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &message);
1296                 }
1297         }
1298
1299         if (info->restart_preview) {
1300                 /* block queue */
1301                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1302                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE);
1303                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", TRUE);
1304
1305                 _mmcam_dbg_log("Set state of pipeline as READY");
1306                 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY);
1307
1308                 /* check decoder recreation */
1309                 if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) {
1310                         _mmcam_dbg_err("_mmcamcorder_recreate_decoder_for_encoded_preview failed");
1311                         ret = MM_ERROR_CAMCORDER_INTERNAL;
1312                 }
1313
1314                 /* unblock queue */
1315                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
1316                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE);
1317                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "keep-camera-preview", FALSE);
1318
1319                 if (ret != MM_ERROR_NONE) {
1320                         msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1321                         msg.param.code = ret;
1322                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1323                         _mmcam_dbg_err("Failed to set state READY[%x]", ret);
1324                 }
1325
1326                 /* reset restart_preview for inset window layout */
1327                 info->restart_preview = FALSE;
1328
1329                 /* recover preview size */
1330                 if (!_mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height)) {
1331                         msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1332                         msg.param.code = MM_ERROR_CAMCORDER_INTERNAL;
1333                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1334                         _mmcam_dbg_err("Failed to set camera resolution %dx%d",
1335                                 info->preview_width, info->preview_height);
1336                 }
1337
1338                 ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_PLAYING);
1339                 /* Do not return when error is occurred.
1340                    Recording file was created successfully, but starting pipeline failed */
1341                 if (ret != MM_ERROR_NONE) {
1342                         msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1343                         msg.param.code = ret;
1344                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1345                         _mmcam_dbg_err("Failed to set state PLAYING[%x]", ret);
1346                 }
1347         } else {
1348                 _mmcam_dbg_log("No need to restart preview");
1349         }
1350
1351         /* Send recording report to application */
1352         msg.id = MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED;
1353         report = (MMCamRecordingReport *)g_malloc(sizeof(MMCamRecordingReport));
1354         if (!report) {
1355                 _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
1356         } else {
1357                 report->recording_filename = g_strdup(info->filename);
1358                 msg.param.data = report;
1359                 msg.param.code = 1;
1360                 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1361         }
1362
1363         /* Finishing */
1364         sc->pipeline_time = 0;
1365         sc->pause_time = 0;
1366         sc->isMaxsizePausing = FALSE; /*In async function, this variable should set in callback function. */
1367         sc->isMaxtimePausing = FALSE;
1368         hcamcorder->error_occurs = FALSE;
1369
1370         info->video_frame_count = 0;
1371         info->audio_frame_count = 0;
1372         info->filesize = 0;
1373         info->b_commiting = FALSE;
1374
1375         if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_FOCUS) {
1376                 /* check recording stop sound */
1377                 _mmcamcorder_sound_solo_play_wait(handle);
1378         }
1379
1380         _mmcam_dbg_err("_MMCamcorder_CMD_COMMIT : end");
1381
1382         return TRUE;
1383 }
1384
1385
1386 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1387 {
1388         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1389         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1390         GstMapInfo mapinfo;
1391         _MMCamcorderSubContext *sc = NULL;
1392         _MMCamcorderVideoInfo *videoinfo = NULL;
1393         _MMCamcorderMsgItem msg;
1394         guint64 buffer_size = 0;
1395         guint64 trailer_size = 0;
1396         guint64 max_size = 0;
1397
1398         mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1399         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1400         sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1401
1402         mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1403         videoinfo = sc->info_video;
1404
1405         /* get buffer size */
1406         if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) {
1407                 _mmcam_dbg_warn("map failed : buffer %p", buffer);
1408                 return GST_PAD_PROBE_OK;
1409         }
1410
1411         buffer_size = mapinfo.size;
1412         gst_buffer_unmap(buffer, &mapinfo);
1413
1414         /*_mmcam_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1415
1416         g_mutex_lock(&videoinfo->size_check_lock);
1417
1418         if (videoinfo->audio_frame_count == 0) {
1419                 videoinfo->filesize += buffer_size;
1420                 videoinfo->audio_frame_count++;
1421                 g_mutex_unlock(&videoinfo->size_check_lock);
1422                 return GST_PAD_PROBE_OK;
1423         }
1424
1425         if (sc->ferror_send || sc->isMaxsizePausing) {
1426                 _mmcam_dbg_warn("Recording is paused, drop frames");
1427                 g_mutex_unlock(&videoinfo->size_check_lock);
1428                 return GST_PAD_PROBE_DROP;
1429         }
1430
1431         /* get trailer size */
1432         if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1433                 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1434         else
1435                 trailer_size = 0;
1436
1437         /* check max size of recorded file */
1438         max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1439         if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1440                 GstState pipeline_state = GST_STATE_VOID_PENDING;
1441                 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1442                 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1443                 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1444                         " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1445                         videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1446
1447                 if (!sc->isMaxsizePausing) {
1448                         sc->isMaxsizePausing = TRUE;
1449                         gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1450                         if (pipeline_state == GST_STATE_PLAYING)
1451                                 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1452
1453                         msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1454                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1455                 }
1456
1457                 g_mutex_unlock(&videoinfo->size_check_lock);
1458
1459                 return FALSE;
1460         }
1461
1462         videoinfo->filesize += buffer_size;
1463         videoinfo->audio_frame_count++;
1464
1465         g_mutex_unlock(&videoinfo->size_check_lock);
1466
1467         return GST_PAD_PROBE_OK;
1468 }
1469
1470
1471 static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1472 {
1473         gint ret = 0;
1474         guint vq_size = 0;
1475         guint aq_size = 0;
1476         guint64 free_space = 0;
1477         guint64 buffer_size = 0;
1478         guint64 trailer_size = 0;
1479         guint64 queued_buffer = 0;
1480         guint64 max_size = 0;
1481         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1482         GstMapInfo mapinfo;
1483         storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE;
1484
1485         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1486         _MMCamcorderMsgItem msg;
1487         _MMCamcorderSubContext *sc = NULL;
1488         _MMCamcorderVideoInfo *videoinfo = NULL;
1489
1490         mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1491         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1492
1493         sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
1494         mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK);
1495         videoinfo = sc->info_video;
1496
1497         /*_mmcam_dbg_log("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1498         if (sc->ferror_send) {
1499                 _mmcam_dbg_warn("file write error, drop frames");
1500                 return GST_PAD_PROBE_DROP;
1501         }
1502
1503         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
1504         buffer_size = mapinfo.size;
1505         gst_buffer_unmap(buffer, &mapinfo);
1506
1507         videoinfo->video_frame_count++;
1508         if (videoinfo->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) {
1509                 /* _mmcam_dbg_log("Pass minimum frame: info->video_frame_count: %" G_GUINT64_FORMAT " ",
1510                         info->video_frame_count); */
1511                 g_mutex_lock(&videoinfo->size_check_lock);
1512                 videoinfo->filesize += buffer_size;
1513                 g_mutex_unlock(&videoinfo->size_check_lock);
1514                 return GST_PAD_PROBE_OK;
1515         }
1516
1517         /* get trailer size */
1518         if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1519                 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1520         else
1521                 trailer_size = 0;
1522
1523         /* check free space */
1524         ret = _mmcamcorder_get_freespace(hcamcorder->storage_info.type, &free_space);
1525         if (ret != 0) {
1526                 _mmcam_dbg_err("Error occured. [%d]", ret);
1527                 if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
1528                         sc->ferror_send = TRUE;
1529
1530                         msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1531                         msg.param.code = MM_ERROR_FILE_READ;
1532
1533                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1534                 } else {
1535                         sc->ferror_count++;
1536                 }
1537
1538                 return GST_PAD_PROBE_DROP; /* skip this buffer */
1539         }
1540
1541         if (free_space == 0) {
1542                 /* check storage state */
1543                 storage_get_state(hcamcorder->storage_info.id, &storage_state);
1544
1545                 _mmcam_dbg_warn("storage state %d", storage_state);
1546
1547                 if (storage_state == STORAGE_STATE_REMOVED ||
1548                         storage_state == STORAGE_STATE_UNMOUNTABLE) {
1549                         _mmcam_dbg_err("storage was removed!");
1550
1551                         _MMCAMCORDER_LOCK(hcamcorder);
1552
1553                         if (sc->ferror_send == FALSE) {
1554                                 _mmcam_dbg_err("OUT_OF_STORAGE error");
1555
1556                                 sc->ferror_send = TRUE;
1557
1558                                 _MMCAMCORDER_UNLOCK(hcamcorder);
1559
1560                                 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
1561                                 msg.param.code = MM_ERROR_OUT_OF_STORAGE;
1562
1563                                 _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1564                         } else {
1565                                 _MMCAMCORDER_UNLOCK(hcamcorder);
1566                                 _mmcam_dbg_warn("error was already sent");
1567                         }
1568
1569                         return GST_PAD_PROBE_DROP;
1570                 }
1571         }
1572
1573         /* get queued buffer size */
1574         if (sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst)
1575                 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "current-level-bytes", &aq_size);
1576
1577         if (sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst)
1578                 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "current-level-bytes", &vq_size);
1579
1580         queued_buffer = aq_size + vq_size;
1581
1582         if (free_space < (_MMCAMCORDER_MINIMUM_SPACE + buffer_size + trailer_size + queued_buffer)) {
1583                 _mmcam_dbg_warn("No more space for recording!!! Recording is paused.");
1584                 _mmcam_dbg_warn("Free Space : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]," \
1585                         " buffer size : [%" G_GUINT64_FORMAT "], queued buffer size : [%" G_GUINT64_FORMAT "]", \
1586                         free_space, trailer_size, buffer_size, queued_buffer);
1587
1588                 if (!sc->isMaxsizePausing) {
1589                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1590                         sc->isMaxsizePausing = TRUE;
1591
1592                         msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
1593                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1594                 }
1595
1596                 return GST_PAD_PROBE_DROP;
1597         }
1598
1599         g_mutex_lock(&videoinfo->size_check_lock);
1600
1601         /* check max size of recorded file */
1602         max_size = videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE;
1603         if (videoinfo->max_size > 0 && videoinfo->max_size < max_size) {
1604                 GstState pipeline_state = GST_STATE_VOID_PENDING;
1605                 GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
1606                 _mmcam_dbg_warn("Max size!!! Recording is paused.");
1607                 _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \
1608                         " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]",
1609                         videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size);
1610
1611                 if (!sc->isMaxsizePausing) {
1612                         sc->isMaxsizePausing = TRUE;
1613                         gst_element_get_state(pipeline, &pipeline_state, NULL, -1) ;
1614                         if (pipeline_state == GST_STATE_PLAYING)
1615                                 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1616
1617                         msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
1618                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1619                 }
1620
1621                 g_mutex_unlock(&videoinfo->size_check_lock);
1622
1623                 return GST_PAD_PROBE_DROP;
1624         }
1625
1626         videoinfo->filesize += (guint64)buffer_size;
1627
1628         /*
1629         _mmcam_dbg_log("filesize %lld Byte, ", videoinfo->filesize);
1630         */
1631
1632         g_mutex_unlock(&videoinfo->size_check_lock);
1633
1634         return GST_PAD_PROBE_OK;
1635 }
1636
1637
1638 static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1639 {
1640         guint64 trailer_size = 0;
1641         guint64 rec_pipe_time = 0;
1642         unsigned int remained_time = 0;
1643
1644         GstClockTime b_time;
1645
1646         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1647         _MMCamcorderMsgItem msg;
1648         _MMCamcorderSubContext *sc = NULL;
1649         _MMCamcorderVideoInfo *videoinfo = NULL;
1650
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
1656         sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
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
1660         videoinfo = sc->info_video;
1661
1662         b_time = GST_BUFFER_PTS(buffer);
1663
1664         rec_pipe_time = GST_TIME_AS_MSECONDS(b_time);
1665
1666         if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1667                 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1668         else
1669                 trailer_size = 0;
1670
1671         /* check max time */
1672         if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1673                 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1674                         rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1675
1676                 if (!sc->isMaxtimePausing) {
1677                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1678
1679                         sc->isMaxtimePausing = TRUE;
1680
1681                         msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1682                         msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1683                         msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1684                         msg.param.recording_status.remained_time = 0;
1685                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1686
1687                         msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1688                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1689                 }
1690
1691                 return GST_PAD_PROBE_DROP;
1692         }
1693
1694         /* calculate remained time can be recorded */
1695         if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1696                 remained_time = videoinfo->max_time - rec_pipe_time;
1697         } else if (videoinfo->max_size > 0) {
1698                 long double max_size = (long double)videoinfo->max_size;
1699                 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1700
1701                 remained_time = (unsigned int)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1702         }
1703
1704         msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1705         msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1706         msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1707         msg.param.recording_status.remained_time = remained_time;
1708         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1709
1710         /*
1711         _mmcam_dbg_log("time [%" GST_TIME_FORMAT "], size [%d]",
1712                 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1713         */
1714
1715         if (videoinfo->record_timestamp_ratio != _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1716                 guint record_motion_rate = (guint)videoinfo->record_motion_rate;
1717
1718                 /*
1719                 _mmcam_dbg_log("record_motion_rate %d, videoinfo->record_drop_count %d",
1720                         record_motion_rate, videoinfo->record_drop_count);
1721                 */
1722
1723                 /* drop some frame if fast motion */
1724                 if (videoinfo->record_motion_rate > _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) {
1725                         if (record_motion_rate != (videoinfo->record_drop_count++)) {
1726                                 /*
1727                                 _mmcam_dbg_warn("drop frame");
1728                                 */
1729                                 return GST_PAD_PROBE_DROP;
1730                         }
1731
1732                         videoinfo->record_drop_count = 1;
1733                         /*
1734                         _mmcam_dbg_warn("pass frame");
1735                         */
1736                 }
1737
1738                 GST_BUFFER_PTS(buffer) = b_time * (videoinfo->record_timestamp_ratio);
1739                 GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer);
1740         }
1741
1742         return GST_PAD_PROBE_OK;
1743 }
1744
1745
1746 static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1747 {
1748         _MMCamcorderMsgItem msg;
1749         guint64 trailer_size = 0;
1750         guint64 rec_pipe_time = 0;
1751         _MMCamcorderSubContext *sc = NULL;
1752         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1753         _MMCamcorderVideoInfo *videoinfo = NULL;
1754         unsigned int remained_time = 0;
1755         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1756
1757         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1758         mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
1759         sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
1760
1761         mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1762         mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1763         mmf_return_val_if_fail(sc->element, GST_PAD_PROBE_OK);
1764
1765         videoinfo = sc->info_video;
1766
1767         if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) {
1768                 _mmcam_dbg_err("Buffer timestamp is invalid, check it");
1769                 return GST_PAD_PROBE_OK;
1770         }
1771
1772         rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer));
1773
1774         if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4)
1775                 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1776         else
1777                 trailer_size = 0;
1778
1779         /* calculate remained time can be recorded */
1780         if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) {
1781                 remained_time = videoinfo->max_time - rec_pipe_time;
1782         } else if (videoinfo->max_size > 0) {
1783                 long double max_size = (long double)videoinfo->max_size;
1784                 long double current_size = (long double)(videoinfo->filesize + trailer_size);
1785
1786                 remained_time = (unsigned long long)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
1787         }
1788
1789         if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1790                 _mmcam_dbg_warn("Time current [%" G_GUINT64_FORMAT "], Max [%" G_GUINT64_FORMAT "], motion rate [%lf]", \
1791                         rec_pipe_time, videoinfo->max_time, videoinfo->record_motion_rate);
1792
1793                 if (!sc->isMaxtimePausing) {
1794                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1795
1796                         sc->isMaxtimePausing = TRUE;
1797
1798                         msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1799                         msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1800                         msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1801                         msg.param.recording_status.remained_time = 0;
1802                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1803
1804                         msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1805                         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1806                 }
1807
1808                 return GST_PAD_PROBE_DROP;
1809         }
1810
1811         msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1812         msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1813         msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1814         msg.param.recording_status.remained_time = remained_time;
1815         _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg);
1816
1817         /*
1818         _mmcam_dbg_log("audio data probe :: time [%" GST_TIME_FORMAT "], size [%lld KB]",
1819                 GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1820         */
1821
1822         return GST_PAD_PROBE_OK;
1823 }
1824
1825
1826 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1827 {
1828         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
1829         double volume = 0.0;
1830         int format = 0;
1831         int channel = 0;
1832         int err = MM_ERROR_UNKNOWN;
1833         char *err_name = NULL;
1834         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1835         GstMapInfo mapinfo;
1836
1837         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1838         mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP);
1839
1840         /*_mmcam_dbg_log("AUDIO SRC time stamp : [%" GST_TIME_FORMAT "] \n", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/
1841         err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name,
1842                 MMCAM_AUDIO_VOLUME, &volume,
1843                 MMCAM_AUDIO_FORMAT, &format,
1844                 MMCAM_AUDIO_CHANNEL, &channel,
1845                 NULL);
1846         if (err != MM_ERROR_NONE) {
1847                 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
1848                 SAFE_FREE(err_name);
1849                 return err;
1850         }
1851
1852         memset(&mapinfo, 0x0, sizeof(GstMapInfo));
1853
1854         gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE);
1855
1856         /* Set audio stream NULL */
1857         if (volume == 0.0)
1858                 memset(mapinfo.data, 0, mapinfo.size);
1859
1860         /* CALL audio stream callback */
1861         if (hcamcorder->astream_cb && buffer && mapinfo.data && mapinfo.size > 0) {
1862                 MMCamcorderAudioStreamDataType stream;
1863
1864                 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE) {
1865                         _mmcam_dbg_warn("Not ready for stream callback");
1866                         gst_buffer_unmap(buffer, &mapinfo);
1867                         return GST_PAD_PROBE_OK;
1868                 }
1869
1870                 /*_mmcam_dbg_log("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
1871                         GST_BUFFER_DATA(buffer), width, height, format);*/
1872
1873                 stream.data = (void *)mapinfo.data;
1874                 stream.format = format;
1875                 stream.channel = channel;
1876                 stream.length = mapinfo.size;
1877                 stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano -> milli second */
1878
1879                 _MMCAMCORDER_LOCK_ASTREAM_CALLBACK(hcamcorder);
1880
1881                 if (hcamcorder->astream_cb)
1882                         hcamcorder->astream_cb(&stream, hcamcorder->astream_cb_param);
1883
1884                 _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(hcamcorder);
1885         }
1886
1887         gst_buffer_unmap(buffer, &mapinfo);
1888         return GST_PAD_PROBE_OK;
1889 }
1890
1891
1892 static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat)
1893 {
1894         gboolean bret = FALSE;
1895
1896         switch (fileformat) {
1897         case MM_FILE_FORMAT_3GP:
1898         case MM_FILE_FORMAT_MP4:
1899                 bret = __mmcamcorder_add_metadata_mp4(handle);
1900                 break;
1901         default:
1902                 _mmcam_dbg_warn("Unsupported fileformat to insert location info (%d)", fileformat);
1903                 break;
1904         }
1905
1906         return bret;
1907 }
1908
1909
1910 static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle)
1911 {
1912         FILE *f = NULL;
1913         guchar buf[4];
1914         guint64 udta_size = 0;
1915         gint64 current_pos = 0;
1916         gint64 moov_pos = 0;
1917         gint64 udta_pos = 0;
1918         gdouble longitude = 0;
1919         gdouble latitude = 0;
1920         gdouble altitude = 0;
1921         int err = 0;
1922         int orientation = 0;
1923         int gps_enable = 0;
1924         char *err_name = NULL;
1925         char err_msg[MAX_ERROR_MESSAGE_LEN] = {'\0',};
1926         _MMCamcorderLocationInfo location_info = {0, 0, 0};
1927         _MMCamcorderLocationInfo geo_info = {0, 0, 0};
1928
1929         _MMCamcorderVideoInfo *info = NULL;
1930         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1931         _MMCamcorderSubContext *sc = NULL;
1932
1933         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1934         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1935
1936         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1937         mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1938
1939         _mmcam_dbg_log("");
1940
1941         info = sc->info_video;
1942
1943         f = fopen64(info->filename, "rb+");
1944         if (f == NULL) {
1945                 strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN);
1946                 _mmcam_dbg_err("file open failed [%s]", err_msg);
1947                 return FALSE;
1948         }
1949
1950         mm_camcorder_get_attributes(handle, &err_name,
1951                 MMCAM_TAG_LATITUDE, &latitude,
1952                 MMCAM_TAG_LONGITUDE, &longitude,
1953                 MMCAM_TAG_ALTITUDE, &altitude,
1954                 MMCAM_TAG_VIDEO_ORIENTATION, &orientation,
1955                 MMCAM_TAG_GPS_ENABLE, &gps_enable,
1956                 NULL);
1957         if (err_name) {
1958                 _mmcam_dbg_warn("Get tag attrs fail. (%s:%x)", err_name, err);
1959                 SAFE_FREE(err_name);
1960         }
1961
1962         location_info.longitude = _mmcamcorder_double_to_fix(longitude);
1963         location_info.latitude = _mmcamcorder_double_to_fix(latitude);
1964         location_info.altitude = _mmcamcorder_double_to_fix(altitude);
1965         geo_info.longitude = longitude *10000;
1966         geo_info.latitude = latitude *10000;
1967         geo_info.altitude = altitude *10000;
1968         /* find udta container.
1969            if, there are udta container, write loci box after that
1970            else, make udta container and write loci box. */
1971         if (_mmcamcorder_find_fourcc(f, MMCAM_FOURCC('u', 'd', 't', 'a'), TRUE)) {
1972                 size_t nread = 0;
1973
1974                 _mmcam_dbg_log("find udta container");
1975
1976                 /* read size */
1977                 if (fseek(f, -8L, SEEK_CUR) != 0)
1978                         goto fail;
1979
1980                 udta_pos = ftello(f);
1981                 if (udta_pos < 0)
1982                         goto ftell_fail;
1983
1984                 nread = fread(&buf, sizeof(char), sizeof(buf), f);
1985
1986                 _mmcam_dbg_log("recorded file fread %d", nread);
1987
1988                 udta_size = _mmcamcorder_get_container_size(buf);
1989
1990                 /* goto end of udta and write 'loci' box */
1991                 if (fseek(f, (udta_size-4L), SEEK_CUR) != 0)
1992                         goto fail;
1993
1994                 if (gps_enable) {
1995                         if (!_mmcamcorder_write_loci(f, location_info)) {
1996                                 _mmcam_dbg_err("failed to write loci");
1997                                 goto fail;
1998                         }
1999
2000                         if (!_mmcamcorder_write_geodata(f, geo_info)) {
2001                                 _mmcam_dbg_err("failed to write geodata");
2002                                 goto fail;
2003                         }
2004                 }
2005
2006                 current_pos = ftello(f);
2007                 if (current_pos < 0)
2008                         goto ftell_fail;
2009
2010                 if (!_mmcamcorder_update_size(f, udta_pos, current_pos))
2011                         goto fail;
2012         } else {
2013                 _mmcam_dbg_log("No udta container");
2014                 if (fseek(f, 0, SEEK_END) != 0)
2015                         goto fail;
2016
2017                 if (!_mmcamcorder_write_udta(f, gps_enable, location_info, geo_info)) {
2018                         _mmcam_dbg_err("failed to write udta");
2019                         goto fail;
2020                 }
2021         }
2022
2023         /* find moov container.
2024            update moov container size. */
2025         if ((current_pos = ftello(f)) < 0)
2026                 goto ftell_fail;
2027
2028         if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('m', 'o', 'o', 'v'), TRUE)) {
2029                 gint64 internal_pos = ftello(f);
2030
2031                 _mmcam_dbg_log("found moov container");
2032                 if (fseek(f, -8L, SEEK_CUR) != 0)
2033                         goto fail;
2034
2035                 moov_pos = ftello(f);
2036                 if (moov_pos < 0)
2037                         goto ftell_fail;
2038
2039                 if (!_mmcamcorder_update_size(f, moov_pos, current_pos))
2040                         goto fail;
2041
2042                 /* add orientation info */
2043                 if (fseeko(f, internal_pos, SEEK_SET) < 0) {
2044                         _mmcam_dbg_err("fseeko failed : errno %d", errno);
2045                         goto fail;
2046                 }
2047
2048                 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'r', 'a', 'k'), FALSE)) {
2049                         _mmcam_dbg_err("failed to find [trak] tag");
2050                         goto fail;
2051                 }
2052
2053                 if (!_mmcamcorder_find_tag(f, MMCAM_FOURCC('t', 'k', 'h', 'd'), FALSE)) {
2054                         _mmcam_dbg_err("failed to find [tkhd] tag");
2055                         goto fail;
2056                 }
2057
2058                 _mmcam_dbg_log("found [tkhd] tag");
2059
2060                 /* seek to start position of composition matrix */
2061                 if (fseek(f, _OFFSET_COMPOSITION_MATRIX, SEEK_CUR) == 0) {
2062                         /* update composition matrix for orientation */
2063                         _mmcamcorder_update_composition_matrix(f, orientation);
2064                 } else {
2065                         _mmcam_dbg_err("fseek failed : errno %d", errno);
2066                         goto fail;
2067                 }
2068         } else {
2069                 _mmcam_dbg_err("No 'moov' container");
2070                 goto fail;
2071         }
2072
2073         fclose(f);
2074         return TRUE;
2075
2076 fail:
2077         fclose(f);
2078         return FALSE;
2079
2080 ftell_fail:
2081         _mmcam_dbg_err("ftell() returns negative value.");
2082         fclose(f);
2083         return FALSE;
2084 }
2085
2086
2087 int _mmcamcorder_connect_video_stream_cb_signal(MMHandleType handle)
2088 {
2089         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2090         _MMCamcorderSubContext *sc = NULL;
2091
2092         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2093
2094         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2095         mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2096
2097         /* check video source element */
2098         if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
2099                 _mmcam_dbg_warn("connect video stream cb signal to _MMCAMCORDER_VIDEOSRC_SRC");
2100                 MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst,
2101                         _MMCAMCORDER_HANDLER_VIDEOREC, "video-stream-cb",
2102                         G_CALLBACK(__mmcamcorder_video_stream_cb),
2103                         hcamcorder);
2104                 return MM_ERROR_NONE;
2105         } else {
2106                 _mmcam_dbg_err("videosrc element is not created yet");
2107                 return MM_ERROR_CAMCORDER_NOT_INITIALIZED;
2108         }
2109 }
2110
2111
2112 int _mmcamcorder_video_prepare_record(MMHandleType handle)
2113 {
2114         int ret = MM_ERROR_NONE;
2115         int size = 0;
2116         char *temp_filename = NULL;
2117
2118         _MMCamcorderVideoInfo *info = NULL;
2119         _MMCamcorderSubContext *sc = NULL;
2120         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
2121
2122         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2123
2124         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
2125         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2126         mmf_return_val_if_fail(sc->info_video, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
2127
2128         info = sc->info_video;
2129
2130         _mmcam_dbg_warn("start");
2131
2132         /* create encoding pipeline */
2133         ret = _mmcamcorder_create_recorder_pipeline((MMHandleType)hcamcorder);
2134         if (ret != MM_ERROR_NONE)
2135                 goto _ERR_PREPARE_RECORD;
2136
2137         SAFE_G_FREE(info->filename);
2138
2139         mm_camcorder_get_attributes(handle, NULL,
2140                 MMCAM_TARGET_FILENAME, &temp_filename, &size,
2141                 NULL);
2142         if (temp_filename) {
2143                 info->filename = g_strdup(temp_filename);
2144                 if (!info->filename) {
2145                         _mmcam_dbg_err("strdup[src:%p] was failed", temp_filename);
2146                         goto _ERR_PREPARE_RECORD;
2147                 }
2148
2149                 _mmcam_dbg_log("Record file name [%s]", info->filename);
2150                 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
2151         } else {
2152                 _mmcam_dbg_log("Recorded data will be written in [%s]", _MMCamcorder_FILENAME_NULL);
2153                 MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", _MMCamcorder_FILENAME_NULL);
2154         }
2155
2156         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", 0);
2157
2158         /* Adjust display FPS */
2159         sc->display_interval = 0;
2160         sc->previous_slot_time = 0;
2161
2162         ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PAUSED);
2163         if (ret != MM_ERROR_NONE)
2164                 goto _ERR_PREPARE_RECORD;
2165
2166         _mmcam_dbg_warn("done");
2167
2168         return ret;
2169
2170 _ERR_PREPARE_RECORD:
2171         /* Remove recorder pipeline and recording file which size maybe zero */
2172         _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
2173         if (info && info->filename) {
2174                 _mmcam_dbg_log("file delete(%s)", info->filename);
2175                 unlink(info->filename);
2176         }
2177
2178         return ret;
2179 }