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