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