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