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