1. Seperate preview pipeline and encoding pipeline
[platform/core/multimedia/libmm-camcorder.git] / src / mm_camcorder_audiorec.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 "mm_camcorder_internal.h"
26 #include "mm_camcorder_audiorec.h"
27 #include "mm_camcorder_util.h"
28 #include <math.h>
29
30 /*---------------------------------------------------------------------------------------
31 |    GLOBAL VARIABLE DEFINITIONS for internal                                           |
32 ---------------------------------------------------------------------------------------*/
33 #define MM_CAMCORDER_START_CHANGE_STATE _MMCamcorderStartHelperFunc((void *)hcamcorder)
34 #define MM_CAMCORDER_STOP_CHANGE_STATE _MMCamcorderStopHelperFunc((void *)hcamcorder)
35 /*---------------------------------------------------------------------------------------
36 |    LOCAL VARIABLE DEFINITIONS for internal                                            |
37 ---------------------------------------------------------------------------------------*/
38 #define RESET_PAUSE_TIME                        0
39 #define _MMCAMCORDER_AUDIO_MINIMUM_SPACE        (100*1024)
40 #define _MMCAMCORDER_AUDIO_MARGIN_SPACE         (1*1024)
41 #define _MMCAMCORDER_RETRIAL_COUNT              10
42 #define _MMCAMCORDER_FRAME_WAIT_TIME            20000 /* micro second */
43 #define _MMCAMCORDER_FREE_SPACE_CHECK_INTERVAL  10
44
45 /*---------------------------------------------------------------------------------------
46 |    LOCAL FUNCTION PROTOTYPES:                                                         |
47 ---------------------------------------------------------------------------------------*/
48 /* STATIC INTERNAL FUNCTION */
49 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
50 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
51 static int __mmcamcorder_create_audiop_with_encodebin(MMHandleType handle);
52 static void __mmcamcorder_audiorec_pad_added_cb(GstElement *element, GstPad *pad, MMHandleType handle);
53
54 /*=======================================================================================
55 |  FUNCTION DEFINITIONS                                                                 |
56 =======================================================================================*/
57
58 /*---------------------------------------------------------------------------------------
59 |    GLOBAL FUNCTION DEFINITIONS:                                                       |
60 ---------------------------------------------------------------------------------------*/
61
62 static int __mmcamcorder_create_audiop_with_encodebin(MMHandleType handle)
63 {
64         int err = MM_ERROR_NONE;
65         const char *aenc_name = NULL;
66         const char *mux_name = NULL;
67
68         GstBus *bus = NULL;
69         GstPad *srcpad = NULL;
70         GstPad *sinkpad = NULL;
71         GList *element_list = NULL;
72
73         _MMCamcorderAudioInfo *info = NULL;
74         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
75         _MMCamcorderSubContext *sc = NULL;
76         type_element *aenc_elem = NULL;
77         type_element *mux_elem = NULL;
78
79         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
80         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
81
82         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
83         mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
84         mmf_return_val_if_fail(sc->info_audio, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
85
86         info = (_MMCamcorderAudioInfo *)sc->info_audio;
87
88         _mmcam_dbg_log("");
89
90         mux_elem = _mmcamcorder_get_type_element(handle, MM_CAM_FILE_FORMAT);
91         err = _mmcamcorder_conf_get_value_element_name( mux_elem, &mux_name );
92
93         if (!mux_name || !strcmp(mux_name, "wavenc")) {
94                 /* IF MUX in not chosen then record in raw file */
95                 _mmcam_dbg_log("Record without muxing.");
96                 info->bMuxing = FALSE;
97         } else {
98                 _mmcam_dbg_log("Record with mux.");
99                 info->bMuxing = TRUE;
100         }
101
102         /* Create GStreamer pipeline */
103         _MMCAMCORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCODE_MAIN_PIPE, "camcorder_pipeline", err);
104
105         err = _mmcamcorder_create_audiosrc_bin(handle);
106         if (err != MM_ERROR_NONE) {
107                 return err;
108         }
109
110         if (info->bMuxing) {
111                 /* Muxing. can use encodebin. */
112                 err = _mmcamcorder_create_encodesink_bin((MMHandleType)hcamcorder, MM_CAMCORDER_ENCBIN_PROFILE_AUDIO);
113                 if (err != MM_ERROR_NONE) {
114                         return err;
115                 }
116         } else {
117                 /* without muxing. can't use encodebin. */
118                 aenc_elem = _mmcamcorder_get_type_element(handle, MM_CAM_AUDIO_ENCODER);
119                 if (!aenc_elem) {
120                         _mmcam_dbg_err("Fail to get type element");
121                         err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
122                         goto pipeline_creation_error;
123                 }
124
125                 err = _mmcamcorder_conf_get_value_element_name(aenc_elem, &aenc_name);
126                 if ((!err) || (!aenc_name)) {
127                         _mmcam_dbg_err("Fail to get element name");
128                         err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
129                         goto pipeline_creation_error;
130                 }
131
132                 _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCSINK_AQUE, "queue",  NULL, element_list, err);
133
134                 if (strcmp(aenc_name, "wavenc") != 0) {
135                         _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCSINK_CONV, "audioconvert",  NULL, element_list, err);
136                 }
137
138                 _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCSINK_AENC, aenc_name, NULL, element_list, err);
139
140                 _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCSINK_SINK, "filesink", NULL, element_list, err);
141         }
142
143         /* Add and link elements */
144         if (info->bMuxing) {
145                 /* IF MUX is indicated create MUX */
146                 gst_bin_add_many(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
147                                  sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst,
148                                  sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst,
149                                  NULL);
150
151                 srcpad = gst_element_get_static_pad (sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
152                 sinkpad = gst_element_get_static_pad (sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
153                 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
154         } else {
155                 /* IF MUX in not chosen then record in raw amr file */
156                 if (!strcmp(aenc_name, "wavenc")) {
157                         gst_bin_add_many(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
158                                          sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst,
159                                          sc->encode_element[_MMCAMCORDER_ENCSINK_AQUE].gst,
160                                          sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst,
161                                          sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst,
162                                          NULL);
163
164                         if (!_MM_GST_ELEMENT_LINK_MANY(sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst,
165                                                        sc->encode_element[_MMCAMCORDER_ENCSINK_AQUE].gst,
166                                                        sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst,
167                                                        sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst,
168                                                        NULL)) {
169                                 err = MM_ERROR_CAMCORDER_GST_LINK;
170                                 goto pipeline_creation_error;
171                         }
172                 } else {
173                         gst_bin_add_many(GST_BIN(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst),
174                                          sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst,
175                                          sc->encode_element[_MMCAMCORDER_ENCSINK_AQUE].gst,
176                                          sc->encode_element[_MMCAMCORDER_ENCSINK_CONV].gst,
177                                          sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst,
178                                          sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst,
179                                          NULL);
180
181                         if (!_MM_GST_ELEMENT_LINK_MANY(sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst,
182                                                        sc->encode_element[_MMCAMCORDER_ENCSINK_AQUE].gst,
183                                                        sc->encode_element[_MMCAMCORDER_ENCSINK_CONV].gst,
184                                                        sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst,
185                                                        sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst,
186                                                        NULL)) {
187                                 err = MM_ERROR_CAMCORDER_GST_LINK;
188                                 goto pipeline_creation_error;
189                         }
190                 }
191         }
192
193         /* set data probe function */
194         srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, "src");
195         MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_AUDIOREC,
196                                      __mmcamcorder_audio_dataprobe_voicerecorder, hcamcorder);
197         gst_object_unref(srcpad);
198         srcpad = NULL;
199
200         if (info->bMuxing) {
201                 MMCAMCORDER_SIGNAL_CONNECT(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst,
202                                            _MMCAMCORDER_HANDLER_AUDIOREC,
203                                            "pad-added",
204                                            __mmcamcorder_audiorec_pad_added_cb,
205                                            hcamcorder);
206         } else {
207                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
208                 MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_AUDIOREC,
209                                              __mmcamcorder_audio_dataprobe_record, hcamcorder);
210                 gst_object_unref(srcpad);
211                 srcpad = NULL;
212         }
213
214         bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst));
215
216         /* register message callback  */
217         hcamcorder->pipeline_cb_event_id = gst_bus_add_watch(bus, (GstBusFunc)_mmcamcorder_pipeline_cb_message, hcamcorder);
218
219         /* set sync callback */
220         gst_bus_set_sync_handler(bus, gst_bus_sync_signal_handler, hcamcorder, NULL);
221
222         gst_object_unref(bus);
223         bus = NULL;
224
225         if (element_list) {
226                 g_list_free(element_list);
227                 element_list = NULL;
228         }
229
230         return MM_ERROR_NONE;
231
232 pipeline_creation_error:
233         _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_ENCODE_MAIN_PIPE);
234         _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_AUDIOSRC_BIN);
235         _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_ENCSINK_AQUE);
236         _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_ENCSINK_CONV);
237         _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_ENCSINK_AENC);
238         _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_ENCSINK_SINK);
239         _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_ENCSINK_BIN);
240
241         if (element_list) {
242                 g_list_free(element_list);
243                 element_list = NULL;
244         }
245
246         return err;
247 }
248
249
250 int
251 _mmcamcorder_create_audio_pipeline(MMHandleType handle)
252 {
253         mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
254         _MMCamcorderSubContext *sc = NULL;
255
256         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
257         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
258
259         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
260
261         return __mmcamcorder_create_audiop_with_encodebin(handle);
262 }
263
264
265 /**
266  * This function destroy audio pipeline.
267  *
268  * @param[in]   handle          Handle of camcorder.
269  * @return      void
270  * @remarks
271  * @see         _mmcamcorder_destroy_pipeline()
272  *
273  */
274 void
275 _mmcamcorder_destroy_audio_pipeline(MMHandleType handle)
276 {
277         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
278         _MMCamcorderSubContext *sc = NULL;
279         _MMCamcorderAudioInfo *info = NULL;
280         mmf_return_if_fail(hcamcorder);
281         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
282
283         mmf_return_if_fail(sc && sc->info_audio);
284         mmf_return_if_fail(sc->element);
285
286         info = sc->info_audio;
287
288         _mmcam_dbg_log("start");
289
290         if (sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst) {
291                 _mmcam_dbg_warn("release audio pipeline");
292
293                 _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_NULL);
294
295                 _mmcamcorder_remove_all_handlers((MMHandleType)hcamcorder, _MMCAMCORDER_HANDLER_CATEGORY_ALL);
296
297                 if (info->bMuxing) {
298                         GstPad *reqpad = NULL;
299                         /* FIXME:
300                             Release request pad
301                             The ref_count of mux is always # of streams in here, i don't know why it happens.
302                             So, i unref the mux manually
303                         */
304                         reqpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "audio");
305                         gst_element_release_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
306                         gst_object_unref(reqpad);
307
308                         if(GST_IS_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst) &&
309                            GST_OBJECT_REFCOUNT(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst) > 1) {
310                                 gst_object_unref(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst);
311                         }
312                 }
313                 gst_object_unref(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst);
314         }
315
316         _mmcam_dbg_log("done");
317
318         return;
319 }
320
321
322 /**
323  * This function operates each command on audio mode.
324  *
325  * @param       c               [in]    Handle of camcorder context.
326  * @param       command [in]    command type received from Multimedia Framework.
327  *
328  * @return      This function returns MM_ERROR_NONE on success, or the other values
329  *                      on error.
330  * @remark
331  * @see         _mmcamcorder_set_functions()
332  *
333  */
334  /* ADDED BY SISO */
335
336
337 void* _MMCamcorderStartHelperFunc(void *handle)
338 {
339         mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
340         _mmcamcorder_set_state((MMHandleType)hcamcorder, hcamcorder->target_state);
341
342         return NULL;
343 }
344
345 void* _MMCamcorderStopHelperFunc(void *handle)
346 {
347         mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
348         _mmcamcorder_set_state((MMHandleType)hcamcorder, hcamcorder->target_state);
349
350         return NULL;
351 }
352
353
354 int
355 _mmcamcorder_audio_command(MMHandleType handle, int command)
356 {
357         int cmd = command;
358         int ret = MM_ERROR_NONE;
359         int err = 0;
360         int size=0;
361         guint64 free_space = 0;
362         char *dir_name = NULL;
363         char *err_attr_name = NULL;
364
365         GstElement *pipeline = NULL;
366         GstElement *audioSrc = NULL;
367
368         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
369         _MMCamcorderSubContext *sc = NULL;
370         _MMCamcorderAudioInfo *info = NULL;
371
372         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
373         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
374
375         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
376         mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
377         mmf_return_val_if_fail(sc->info_audio, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
378         pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
379         info = sc->info_audio;
380
381         _mmcam_dbg_log("");
382
383         pipeline = sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst;
384         audioSrc = sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst;
385         switch (cmd) {
386         case _MMCamcorder_CMD_RECORD:
387                 /* check status for resume case */
388                 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) != MM_CAMCORDER_STATE_PAUSED) {
389                         guint imax_size = 0;
390                         guint imax_time = 0;
391                         char *temp_filename = NULL;
392                         int file_system_type = 0;
393
394                         if(sc->pipeline_time) {
395                                 gst_element_set_start_time(pipeline, sc->pipeline_time);
396                         }
397                         sc->pipeline_time = RESET_PAUSE_TIME;
398
399                         ret = mm_camcorder_get_attributes(handle, &err_attr_name,
400                                                           MMCAM_TARGET_MAX_SIZE, &imax_size,
401                                                           MMCAM_TARGET_TIME_LIMIT, &imax_time,
402                                                           MMCAM_FILE_FORMAT, &(info->fileformat),
403                                                           MMCAM_TARGET_FILENAME, &temp_filename, &size,
404                                                           NULL);
405                         if (ret != MM_ERROR_NONE) {
406                                 _mmcam_dbg_warn("failed to get attribute. (%s:%x)", err_attr_name, ret);
407                                 SAFE_FREE(err_attr_name);
408                                 goto _ERR_CAMCORDER_AUDIO_COMMAND;
409                         }
410
411                         if (temp_filename == NULL) {
412                                 _mmcam_dbg_err("filename is not set");
413                                 ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
414                                 goto _ERR_CAMCORDER_AUDIO_COMMAND;
415                         }
416
417                         info->filename = strdup(temp_filename);
418                         if (!info->filename) {
419                                 _mmcam_dbg_err("STRDUP was failed");
420                                 goto _ERR_CAMCORDER_AUDIO_COMMAND;
421                         }
422
423                         _mmcam_dbg_log("Record start : set file name using attribute - %s\n ",info->filename);
424
425                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
426
427                         sc->ferror_send = FALSE;
428                         sc->ferror_count = 0;
429                         sc->bget_eos = FALSE;
430                         info->filesize =0;
431
432                         /* set max size */
433                         if (imax_size <= 0) {
434                                 info->max_size = 0; /* do not check */
435                         } else {
436                                 info->max_size = ((guint64)imax_size) << 10; /* to byte */
437                         }
438
439                         /* set max time */
440                         if (imax_time <= 0) {
441                                 info->max_time = 0; /* do not check */
442                         } else {
443                                 info->max_time = ((guint64)imax_time) * 1000; /* to millisecond */
444                         }
445
446                         /* TODO : check free space before recording start */
447                         dir_name = g_path_get_dirname(info->filename);
448                         if (dir_name) {
449                                 err = _mmcamcorder_get_freespace(dir_name, &free_space);
450                                 _mmcam_dbg_warn("current space for recording - %s :[%" G_GUINT64_FORMAT "]" ,dir_name, free_space);
451
452                                 if (_mmcamcorder_get_file_system_type(dir_name, &file_system_type) == 0) {
453                                         /* MSDOS_SUPER_MAGIC : 0x4d44 */
454                                         if (file_system_type == MSDOS_SUPER_MAGIC &&
455                                             (info->max_size == 0 || info->max_size > FAT32_FILE_SYSTEM_MAX_SIZE)) {
456                                                 _mmcam_dbg_warn("FAT32 and too large max[%"G_GUINT64_FORMAT"], set max as %"G_GUINT64_FORMAT,
457                                                                 info->max_size, FAT32_FILE_SYSTEM_MAX_SIZE);
458                                                 info->max_size = FAT32_FILE_SYSTEM_MAX_SIZE;
459                                         } else {
460                                                 _mmcam_dbg_warn("file system 0x%x, max size %"G_GUINT64_FORMAT,
461                                                                 file_system_type, info->max_size);
462                                         }
463                                 } else {
464                                         _mmcam_dbg_warn("_mmcamcorder_get_file_system_type failed");
465                                 }
466
467                                 g_free(dir_name);
468                                 dir_name = NULL;
469                         } else {
470                                 _mmcam_dbg_err("failed to get directory name");
471                                 err = -1;
472                         }
473
474                         if ((err == -1) || free_space <= (_MMCAMCORDER_AUDIO_MINIMUM_SPACE+(5*1024))) {
475                                 _mmcam_dbg_err("OUT of STORAGE [err:%d or free space [%" G_GUINT64_FORMAT "] is smaller than [%d]",
476                                                err, free_space, (_MMCAMCORDER_AUDIO_MINIMUM_SPACE+(5*1024)));
477                                 return MM_ERROR_OUT_OF_STORAGE;
478                         }
479                 }
480
481                 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
482                 if (ret != MM_ERROR_NONE) {
483                         goto _ERR_CAMCORDER_AUDIO_COMMAND;
484                 }
485                 break;
486
487         case _MMCamcorder_CMD_PAUSE:
488         {
489                 GstClock *pipe_clock = NULL;
490                 int count = 0;
491
492                 if (info->b_commiting) {
493                         _mmcam_dbg_warn("now on commiting previous file!!(cmd : %d)", cmd);
494                         return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
495                 }
496
497                 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
498                         if (info->filesize > 0) {
499                                 break;
500                         } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
501                                 _mmcam_dbg_err("Pause fail, wait 200 ms, but file size is %lld",
502                                                info->filesize);
503                                 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
504                         } else {
505                                 _mmcam_dbg_warn("Wait for enough audio frame, retry count[%d], file size is %lld",
506                                                 count, info->filesize);
507                         }
508                         usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
509                 }
510
511                 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PAUSED);
512                 if (ret != MM_ERROR_NONE) {
513                         goto _ERR_CAMCORDER_AUDIO_COMMAND;
514                 }
515
516                 /* FIXME: consider delay. */
517                 pipe_clock = gst_pipeline_get_clock(GST_PIPELINE(pipeline));
518                 sc->pipeline_time = gst_clock_get_time(pipe_clock) - gst_element_get_base_time(GST_ELEMENT(pipeline));
519                 break;
520         }
521
522         case _MMCamcorder_CMD_CANCEL:
523                 if (info->b_commiting) {
524                         _mmcam_dbg_warn("now on commiting previous file!!(cmd : %d)", cmd);
525                         return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
526                 }
527
528                 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
529                 if (ret != MM_ERROR_NONE) {
530                         goto _ERR_CAMCORDER_AUDIO_COMMAND;
531                 }
532
533                 if (info->bMuxing) {
534                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
535                 } else {
536                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_AQUE].gst, "empty-buffers", FALSE);
537                 }
538
539                 _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, GST_STATE_NULL);
540
541                 sc->pipeline_time = 0;
542                 sc->pause_time = 0;
543                 sc->isMaxsizePausing = FALSE;
544                 sc->isMaxtimePausing = FALSE;
545
546                 if (info->filename) {
547                         _mmcam_dbg_log("file delete(%s)", info->filename);
548                         unlink(info->filename);
549                         g_free(info->filename);
550                         info->filename = NULL;
551                 }
552                 break;
553
554         case _MMCamcorder_CMD_COMMIT:
555         {
556                 int count = 0;
557
558                 _mmcam_dbg_log("_MMCamcorder_CMD_COMMIT");
559
560                 if (info->b_commiting) {
561                         _mmcam_dbg_warn("now on commiting previous file!!(cmd : %d)", cmd);
562                         return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
563                 } else {
564                         _mmcam_dbg_log("_MMCamcorder_CMD_COMMIT : start");
565                         info->b_commiting = TRUE;
566                 }
567
568                 for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
569                         if (info->filesize > 0) {
570                                 break;
571                         } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
572                                 _mmcam_dbg_err("Commit fail, waited 200 ms, but file size is %lld", info->filesize);
573                                         info->b_commiting = FALSE;
574                                 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
575                         } else {
576                                 _mmcam_dbg_warn("Waiting for enough audio frame, re-count[%d], file size is %lld",
577                                                  count, info->filesize);
578                         }
579                         usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
580                 }
581
582                 if (audioSrc) {
583                         ret = gst_element_send_event(audioSrc, gst_event_new_eos());
584                         /* for pause -> commit case */
585                         if (_mmcamcorder_get_state((MMHandleType)hcamcorder) == MM_CAMCORDER_STATE_PAUSED) {
586                                 ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
587                                 if (ret != MM_ERROR_NONE) {
588                                         info->b_commiting = FALSE;
589                                         goto _ERR_CAMCORDER_AUDIO_COMMAND;
590                                 }
591                         }
592                 }
593
594                 /* wait until finishing EOS */
595                 _mmcam_dbg_log("Start to wait EOS");
596                 if ((ret =_mmcamcorder_get_eos_message(handle)) != MM_ERROR_NONE) {
597                         info->b_commiting = FALSE;
598                         goto _ERR_CAMCORDER_AUDIO_COMMAND;
599                 }
600                 break;
601         }
602
603         case _MMCamcorder_CMD_PREVIEW_START:
604                 //MM_CAMCORDER_START_CHANGE_STATE;
605                 break;
606
607         case _MMCamcorder_CMD_PREVIEW_STOP:
608                 //MM_CAMCORDER_STOP_CHANGE_STATE;
609                 //void
610                 break;
611
612         default:
613                 ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
614                 break;
615         }
616
617 _ERR_CAMCORDER_AUDIO_COMMAND:
618         return ret;
619 }
620
621 int _mmcamcorder_audio_handle_eos(MMHandleType handle)
622 {
623         int err = MM_ERROR_NONE;
624         mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
625         _MMCamcorderSubContext *sc = NULL;
626         _MMCamcorderAudioInfo *info = NULL;
627         GstElement *pipeline = NULL;
628         _MMCamcorderMsgItem msg;
629         MMCamRecordingReport * report;
630
631         mmf_return_val_if_fail(hcamcorder, FALSE);
632         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
633
634         mmf_return_val_if_fail(sc, FALSE);
635         mmf_return_val_if_fail(sc->info_audio, FALSE);
636
637         _mmcam_dbg_err("");
638
639         info = sc->info_audio;
640
641         pipeline = sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst;
642
643         err = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
644         if (err != MM_ERROR_NONE) {
645                 _mmcam_dbg_warn("Failed:_MMCamcorder_CMD_COMMIT:GST_STATE_READY. err[%x]", err);
646         }
647
648         /* Send recording report message to application */
649         msg.id = MM_MESSAGE_CAMCORDER_AUDIO_CAPTURED;
650         report = (MMCamRecordingReport*) malloc(sizeof(MMCamRecordingReport));
651         if (!report) {
652                 _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
653                 return FALSE;
654         }
655
656         report->recording_filename = strdup(info->filename);
657         msg.param.data= report;
658
659         _mmcamcroder_send_message(handle, &msg);
660
661         if (info->bMuxing) {
662                 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
663         } else {
664                 MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_AQUE].gst, "empty-buffers", FALSE);
665         }
666
667         _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_NULL);
668
669         sc->pipeline_time = 0;
670         sc->pause_time = 0;
671         sc->isMaxsizePausing = FALSE;
672         sc->isMaxtimePausing = FALSE;
673
674         g_free(info->filename);
675         info->filename = NULL;
676
677         _mmcam_dbg_err("_MMCamcorder_CMD_COMMIT : end");
678
679         info->b_commiting = FALSE;
680
681         return TRUE;
682 }
683
684
685 static float
686 __mmcamcorder_get_decibel(unsigned char* raw, int size, MMCamcorderAudioFormat format)
687 {
688         #define MAX_AMPLITUDE_MEAN_16BIT (23170.115738161934)
689         #define MAX_AMPLITUDE_MEAN_08BIT (89.803909382810)
690         #define DEFAULT_DECIBEL          (-80.0)
691
692         int i = 0;
693         int depthByte = 0;
694         int count = 0;
695
696         short* pcm16 = 0;
697         char* pcm8 = 0;
698
699         float db = DEFAULT_DECIBEL;
700         float rms = 0.0;
701         unsigned long long square_sum = 0;
702
703         if (format == MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE)
704                 depthByte = 2;
705         else            //MM_CAMCORDER_AUDIO_FORMAT_PCM_U8
706                 depthByte = 1;
707
708         for( ; i < size ; i += (depthByte<<1) )
709         {
710                 if (depthByte == 1)
711                 {
712                         pcm8 = (char *)(raw + i);
713                         square_sum += (*pcm8)*(*pcm8);
714                 }
715                 else            //2byte
716                 {
717                         pcm16 = (short*)(raw + i);
718                         square_sum += (*pcm16)*(*pcm16);
719                 }
720
721                 count++;
722         }
723
724         if (count > 0) {
725                 rms = sqrt( square_sum/count );
726                 if (depthByte == 1) {
727                         db = 20 * log10( rms/MAX_AMPLITUDE_MEAN_08BIT );
728                 } else {
729                         db = 20 * log10( rms/MAX_AMPLITUDE_MEAN_16BIT );
730                 }
731         }
732
733         /*
734         _mmcam_dbg_log("size[%d],depthByte[%d],count[%d],rms[%f],db[%f]",
735                        size, depthByte, count, rms, db);
736         */
737
738         return db;
739 }
740
741
742 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
743 {
744         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
745         double volume = 0.0;
746         int format = 0;
747         int channel = 0;
748         float curdcb = 0.0;
749         _MMCamcorderMsgItem msg;
750         int err = MM_ERROR_UNKNOWN;
751         char *err_name = NULL;
752         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
753         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
754
755         mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK);
756
757         /* Set volume to audio input */
758         err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name,
759                                                                         MMCAM_AUDIO_VOLUME, &volume,
760                                                                         MMCAM_AUDIO_FORMAT, &format,
761                                                                         MMCAM_AUDIO_CHANNEL, &channel,
762                                                                         NULL);
763         if (err < 0) {
764                 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
765                 SAFE_FREE(err_name);
766                 return err;
767         }
768
769         gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE);
770
771         if(volume == 0){
772                 memset(mapinfo.data, 0, mapinfo.size);
773         }
774
775         /* Get current volume level of real input stream */
776         curdcb = __mmcamcorder_get_decibel(mapinfo.data, mapinfo.size, format);
777
778         msg.id = MM_MESSAGE_CAMCORDER_CURRENT_VOLUME;
779         msg.param.rec_volume_dB = curdcb;
780         _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
781
782         /* CALL audio stream callback */
783         if ((hcamcorder->astream_cb) && buffer && mapinfo.data && mapinfo.size > 0)
784         {
785                 MMCamcorderAudioStreamDataType stream;
786
787                 if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE)
788                 {
789                         _mmcam_dbg_warn("Not ready for stream callback");
790                         gst_buffer_unmap(buffer, &mapinfo);
791                         return GST_PAD_PROBE_OK;
792                 }
793
794                 /*
795                 _mmcam_dbg_log("Call audio steramCb, data[%p], format[%d], channel[%d], length[%d], volume_dB[%f]",
796                                GST_BUFFER_DATA(buffer), format, channel, GST_BUFFER_SIZE(buffer), curdcb);
797                 */
798
799                 stream.data = (void *)mapinfo.data;
800                 stream.format = format;
801                 stream.channel = channel;
802                 stream.length = mapinfo.size;
803                 stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000);      //nano -> msecond
804                 stream.volume_dB = curdcb;
805
806                 _MMCAMCORDER_LOCK_ASTREAM_CALLBACK( hcamcorder );
807
808                 if(hcamcorder->astream_cb)
809                 {
810                         hcamcorder->astream_cb(&stream, hcamcorder->astream_cb_param);
811                 }
812
813                 _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK( hcamcorder );
814         }
815
816         gst_buffer_unmap(buffer, &mapinfo);
817         return GST_PAD_PROBE_OK;
818 }
819
820
821 static void
822 __mmcamcorder_audiorec_pad_added_cb(GstElement *element, GstPad *pad,  MMHandleType handle)
823 {
824         mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
825
826         _mmcam_dbg_log("ENTER(%s)", GST_PAD_NAME(pad));
827         //FIXME : the name of audio sink pad of wavparse, oggmux doesn't have 'audio'. How could I handle the name?
828         if((strstr(GST_PAD_NAME(pad), "audio")) || (strstr(GST_PAD_NAME(pad), "sink")))
829         {
830                 MMCAMCORDER_ADD_BUFFER_PROBE(pad, _MMCAMCORDER_HANDLER_AUDIOREC,
831                         __mmcamcorder_audio_dataprobe_record, hcamcorder);
832         }
833         else
834         {
835                 _mmcam_dbg_warn("Unknow pad is added, check it : [%s]", GST_PAD_NAME(pad));
836         }
837
838         return;
839 }
840
841
842 static GstPadProbeReturn __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
843 {
844         static int count = 0;
845         guint64 rec_pipe_time = 0;
846         guint64 free_space = 0;
847         guint64 buffer_size = 0;
848         guint64 trailer_size = 0;
849         char *filename = NULL;
850         unsigned long long remained_time = 0;
851
852         _MMCamcorderSubContext *sc = NULL;
853         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
854         _MMCamcorderAudioInfo *audioinfo = NULL;
855         _MMCamcorderMsgItem msg;
856         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
857
858         mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP);
859         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
860
861         sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
862         mmf_return_val_if_fail(sc && sc->info_audio, GST_PAD_PROBE_DROP);
863         audioinfo = sc->info_audio;
864
865         if (sc->isMaxtimePausing || sc->isMaxsizePausing) {
866                 _mmcam_dbg_warn("isMaxtimePausing[%d],isMaxsizePausing[%d]",
867                                 sc->isMaxtimePausing, sc->isMaxsizePausing);
868                 return GST_PAD_PROBE_DROP;
869         }
870
871         buffer_size = gst_buffer_get_size(buffer);
872
873         if (audioinfo->filesize == 0) {
874                 if (audioinfo->fileformat == MM_FILE_FORMAT_WAV) {
875                         audioinfo->filesize += 44; /* wave header size */
876                 } else if (audioinfo->fileformat == MM_FILE_FORMAT_AMR) {
877                         audioinfo->filesize += 6; /* amr header size */
878                 }
879
880                 audioinfo->filesize += buffer_size;
881                 return GST_PAD_PROBE_OK;
882         }
883
884         if (sc->ferror_send) {
885                 _mmcam_dbg_warn("file write error, drop frames");
886                 return GST_PAD_PROBE_DROP;
887         }
888
889         /* get trailer size */
890         if (audioinfo->fileformat == MM_FILE_FORMAT_3GP ||
891                         audioinfo->fileformat == MM_FILE_FORMAT_MP4 ||
892                         audioinfo->fileformat == MM_FILE_FORMAT_AAC) {
893                 MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
894                 /*_mmcam_dbg_log("trailer_size %d", trailer_size);*/
895         } else {
896                 trailer_size = 0; /* no trailer */
897         }
898
899         filename = audioinfo->filename;
900
901         /* to minimizing free space check overhead */
902         count = count % _MMCAMCORDER_FREE_SPACE_CHECK_INTERVAL;
903         if (count++ == 0) {
904                 gint free_space_ret = _mmcamcorder_get_freespace(filename, &free_space);
905
906                 /*_mmcam_dbg_log("check free space for recording");*/
907
908                 switch (free_space_ret) {
909                 case -2: /* file not exist */
910                 case -1: /* failed to get free space */
911                         _mmcam_dbg_err("Error occured. [%d]", free_space_ret);
912                         if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
913                                 sc->ferror_send = TRUE;
914                                 msg.id = MM_MESSAGE_CAMCORDER_ERROR;
915                                 if (free_space_ret == -2) {
916                                         msg.param.code = MM_ERROR_FILE_NOT_FOUND;
917                                 } else {
918                                         msg.param.code = MM_ERROR_FILE_READ;
919                                 }
920                                 _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
921                         } else {
922                                 sc->ferror_count++;
923                         }
924
925                         return GST_PAD_PROBE_DROP; /* skip this buffer */
926
927                 default: /* succeeded to get free space */
928                         /* check free space for recording */
929                         if (free_space < (guint64)(_MMCAMCORDER_AUDIO_MINIMUM_SPACE + buffer_size + trailer_size)) {
930                                 _mmcam_dbg_warn("No more space for recording!!!");
931                                 _mmcam_dbg_warn("Free Space : [%" G_GUINT64_FORMAT "], file size : [%" G_GUINT64_FORMAT "]",
932                                                 free_space, audioinfo->filesize);
933
934                                 if (audioinfo->bMuxing) {
935                                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
936                                 } else {
937                                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_AQUE].gst, "empty-buffers", TRUE);
938                                 }
939
940                                 sc->isMaxsizePausing = TRUE;
941                                 msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
942                                 _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
943
944                                 return GST_PAD_PROBE_DROP; /* skip this buffer */
945                         }
946                         break;
947                 }
948         }
949
950         if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) {
951                 _mmcam_dbg_err("Buffer timestamp is invalid, check it");
952                 return GST_PAD_PROBE_DROP;
953         }
954
955         rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer));
956
957         /* calculate remained time can be recorded */
958         if (audioinfo->max_time > 0 && audioinfo->max_time < (remained_time + rec_pipe_time)) {
959                 remained_time = audioinfo->max_time - rec_pipe_time;
960         } else if (audioinfo->max_size > 0) {
961                 long double max_size = (long double)audioinfo->max_size;
962                 long double current_size = (long double)(audioinfo->filesize + buffer_size + trailer_size);
963
964                 remained_time = (unsigned long long)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time;
965         }
966
967         /*_mmcam_dbg_log("remained time : %u", remained_time);*/
968
969         /* check max size of recorded file */
970         if (audioinfo->max_size > 0 &&
971                         audioinfo->max_size < audioinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE) {
972                 _mmcam_dbg_warn("Max size!!! Recording is paused.");
973                 _mmcam_dbg_warn("Max [%" G_GUINT64_FORMAT "], file [%" G_GUINT64_FORMAT "], trailer : [%" G_GUINT64_FORMAT "]", \
974                                 audioinfo->max_size, audioinfo->filesize, trailer_size);
975
976                 /* just same as pause status. After blocking two queue, this function will not call again. */
977                 if (audioinfo->bMuxing) {
978                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
979                 } else {
980                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_AQUE].gst, "empty-buffers", TRUE);
981                 }
982
983                 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
984                 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
985                 msg.param.recording_status.filesize = (unsigned long long)((audioinfo->filesize + trailer_size) >> 10);
986                 msg.param.recording_status.remained_time = 0;
987                 _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
988
989                 _mmcam_dbg_warn("Last filesize sent by message : %d", audioinfo->filesize + trailer_size);
990
991                 sc->isMaxsizePausing = TRUE;
992                 msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE;
993                 _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
994
995                 /* skip this buffer */
996                 return GST_PAD_PROBE_DROP;
997         }
998
999         /* check recording time limit and send recording status message */
1000         if (audioinfo->max_time > 0 && rec_pipe_time > audioinfo->max_time) {
1001                 _mmcam_dbg_warn("Current time : [%" G_GUINT64_FORMAT "], Maximum time : [%" G_GUINT64_FORMAT "]", \
1002                                 rec_pipe_time, audioinfo->max_time);
1003
1004                 if (audioinfo->bMuxing) {
1005                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1006                 } else {
1007                         MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_AQUE].gst, "empty-buffers", TRUE);
1008                 }
1009
1010                 sc->isMaxtimePausing = TRUE;
1011                 msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
1012                 _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
1013
1014                 /* skip this buffer */
1015                 return GST_PAD_PROBE_DROP;
1016         }
1017
1018         /* send message for recording time and recorded file size */
1019         if (audioinfo->b_commiting == FALSE) {
1020                 audioinfo->filesize += buffer_size;
1021
1022                 msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
1023                 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1024                 msg.param.recording_status.filesize = (unsigned long long)((audioinfo->filesize + trailer_size) >> 10);
1025                 msg.param.recording_status.remained_time = remained_time;
1026                 _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
1027
1028                 return GST_PAD_PROBE_OK;
1029         } else {
1030                 /* skip this buffer if commit process has been started */
1031                 return GST_PAD_PROBE_DROP;
1032         }
1033 }