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