[libmm-streamrecorder] initial code for new feature of streamrecorder
[platform/core/multimedia/libmm-streamrecorder.git] / src / mm_streamrecorder_gstdispatch.c
1 /*
2  * libmm-streamrecorder
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Hyuntae Kim <ht1211.kim@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 <stdio.h>
26 #include <stdarg.h>
27 #include <sys/vfs.h>                    /* struct statfs */
28
29 #include "mm_streamrecorder_internal.h"
30 #include "mm_streamrecorder_gstdispatch.h"
31 #include "mm_streamrecorder_gstcommon.h"
32 #include "mm_streamrecorder_util.h"
33 #include "mm_streamrecorder_recorder.h"
34
35 /*-----------------------------------------------------------------------
36 |    GLOBAL VARIABLE DEFINITIONS for internal                           |
37 -----------------------------------------------------------------------*/
38
39 #define _MMSTREAMRECORDER_MINIMUM_FRAME              5
40 #define _MMSTREAMRECORDER_FREE_SPACE_CHECK_INTERVAL  5
41 #define _MMSTREAMRECORDER_MINIMUM_SPACE         (512*1024)      /* byte */
42 #define _MMSTREAMRECORDER_MMS_MARGIN_SPACE              (512)   /* byte */
43 #define _MMSTREAMRECORDER_AUDIO_FREE_SPACE_CHECK_INTERVAL  10
44 #define _MMSTREAMRECORDER_AUDIO_MINIMUM_SPACE        (100*1024)
45
46 /*-----------------------------------------------------------------------
47 |    LOCAL VARIABLE DEFINITIONS for internal                            |
48 -----------------------------------------------------------------------*/
49
50 /*---------------------------------------------------------------------------
51 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
52 ---------------------------------------------------------------------------*/
53 /* STATIC INTERNAL FUNCTION */
54
55 /*===========================================================================================
56 |                                                                                                                                                                                       |
57 |  FUNCTION DEFINITIONS                                                                                                                                         |
58 ========================================================================================== */
59 /*---------------------------------------------------------------------------
60 |    GLOBAL FUNCTION DEFINITIONS:                                                                                       |
61 ---------------------------------------------------------------------------*/
62 void _mmstreamrecorder_remove_buffer_probe(MMHandleType handle, _MMStreamRecorderHandlerCategory category)
63 {
64         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
65         GList *list = NULL;
66         MMStreamRecorderHandlerItem *item = NULL;
67
68         mmf_return_if_fail(hstreamrecorder);
69
70         if (!hstreamrecorder->buffer_probes) {
71                 _mmstreamrec_dbg_warn("list for buffer probe is NULL");
72                 return;
73         }
74
75         _mmstreamrec_dbg_log("start - category : 0x%x", category);
76
77         list = hstreamrecorder->buffer_probes;
78         while (list) {
79                 item = list->data;
80                 if (!item) {
81                         _mmstreamrec_dbg_err("Remove buffer probe faild, the item is NULL");
82                         list = g_list_next(list);
83                         continue;
84                 }
85
86                 if (item->category & category) {
87                         if (item->object && GST_IS_PAD(item->object)) {
88                                 _mmstreamrec_dbg_log("Remove buffer probe on [%s:%s] - [ID : %lu], [Category : %x]", GST_DEBUG_PAD_NAME(item->object), item->handler_id, item->category);
89                                 gst_pad_remove_probe(GST_PAD(item->object), item->handler_id);
90                         } else {
91                                 _mmstreamrec_dbg_warn("Remove buffer probe faild, the pad is null or not pad, just remove item from list and free it");
92                         }
93
94                         list = g_list_next(list);
95                         hstreamrecorder->buffer_probes = g_list_remove(hstreamrecorder->buffer_probes, item);
96                         SAFE_FREE(item);
97                 } else {
98                         _mmstreamrec_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
99                         list = g_list_next(list);
100                 }
101         }
102
103         if (category == _MMSTREAMRECORDER_HANDLER_CATEGORY_ALL) {
104                 g_list_free(hstreamrecorder->buffer_probes);
105                 hstreamrecorder->buffer_probes = NULL;
106         }
107
108         _mmstreamrec_dbg_log("done");
109
110         return;
111 }
112
113 void _mmstreamrecorder_remove_event_probe(MMHandleType handle, _MMStreamRecorderHandlerCategory category)
114 {
115         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
116         GList *list = NULL;
117         MMStreamRecorderHandlerItem *item = NULL;
118
119         mmf_return_if_fail(hstreamrecorder);
120
121         if (!hstreamrecorder->event_probes) {
122                 _mmstreamrec_dbg_warn("list for event probe is NULL");
123                 return;
124         }
125
126         _mmstreamrec_dbg_log("start - category : 0x%x", category);
127
128         list = hstreamrecorder->event_probes;
129         while (list) {
130                 item = list->data;
131                 if (!item) {
132                         _mmstreamrec_dbg_err("Remove event probe faild, the item is NULL");
133                         list = g_list_next(list);
134                         continue;
135                 }
136
137                 if (item->category & category) {
138                         if (item->object && GST_IS_PAD(item->object)) {
139                                 _mmstreamrec_dbg_log("Remove event probe on [%s:%s] - [ID : %lu], [Category : %x]", GST_DEBUG_PAD_NAME(item->object), item->handler_id, item->category);
140                                 gst_pad_remove_probe(GST_PAD(item->object), item->handler_id);
141                         } else {
142                                 _mmstreamrec_dbg_warn("Remove event probe faild, the pad is null or not pad, just remove item from list and free it");
143                         }
144
145                         list = g_list_next(list);
146                         hstreamrecorder->event_probes = g_list_remove(hstreamrecorder->event_probes, item);
147                         SAFE_FREE(item);
148                 } else {
149                         _mmstreamrec_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
150                         list = g_list_next(list);
151                 }
152         }
153
154         if (category == _MMSTREAMRECORDER_HANDLER_CATEGORY_ALL) {
155                 g_list_free(hstreamrecorder->event_probes);
156                 hstreamrecorder->event_probes = NULL;
157         }
158
159         _mmstreamrec_dbg_log("done");
160
161         return;
162 }
163
164 void _mmstreamrecorder_remove_data_probe(MMHandleType handle, _MMStreamRecorderHandlerCategory category)
165 {
166         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
167         GList *list = NULL;
168         MMStreamRecorderHandlerItem *item = NULL;
169
170         mmf_return_if_fail(hstreamrecorder);
171
172         if (!hstreamrecorder->data_probes) {
173                 _mmstreamrec_dbg_warn("list for data probe is NULL");
174                 return;
175         }
176
177         _mmstreamrec_dbg_log("start - category : 0x%x", category);
178
179         list = hstreamrecorder->data_probes;
180         while (list) {
181                 item = list->data;
182                 if (!item) {
183                         _mmstreamrec_dbg_err("Remove data probe faild, the item is NULL");
184                         list = g_list_next(list);
185                         continue;
186                 }
187
188                 if (item->category & category) {
189                         if (item->object && GST_IS_PAD(item->object)) {
190                                 _mmstreamrec_dbg_log("Remove data probe on [%s:%s] - [ID : %lu], [Category : %x]", GST_DEBUG_PAD_NAME(item->object), item->handler_id, item->category);
191                                 gst_pad_remove_probe(GST_PAD(item->object), item->handler_id);
192                         } else {
193                                 _mmstreamrec_dbg_warn("Remove data probe faild, the pad is null or not pad, just remove item from list and free it");
194                         }
195
196                         list = g_list_next(list);
197                         hstreamrecorder->data_probes = g_list_remove(hstreamrecorder->data_probes, item);
198                         SAFE_FREE(item);
199                 } else {
200                         _mmstreamrec_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
201                         list = g_list_next(list);
202                 }
203         }
204
205         if (category == _MMSTREAMRECORDER_HANDLER_CATEGORY_ALL) {
206                 g_list_free(hstreamrecorder->data_probes);
207                 hstreamrecorder->data_probes = NULL;
208         }
209
210         _mmstreamrec_dbg_log("done");
211
212         return;
213 }
214
215 void _mmstreamrecorder_disconnect_signal(MMHandleType handle, _MMStreamRecorderHandlerCategory category)
216 {
217         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
218         GList *list = NULL;
219         MMStreamRecorderHandlerItem *item = NULL;
220
221         mmf_return_if_fail(hstreamrecorder);
222
223         if (!hstreamrecorder->signals) {
224                 _mmstreamrec_dbg_warn("list for signal is NULL");
225                 return;
226         }
227
228         _mmstreamrec_dbg_log("start - category : 0x%x", category);
229
230         list = hstreamrecorder->signals;
231         while (list) {
232                 item = list->data;
233                 if (!item) {
234                         _mmstreamrec_dbg_err("Fail to Disconnecting signal, the item is NULL");
235                         list = g_list_next(list);
236                         continue;
237                 }
238
239                 if (item->category & category) {
240                         if (item->object && GST_IS_ELEMENT(item->object)) {
241                                 if (g_signal_handler_is_connected(item->object, item->handler_id)) {
242                                         _mmstreamrec_dbg_log("Disconnect signal from [%s] : [ID : %lu], [Category : %x]", GST_OBJECT_NAME(item->object), item->handler_id, item->category);
243                                         g_signal_handler_disconnect(item->object, item->handler_id);
244                                 } else {
245                                         _mmstreamrec_dbg_warn("Signal was not connected, cannot disconnect it :  [%s]  [ID : %lu], [Category : %x]", GST_OBJECT_NAME(item->object), item->handler_id, item->category);
246                                 }
247                         } else {
248                                 _mmstreamrec_dbg_err("Fail to Disconnecting signal, the element is null or not element, just remove item from list and free it");
249                         }
250
251                         list = g_list_next(list);
252                         hstreamrecorder->signals = g_list_remove(hstreamrecorder->signals, item);
253                         SAFE_FREE(item);
254                 } else {
255                         _mmstreamrec_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
256                         list = g_list_next(list);
257                 }
258         }
259
260         if (category == _MMSTREAMRECORDER_HANDLER_CATEGORY_ALL) {
261                 g_list_free(hstreamrecorder->signals);
262                 hstreamrecorder->signals = NULL;
263         }
264
265         _mmstreamrec_dbg_log("done");
266
267         return;
268 }
269
270 void _mmstreamrecorder_element_release_noti(gpointer data, GObject *where_the_object_was)
271 {
272         int i = 0;
273         _MMStreamRecorderSubContext *sc = (_MMStreamRecorderSubContext *) data;
274
275         mmf_return_if_fail(sc);
276
277         mmf_return_if_fail(sc->encode_element);
278
279         for (i = 0; i < _MMSTREAMRECORDER_ENCODE_PIPELINE_ELEMENT_NUM; i++) {
280                 if (sc->encode_element[i].gst && (G_OBJECT(sc->encode_element[i].gst) == where_the_object_was)) {
281                         _mmstreamrec_dbg_warn("The encode element[%d][%p] is finalized", sc->encode_element[i].id, sc->encode_element[i].gst);
282                         sc->encode_element[i].gst = NULL;
283                         sc->encode_element[i].id = _MMSTREAMRECORDER_ENCODE_NONE;
284                         return;
285                 }
286         }
287
288         _mmstreamrec_dbg_warn("there is no matching element %p", where_the_object_was);
289
290         return;
291 }
292
293 gboolean _mmstreamrecorder_msg_callback(void *data)
294 {
295         _MMStreamRecorderMsgItem *item = (_MMStreamRecorderMsgItem *) data;
296         mmf_streamrecorder_t *hstreamrecorder = NULL;
297         mmf_return_val_if_fail(item, FALSE);
298
299         hstreamrecorder = MMF_STREAMRECORDER(item->handle);
300         mmf_return_val_if_fail(hstreamrecorder, FALSE);
301
302         /* _mmstreamrec_dbg_log("msg id:%x, msg_cb:%p, msg_data:%p, item:%p", item->id, hstreamrecorder->msg_cb, hstreamrecorder->msg_data, item); */
303         _MMSTREAMRECORDER_LOCK_MESSAGE_CALLBACK(hstreamrecorder);
304
305         if ((hstreamrecorder) && (hstreamrecorder->msg_cb))
306                 hstreamrecorder->msg_cb(item->id, (MMMessageParamType *) (&(item->param)), hstreamrecorder->msg_cb_param);
307
308         _MMSTREAMRECORDER_UNLOCK_MESSAGE_CALLBACK(hstreamrecorder);
309
310         _MMSTREAMRECORDER_LOCK((MMHandleType) hstreamrecorder);
311         if (hstreamrecorder->msg_data)
312                 hstreamrecorder->msg_data = g_list_remove(hstreamrecorder->msg_data, item);
313
314         free(item);
315         item = NULL;
316         _MMSTREAMRECORDER_UNLOCK((MMHandleType) hstreamrecorder);
317         /* For not being called again */
318         return FALSE;
319 }
320
321 void _mmstreamrecorder_remove_all_handlers(MMHandleType handle, _MMStreamRecorderHandlerCategory category)
322 {
323         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
324
325         _mmstreamrec_dbg_log("ENTER");
326
327         if (hstreamrecorder->signals)
328                 _mmstreamrecorder_disconnect_signal((MMHandleType) hstreamrecorder, category);
329         if (hstreamrecorder->data_probes)
330                 _mmstreamrecorder_remove_data_probe((MMHandleType) hstreamrecorder, category);
331         if (hstreamrecorder->event_probes)
332                 _mmstreamrecorder_remove_event_probe((MMHandleType) hstreamrecorder, category);
333         if (hstreamrecorder->buffer_probes)
334                 _mmstreamrecorder_remove_buffer_probe((MMHandleType) hstreamrecorder, category);
335
336         _mmstreamrec_dbg_log("LEAVE");
337 }
338
339 gboolean _mmstreamrecorder_send_message(MMHandleType handle, _MMStreamRecorderMsgItem *data)
340 {
341         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
342         _MMStreamRecorderMsgItem *item = NULL;
343
344         mmf_return_val_if_fail(hstreamrecorder, FALSE);
345         mmf_return_val_if_fail(data, FALSE);
346
347         /* _mmstreamrec_dbg_err("ENTER"); */
348
349         /* _mmstreamrec_dbg_err("data->id =  %x",data->id); */
350
351         switch (data->id) {
352         case MM_MESSAGE_STREAMRECORDER_STATE_CHANGED:
353                 data->param.union_type = MM_MSG_UNION_STATE;
354                 break;
355         case MM_MESSAGE_STREAMRECORDER_RECORDING_STATUS:
356                 data->param.union_type = MM_MSG_UNION_RECORDING_STATUS;
357                 break;
358         case MM_MESSAGE_STREAMRECORDER_CONSUME_COMPLETE:        /* 0x801 */
359                 data->param.union_type = MM_MSG_UNION_CONSUME_RECORDER_BUFFER;
360                 break;
361         case MM_MESSAGE_STREAMRECORDER_TIME_LIMIT:
362         case MM_MESSAGE_STREAMRECORDER_MAX_SIZE:
363         case MM_MESSAGE_STREAMRECORDER_NO_FREE_SPACE:
364         case MM_MESSAGE_STREAMRECORDER_ERROR:
365         case MM_MESSAGE_STREAMRECORDER_VIDEO_CAPTURED:
366         case MM_MESSAGE_STREAMRECORDER_AUDIO_CAPTURED:
367         case MM_MESSAGE_READY_TO_RESUME:
368         default:
369                 data->param.union_type = MM_MSG_UNION_CODE;
370                 break;
371         }
372
373         item = g_malloc(sizeof(_MMStreamRecorderMsgItem));
374         if (!item)
375                 return FALSE;
376         memcpy(item, data, sizeof(_MMStreamRecorderMsgItem));
377         item->handle = handle;
378
379         _MMSTREAMRECORDER_LOCK(handle);
380         hstreamrecorder->msg_data = g_list_append(hstreamrecorder->msg_data, item);
381         /* _mmstreamrec_dbg_log("item[%p]", item); */
382
383         /* Use DEFAULT priority */
384         g_idle_add_full(G_PRIORITY_DEFAULT, _mmstreamrecorder_msg_callback, item, NULL);
385
386         _MMSTREAMRECORDER_UNLOCK(handle);
387
388         return TRUE;
389 }
390
391 gboolean _mmstreamrecorder_remove_message_all(MMHandleType handle)
392 {
393         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
394         _MMStreamRecorderMsgItem *item = NULL;
395         gboolean ret = TRUE;
396         GList *list = NULL;
397
398         mmf_return_val_if_fail(hstreamrecorder, FALSE);
399
400         _MMSTREAMRECORDER_LOCK(handle);
401
402         if (hstreamrecorder->msg_data) {
403                 list = hstreamrecorder->msg_data;
404
405                 while (list) {
406                         item = list->data;
407                         list = g_list_next(list);
408
409                         if (item) {
410                                 ret = g_idle_remove_by_data(item);
411                                 _mmstreamrec_dbg_log("Remove item[%p]. ret[%d]", item, ret);
412
413                                 hstreamrecorder->msg_data = g_list_remove(hstreamrecorder->msg_data, item);
414
415                                 SAFE_FREE(item);
416                         }
417                 }
418
419                 g_list_free(hstreamrecorder->msg_data);
420                 hstreamrecorder->msg_data = NULL;
421         }
422
423         /* remove idle function for playing capture sound */
424         do {
425                 ret = g_idle_remove_by_data(hstreamrecorder);
426                 _mmstreamrec_dbg_log("remove idle function for playing capture sound. ret[%d]", ret);
427         } while (ret);
428
429         _MMSTREAMRECORDER_UNLOCK(handle);
430
431         return ret;
432 }
433
434 gboolean _mmstreamrecorder_handle_gst_error(MMHandleType handle, GstMessage *message, GError *error)
435 {
436         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
437         /* _MMstreamrecorderMsgItem msg; */
438         gchar *msg_src_element;
439         _MMStreamRecorderSubContext *sc = NULL;
440
441         return_val_if_fail(hstreamrecorder, FALSE);
442         return_val_if_fail(error, FALSE);
443         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
444         mmf_return_val_if_fail(sc, FALSE);
445
446         _mmstreamrec_dbg_log("");
447
448         /* filtering filesink related errors */
449         if ((error->code == GST_RESOURCE_ERROR_WRITE || error->code == GST_RESOURCE_ERROR_SEEK)) {
450                 if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
451                         sc->ferror_send = TRUE;
452                         /* msg.param.code = __mmstreamrecorder_gst_handle_resource_error(handle, error->code, message); */
453                 } else {
454                         sc->ferror_count++;
455                         _mmstreamrec_dbg_warn("Skip error");
456                         return TRUE;
457                 }
458         }
459
460         if (error->domain == GST_CORE_ERROR) {
461                 /* msg.param.code = __mmstreamrecorder_gst_handle_core_error(handle, error->code, message); */
462         } else if (error->domain == GST_LIBRARY_ERROR) {
463                 /* msg.param.code = __mmstreamrecorder_gst_handle_library_error(handle, error->code, message); */
464         } else if (error->domain == GST_RESOURCE_ERROR) {
465                 /* msg.param.code = __mmstreamrecorder_gst_handle_resource_error(handle, error->code, message); */
466         } else if (error->domain == GST_STREAM_ERROR) {
467                 /* msg.param.code = __mmstreamrecorder_gst_handle_stream_error(handle, error->code, message); */
468         } else {
469                 _mmstreamrec_dbg_warn("This error domain is not defined.");
470
471                 /* we treat system error as an internal error */
472                 /* msg.param.code = MM_ERROR_streamrecorder_INTERNAL; */
473         }
474
475         if (message->src) {
476                 msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
477 /*              _mmstreamrec_dbg_err("-Msg src : [%s] Domain : [%s]   Error : [%s]  Code : [%d] is tranlated to error code : [0x%x]",
478                                                                 msg_src_element, g_quark_to_string (error->domain), error->message, error->code, msg.param.code); */
479         } else {
480 /*              _mmstreamrec_dbg_err("Domain : [%s]   Error : [%s]  Code : [%d] is tranlated to error code : [0x%x]",
481                                                                 g_quark_to_string (error->domain), error->message, error->code, msg.param.code); */
482         }
483
484 #ifdef _MMSTREAMRECORDER_SKIP_GST_FLOW_ERROR
485         /* Check whether send this error to application */
486 /*      if (msg.param.code == MM_ERROR_streamrecorder_GST_FLOW_ERROR) {
487                 _mmstreamrec_dbg_log("We got the error. But skip it.");
488                 return TRUE;
489         } */
490 #endif                                                  /* _MMstreamrecorder_SKIP_GST_FLOW_ERROR */
491
492         /* post error to application */
493         sc->error_occurs = TRUE;
494 /*      msg.id = MM_MESSAGE_streamrecorder_ERROR;
495         _mmstreamrecorder_send_message(handle, &msg); */
496
497         return TRUE;
498 }
499
500 gint _mmstreamrecorder_gst_handle_core_error(MMHandleType handle, int code, GstMessage *message)
501 {
502         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
503         _MMStreamRecorderSubContext *sc = NULL;
504         GstElement *element = NULL;
505
506         _mmstreamrec_dbg_log("");
507
508         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
509
510         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
511         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
512
513         /* Specific plugin - video encoder plugin */
514         element = GST_ELEMENT_CAST(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst);
515
516         if (GST_ELEMENT_CAST(message->src) == element) {
517                 if (code == GST_CORE_ERROR_NEGOTIATION)
518                         return MM_ERROR_STREAMRECORDER_GST_NEGOTIATION;
519                 else
520                         return MM_ERROR_STREAMRECORDER_ENCODER;
521         }
522
523         /* General */
524         switch (code) {
525         case GST_CORE_ERROR_STATE_CHANGE:
526                 return MM_ERROR_STREAMRECORDER_GST_STATECHANGE;
527         case GST_CORE_ERROR_NEGOTIATION:
528                 return MM_ERROR_STREAMRECORDER_GST_NEGOTIATION;
529         case GST_CORE_ERROR_MISSING_PLUGIN:
530         case GST_CORE_ERROR_SEEK:
531         case GST_CORE_ERROR_NOT_IMPLEMENTED:
532         case GST_CORE_ERROR_FAILED:
533         case GST_CORE_ERROR_TOO_LAZY:
534         case GST_CORE_ERROR_PAD:
535         case GST_CORE_ERROR_THREAD:
536         case GST_CORE_ERROR_EVENT:
537         case GST_CORE_ERROR_CAPS:
538         case GST_CORE_ERROR_TAG:
539         case GST_CORE_ERROR_CLOCK:
540         case GST_CORE_ERROR_DISABLED:
541         default:
542                 return MM_ERROR_STREAMRECORDER_GST_CORE;
543                 break;
544         }
545 }
546
547 gint _mmstreamrecorder_gst_handle_library_error(MMHandleType handle, int code, GstMessage *message)
548 {
549         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
550         return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
551
552         _mmstreamrec_dbg_log("");
553
554         /* Specific plugin - NONE */
555
556         /* General */
557         switch (code) {
558         case GST_LIBRARY_ERROR_FAILED:
559         case GST_LIBRARY_ERROR_TOO_LAZY:
560         case GST_LIBRARY_ERROR_INIT:
561         case GST_LIBRARY_ERROR_SHUTDOWN:
562         case GST_LIBRARY_ERROR_SETTINGS:
563         case GST_LIBRARY_ERROR_ENCODE:
564         default:
565                 _mmstreamrec_dbg_err("Library error(%d)", code);
566                 return MM_ERROR_STREAMRECORDER_GST_LIBRARY;
567         }
568 }
569
570 gint _mmstreamrecorder_gst_handle_resource_error(MMHandleType handle, int code, GstMessage *message)
571 {
572         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
573         _MMStreamRecorderSubContext *sc = NULL;
574         GstElement *element = NULL;
575
576         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
577
578         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
579         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
580
581         _mmstreamrec_dbg_log("");
582
583         /* Specific plugin */
584
585         /* encodebin */
586         element = GST_ELEMENT_CAST(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst);
587         if (GST_ELEMENT_CAST(message->src) == element) {
588                 if (code == GST_RESOURCE_ERROR_FAILED) {
589                         _mmstreamrec_dbg_err("Encoder [Resource error]");
590                         return MM_ERROR_STREAMRECORDER_ENCODER_BUFFER;
591                 } else {
592                         _mmstreamrec_dbg_err("Encoder [General(%d)]", code);
593                         return MM_ERROR_STREAMRECORDER_ENCODER;
594                 }
595         }
596
597         /* General */
598         switch (code) {
599         case GST_RESOURCE_ERROR_WRITE:
600                 _mmstreamrec_dbg_err("File write error");
601                 return MM_ERROR_FILE_WRITE;
602         case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
603                 _mmstreamrec_dbg_err("No left space");
604                 return MM_MESSAGE_STREAMRECORDER_NO_FREE_SPACE;
605         case GST_RESOURCE_ERROR_OPEN_WRITE:
606                 _mmstreamrec_dbg_err("Out of storage");
607                 return MM_ERROR_OUT_OF_STORAGE;
608         case GST_RESOURCE_ERROR_SEEK:
609                 _mmstreamrec_dbg_err("File read(seek)");
610                 return MM_ERROR_FILE_READ;
611         case GST_RESOURCE_ERROR_NOT_FOUND:
612         case GST_RESOURCE_ERROR_FAILED:
613         case GST_RESOURCE_ERROR_TOO_LAZY:
614         case GST_RESOURCE_ERROR_BUSY:
615         case GST_RESOURCE_ERROR_OPEN_READ:
616         case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
617         case GST_RESOURCE_ERROR_CLOSE:
618         case GST_RESOURCE_ERROR_READ:
619         case GST_RESOURCE_ERROR_SYNC:
620         case GST_RESOURCE_ERROR_SETTINGS:
621         default:
622                 _mmstreamrec_dbg_err("Resource error(%d)", code);
623                 return MM_ERROR_STREAMRECORDER_GST_RESOURCE;
624         }
625 }
626
627 gint _mmstreamrecorder_gst_handle_stream_error(MMHandleType handle, int code, GstMessage *message)
628 {
629         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
630         _MMStreamRecorderSubContext *sc = NULL;
631         GstElement *element = NULL;
632
633         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
634
635         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
636         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
637
638         _mmstreamrec_dbg_log("");
639
640         /* Specific plugin */
641         /* video encoder */
642         element = GST_ELEMENT_CAST(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst);
643         if (GST_ELEMENT_CAST(message->src) == element) {
644                 switch (code) {
645                 case GST_STREAM_ERROR_WRONG_TYPE:
646                         _mmstreamrec_dbg_err("Video encoder [wrong stream type]");
647                         return MM_ERROR_STREAMRECORDER_ENCODER_WRONG_TYPE;
648                 case GST_STREAM_ERROR_ENCODE:
649                         _mmstreamrec_dbg_err("Video encoder [encode error]");
650                         return MM_ERROR_STREAMRECORDER_ENCODER_WORKING;
651                 case GST_STREAM_ERROR_FAILED:
652                         _mmstreamrec_dbg_err("Video encoder [stream failed]");
653                         return MM_ERROR_STREAMRECORDER_ENCODER_WORKING;
654                 default:
655                         _mmstreamrec_dbg_err("Video encoder [General(%d)]", code);
656                         return MM_ERROR_STREAMRECORDER_ENCODER;
657                 }
658         }
659
660         /* General plugin */
661         switch (code) {
662         case GST_STREAM_ERROR_FORMAT:
663                 _mmstreamrec_dbg_err("General [negotiation error(%d)]", code);
664                 return MM_ERROR_STREAMRECORDER_GST_NEGOTIATION;
665         case GST_STREAM_ERROR_FAILED:
666                 _mmstreamrec_dbg_err("General [flow error(%d)]", code);
667                 return MM_ERROR_STREAMRECORDER_GST_FLOW_ERROR;
668         case GST_STREAM_ERROR_TYPE_NOT_FOUND:
669         case GST_STREAM_ERROR_DECODE:
670         case GST_STREAM_ERROR_CODEC_NOT_FOUND:
671         case GST_STREAM_ERROR_NOT_IMPLEMENTED:
672         case GST_STREAM_ERROR_TOO_LAZY:
673         case GST_STREAM_ERROR_ENCODE:
674         case GST_STREAM_ERROR_DEMUX:
675         case GST_STREAM_ERROR_MUX:
676         case GST_STREAM_ERROR_DECRYPT:
677         case GST_STREAM_ERROR_DECRYPT_NOKEY:
678         case GST_STREAM_ERROR_WRONG_TYPE:
679         default:
680                 _mmstreamrec_dbg_err("General [error(%d)]", code);
681                 return MM_ERROR_STREAMRECORDER_GST_STREAM;
682         }
683 }
684
685 gboolean _mmstreamrecorder_handle_gst_warning(MMHandleType handle, GstMessage *message, GError *error)
686 {
687         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
688         gchar *debug = NULL;
689         GError *err = NULL;
690
691         return_val_if_fail(hstreamrecorder, FALSE);
692         return_val_if_fail(error, FALSE);
693
694         _mmstreamrec_dbg_log("");
695
696         gst_message_parse_warning(message, &err, &debug);
697
698         if (error->domain == GST_CORE_ERROR) {
699                 _mmstreamrec_dbg_warn("GST warning: GST_CORE domain");
700         } else if (error->domain == GST_LIBRARY_ERROR) {
701                 _mmstreamrec_dbg_warn("GST warning: GST_LIBRARY domain");
702         } else if (error->domain == GST_RESOURCE_ERROR) {
703                 _mmstreamrec_dbg_warn("GST warning: GST_RESOURCE domain");
704                 /* _mmstreamrecorder_gst_handle_resource_warning(handle, message, error); */
705         } else if (error->domain == GST_STREAM_ERROR) {
706                 _mmstreamrec_dbg_warn("GST warning: GST_STREAM domain");
707         } else {
708                 _mmstreamrec_dbg_warn("This error domain(%d) is not defined.", error->domain);
709         }
710
711         if (err != NULL) {
712                 g_error_free(err);
713                 err = NULL;
714         }
715         if (debug != NULL) {
716                 _mmstreamrec_dbg_err("Debug: %s", debug);
717                 g_free(debug);
718                 debug = NULL;
719         }
720
721         return TRUE;
722 }
723
724 gboolean _mmstreamrecorder_pipeline_cb_message(GstBus *bus, GstMessage *message, gpointer data)
725 {
726         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(data);
727         /* _MMstreamrecorderMsgItem msg; */
728         _MMStreamRecorderSubContext *sc = NULL;
729
730         mmf_return_val_if_fail(hstreamrecorder, FALSE);
731         mmf_return_val_if_fail(message, FALSE);
732         /* _mmstreamrec_dbg_log("message type=(%d)", GST_MESSAGE_TYPE(message)); */
733
734         switch (GST_MESSAGE_TYPE(message)) {
735         case GST_MESSAGE_UNKNOWN:
736                 _mmstreamrec_dbg_log("GST_MESSAGE_UNKNOWN");
737                 break;
738         case GST_MESSAGE_EOS:
739                 {
740                         _mmstreamrec_dbg_log("Got EOS from element \"%s\".", GST_STR_NULL(GST_ELEMENT_NAME(GST_MESSAGE_SRC(message))));
741
742                         sc = MMF_STREAMRECORDER_SUBCONTEXT(hstreamrecorder);
743                         mmf_return_val_if_fail(sc, TRUE);
744
745                         /*if (hstreamrecorder->type != MM_STREAMRECORDER_MODE_AUDIO) { */
746                         mmf_return_val_if_fail(sc->info_video, TRUE);
747                         if (sc->info_video->b_commiting) {
748                                 _mmstreamrecorder_video_handle_eos((MMHandleType) hstreamrecorder);
749                         }
750                         /*} else {
751                            mmf_return_val_if_fail(sc->info_audio, TRUE);
752                            if (sc->info_audio->b_commiting) {
753                            _mmstreamrecorder_audio_handle_eos((MMHandleType)hstreamrecorder);
754                            }
755                            } */
756
757                         sc->bget_eos = TRUE;
758
759                         break;
760                 }
761         case GST_MESSAGE_ERROR:
762                 {
763                         GError *err;
764                         gchar *debug;
765                         gst_message_parse_error(message, &err, &debug);
766
767                         _mmstreamrec_dbg_err("GSTERR: %s", err->message);
768                         _mmstreamrec_dbg_err("Error Debug: %s", debug);
769
770                         _mmstreamrecorder_handle_gst_error((MMHandleType) hstreamrecorder, message, err);
771
772                         g_error_free(err);
773                         g_free(debug);
774                         break;
775                 }
776         case GST_MESSAGE_WARNING:
777                 {
778                         GError *err;
779                         gchar *debug;
780                         gst_message_parse_warning(message, &err, &debug);
781
782                         _mmstreamrec_dbg_warn("GSTWARN: %s", err->message);
783
784                         _mmstreamrecorder_handle_gst_warning((MMHandleType) hstreamrecorder, message, err);
785
786                         g_error_free(err);
787                         g_free(debug);
788                         break;
789                 }
790         case GST_MESSAGE_INFO:
791                 _mmstreamrec_dbg_log("GST_MESSAGE_INFO");
792                 break;
793         case GST_MESSAGE_TAG:
794                 _mmstreamrec_dbg_log("GST_MESSAGE_TAG");
795                 break;
796         case GST_MESSAGE_BUFFERING:
797                 _mmstreamrec_dbg_log("GST_MESSAGE_BUFFERING");
798                 break;
799         case GST_MESSAGE_STATE_CHANGED:
800                 {
801                         const GValue *vnewstate;
802                         GstState newstate;
803                         GstElement *pipeline = NULL;
804
805                         sc = MMF_STREAMRECORDER_SUBCONTEXT(hstreamrecorder);
806                         if ((sc) && (sc->encode_element)) {
807                                 if (sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst) {
808                                         pipeline = sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst;
809                                         if (message->src == (GstObject *) pipeline) {
810                                                 vnewstate = (GValue *) gst_structure_get_value(gst_message_get_structure(message), "new-state");
811                                                 newstate = (GstState) vnewstate->data[0].v_int;
812                                                 _mmstreamrec_dbg_log("GST_MESSAGE_STATE_CHANGED[%s]", gst_element_state_get_name(newstate));
813                                         }
814                                 }
815                         }
816                         break;
817                 }
818         case GST_MESSAGE_STATE_DIRTY:
819                 _mmstreamrec_dbg_log("GST_MESSAGE_STATE_DIRTY");
820                 break;
821         case GST_MESSAGE_STEP_DONE:
822                 _mmstreamrec_dbg_log("GST_MESSAGE_STEP_DONE");
823                 break;
824         case GST_MESSAGE_CLOCK_PROVIDE:
825                 _mmstreamrec_dbg_log("GST_MESSAGE_CLOCK_PROVIDE");
826                 break;
827         case GST_MESSAGE_CLOCK_LOST:
828                 _mmstreamrec_dbg_log("GST_MESSAGE_CLOCK_LOST");
829                 break;
830         case GST_MESSAGE_NEW_CLOCK:
831                 {
832                         GstClock *l_clock;
833                         gst_message_parse_new_clock(message, &l_clock);
834                         _mmstreamrec_dbg_log("GST_MESSAGE_NEW_CLOCK : %s", (l_clock ? GST_OBJECT_NAME(l_clock) : "NULL"));
835                         break;
836                 }
837         case GST_MESSAGE_STRUCTURE_CHANGE:
838                 _mmstreamrec_dbg_log("GST_MESSAGE_STRUCTURE_CHANGE");
839                 break;
840         case GST_MESSAGE_STREAM_STATUS:
841                 _mmstreamrec_dbg_log("GST_MESSAGE_STREAM_STATUS");
842                 break;
843         case GST_MESSAGE_APPLICATION:
844                 _mmstreamrec_dbg_log("GST_MESSAGE_APPLICATION");
845                 break;
846         case GST_MESSAGE_ELEMENT:
847                 _mmstreamrec_dbg_log("GST_MESSAGE_ELEMENT");
848                 break;
849         case GST_MESSAGE_SEGMENT_START:
850                 _mmstreamrec_dbg_log("GST_MESSAGE_SEGMENT_START");
851                 break;
852         case GST_MESSAGE_SEGMENT_DONE:
853                 _mmstreamrec_dbg_log("GST_MESSAGE_SEGMENT_DONE");
854                 break;
855         case GST_MESSAGE_DURATION:
856                 _mmstreamrec_dbg_log("GST_MESSAGE_DURATION");
857                 break;
858         case GST_MESSAGE_LATENCY:
859                 _mmstreamrec_dbg_log("GST_MESSAGE_LATENCY");
860                 break;
861         case GST_MESSAGE_ASYNC_START:
862                 _mmstreamrec_dbg_log("GST_MESSAGE_ASYNC_START");
863                 break;
864         case GST_MESSAGE_ASYNC_DONE:
865                 _mmstreamrec_dbg_log("GST_MESSAGE_ASYNC_DONE");
866                 break;
867         case GST_MESSAGE_ANY:
868                 _mmstreamrec_dbg_log("GST_MESSAGE_ANY");
869                 break;
870         default:
871                 _mmstreamrec_dbg_log("not handled message type=(%d)", GST_MESSAGE_TYPE(message));
872                 break;
873         }
874
875         return TRUE;
876 }
877
878 /**
879  * This function is record video data probing function.
880  * If this function is linked with certain pad by gst_pad_add_buffer_probe(),
881  * this function will be called when data stream pass through the pad.
882  *
883  * @param[in]   pad             probing pad which calls this function.
884  * @param[in]   buffer          buffer which contains stream data.
885  * @param[in]   u_data          user data.
886  * @return      This function returns true on success, or false value with error
887  * @remarks
888  * @see
889  */
890 GstPadProbeReturn __mmstreamrecorder_eventprobe_monitor(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
891 {
892         GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info);
893         switch (GST_EVENT_TYPE(event)) {
894         case GST_EVENT_UNKNOWN:
895                 /* upstream events */
896         case GST_EVENT_QOS:
897         case GST_EVENT_SEEK:
898         case GST_EVENT_NAVIGATION:
899         case GST_EVENT_LATENCY:
900                 /* downstream serialized events */
901         case GST_EVENT_SEGMENT:
902         case GST_EVENT_TAG:
903         case GST_EVENT_BUFFERSIZE:
904                 _mmstreamrec_dbg_log("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event));
905                 break;
906         case GST_EVENT_EOS:
907                 _mmstreamrec_dbg_warn("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event));
908                 break;
909                 /* bidirectional events */
910         case GST_EVENT_FLUSH_START:
911         case GST_EVENT_FLUSH_STOP:
912                 _mmstreamrec_dbg_err("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event));
913                 break;
914         default:
915                 _mmstreamrec_dbg_log("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event));
916                 break;
917         }
918
919         return GST_PAD_PROBE_OK;
920 }
921
922 GstPadProbeReturn __mmstreamrecorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
923 {
924         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(u_data);
925         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
926         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
927         guint64 buffer_size = 0;
928
929         _MMStreamRecorderSubContext *sc = NULL;
930         _MMStreamRecorderAudioInfo *audioinfo = NULL;
931
932         mmf_return_val_if_fail(hstreamrecorder, GST_PAD_PROBE_OK);
933         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
934         sc = MMF_STREAMRECORDER_SUBCONTEXT(hstreamrecorder);
935
936         mmf_return_val_if_fail(sc && sc->info_audio, GST_PAD_PROBE_OK);
937         memset(&mapinfo, 0x0, sizeof(GstMapInfo));
938
939         audioinfo = sc->info_audio;
940
941         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
942         buffer_size = mapinfo.size;
943         gst_buffer_unmap(buffer, &mapinfo);
944
945         /*_mmstreamrec_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));*/
946
947         if (audioinfo->audio_frame_count == 0) {
948                 audioinfo->filesize += buffer_size;
949                 audioinfo->audio_frame_count++;
950                 return GST_PAD_PROBE_OK;
951         }
952
953         if (sc->ferror_send || sc->isMaxsizePausing) {
954                 _mmstreamrec_dbg_warn("Recording is paused, drop frames");
955                 return GST_PAD_PROBE_DROP;
956         }
957
958         audioinfo->filesize += buffer_size;
959         audioinfo->audio_frame_count++;
960
961         return GST_PAD_PROBE_OK;
962 }
963
964 GstPadProbeReturn __mmstreamrecorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
965 {
966         static int count = 0;
967         gint ret = 0;
968         guint vq_size = 0;
969         guint aq_size = 0;
970         guint64 free_space = 0;
971         guint64 buffer_size = 0;
972         guint64 trailer_size = 0;
973         guint64 queued_buffer = 0;
974         char *filename = NULL;
975         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
976         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
977
978         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(u_data);
979         _MMStreamRecorderMsgItem msg;
980         _MMStreamRecorderSubContext *sc = NULL;
981         _MMStreamRecorderVideoInfo *videoinfo = NULL;
982         _MMStreamRecorderFileInfo *finfo = NULL;
983
984         mmf_return_val_if_fail(hstreamrecorder, GST_PAD_PROBE_OK);
985         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
986
987         sc = MMF_STREAMRECORDER_SUBCONTEXT(hstreamrecorder);
988         mmf_return_val_if_fail(sc && sc->info_video && sc->info_file, TRUE);
989         memset(&mapinfo, 0x0, sizeof(GstMapInfo));
990
991         videoinfo = sc->info_video;
992         finfo = sc->info_file;
993
994         /*_mmstreamrec_dbg_log("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));*/
995         if (sc->ferror_send) {
996                 _mmstreamrec_dbg_warn("file write error, drop frames");
997                 return GST_PAD_PROBE_DROP;
998         }
999         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
1000         buffer_size = mapinfo.size;
1001         gst_buffer_unmap(buffer, &mapinfo);
1002
1003         videoinfo->video_frame_count++;
1004         if (videoinfo->video_frame_count <= (guint64) _MMSTREAMRECORDER_MINIMUM_FRAME) {
1005                 /* _mmstreamrec_dbg_log("Pass minimum frame: info->video_frame_count: %" G_GUINT64_FORMAT " ", info->video_frame_count); */
1006                 videoinfo->filesize += buffer_size;
1007                 return GST_PAD_PROBE_OK;
1008         }
1009
1010         /* get trailer size */
1011         if (finfo->fileformat == MM_FILE_FORMAT_3GP || finfo->fileformat == MM_FILE_FORMAT_MP4) {
1012                 MMSTREAMRECORDER_G_OBJECT_GET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1013         } else {
1014                 trailer_size = 0;
1015         }
1016
1017         /* to minimizing free space check overhead */
1018         count = count % _MMSTREAMRECORDER_FREE_SPACE_CHECK_INTERVAL;
1019         if (count++ == 0) {
1020                 filename = finfo->filename;
1021                 ret = _mmstreamrecorder_get_freespace(filename, &free_space);
1022
1023                 /*_mmstreamrec_dbg_log("check free space for recording");*/
1024
1025                 switch (ret) {
1026                 case -2:                                /* file not exist */
1027                 case -1:                                /* failed to get free space */
1028                         _mmstreamrec_dbg_err("Error occured. [%d]", ret);
1029                         if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
1030                                 sc->ferror_send = TRUE;
1031                                 msg.id = MM_MESSAGE_STREAMRECORDER_ERROR;
1032                                 if (ret == -2) {
1033                                         msg.param.code = MM_ERROR_FILE_NOT_FOUND;
1034                                 } else {
1035                                         msg.param.code = MM_ERROR_FILE_READ;
1036                                 }
1037                                 _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1038                         } else {
1039                                 sc->ferror_count++;
1040                         }
1041
1042                         return GST_PAD_PROBE_DROP;      /* skip this buffer */
1043                         break;
1044                 default:                                /* succeeded to get free space */
1045                         /* check free space for recording */
1046                         /* get queued buffer size */
1047                         if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC_QUE].gst) {
1048                                 MMSTREAMRECORDER_G_OBJECT_GET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC_QUE].gst, "current-level-bytes", &aq_size);
1049                         }
1050                         if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC_QUE].gst) {
1051                                 MMSTREAMRECORDER_G_OBJECT_GET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC_QUE].gst, "current-level-bytes", &vq_size);
1052                         }
1053
1054                         queued_buffer = aq_size + vq_size;
1055
1056                         /* check free space */
1057                         if (free_space < (_MMSTREAMRECORDER_MINIMUM_SPACE + buffer_size + trailer_size + queued_buffer)) {
1058                                 _mmstreamrec_dbg_warn("No more space for recording!!! Recording is paused.");
1059                                 _mmstreamrec_dbg_warn("Free Space : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]," " buffer size : [%" G_GUINT64_FORMAT "], queued buffer size : [%" G_GUINT64_FORMAT "]", free_space, trailer_size, buffer_size, queued_buffer);
1060
1061                                 if (!sc->isMaxsizePausing) {
1062                                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1063                                         sc->isMaxsizePausing = TRUE;
1064
1065                                         msg.id = MM_MESSAGE_STREAMRECORDER_NO_FREE_SPACE;
1066                                         _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1067                                 }
1068
1069                                 return GST_PAD_PROBE_DROP;
1070                         }
1071                         break;
1072                 }
1073         }
1074
1075         videoinfo->filesize += (guint64) buffer_size;
1076
1077         /*
1078            _mmstreamrec_dbg_log("filesize %lld Byte, ", info->filesize);
1079          */
1080
1081         return GST_PAD_PROBE_OK;
1082 }
1083
1084 GstPadProbeReturn __mmstreamrecorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1085 {
1086         guint64 trailer_size = 0;
1087         guint64 rec_pipe_time = 0;
1088         unsigned int remained_time = 0;
1089
1090         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1091         GstClockTime b_time;
1092
1093         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(u_data);
1094         _MMStreamRecorderMsgItem msg;
1095         _MMStreamRecorderSubContext *sc = NULL;
1096         _MMStreamRecorderVideoInfo *videoinfo = NULL;
1097         _MMStreamRecorderFileInfo *finfo = NULL;
1098
1099         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1100         mmf_return_val_if_fail(hstreamrecorder, GST_PAD_PROBE_OK);
1101
1102         sc = MMF_STREAMRECORDER_SUBCONTEXT(u_data);
1103         mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1104         mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1105         mmf_return_val_if_fail(sc->info_file, GST_PAD_PROBE_OK);
1106
1107         videoinfo = sc->info_video;
1108         finfo = sc->info_file;
1109
1110         b_time = GST_BUFFER_TIMESTAMP(buffer);
1111
1112         rec_pipe_time = GST_TIME_AS_MSECONDS(b_time);
1113
1114         if (finfo->fileformat == MM_FILE_FORMAT_3GP || finfo->fileformat == MM_FILE_FORMAT_MP4) {
1115                 MMSTREAMRECORDER_G_OBJECT_GET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1116         } else {
1117                 trailer_size = 0;
1118         }
1119
1120         /* check max time */
1121         if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1122                 _mmstreamrec_dbg_warn("Current time : [%" G_GUINT64_FORMAT "], Maximum time : [%" G_GUINT64_FORMAT "]", rec_pipe_time, videoinfo->max_time);
1123
1124                 if (!sc->isMaxtimePausing) {
1125                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1126
1127                         sc->isMaxtimePausing = TRUE;
1128
1129                         msg.id = MM_MESSAGE_STREAMRECORDER_RECORDING_STATUS;
1130                         msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1131                         msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1132                         msg.param.recording_status.remained_time = 0;
1133                         _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1134
1135                         msg.id = MM_MESSAGE_STREAMRECORDER_TIME_LIMIT;
1136                         _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1137                 }
1138
1139                 return GST_PAD_PROBE_DROP;
1140         }
1141
1142         if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time))
1143                 remained_time = videoinfo->max_time - rec_pipe_time;
1144
1145         msg.id = MM_MESSAGE_STREAMRECORDER_RECORDING_STATUS;
1146         msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1147         msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1148         msg.param.recording_status.remained_time = remained_time;
1149         _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1150
1151         /*
1152            _mmstreamrec_dbg_log("time [%" GST_TIME_FORMAT "], size [%d]",
1153            GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1154          */
1155
1156         return GST_PAD_PROBE_OK;
1157 }
1158
1159 GstPadProbeReturn __mmstreamrecorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1160 {
1161         _MMStreamRecorderMsgItem msg;
1162         guint64 trailer_size = 0;
1163         guint64 rec_pipe_time = 0;
1164         _MMStreamRecorderSubContext *sc = NULL;
1165         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(u_data);
1166         _MMStreamRecorderVideoInfo *videoinfo = NULL;
1167         _MMStreamRecorderFileInfo *finfo = NULL;
1168         unsigned int remained_time = 0;
1169         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1170
1171         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1172         mmf_return_val_if_fail(hstreamrecorder, GST_PAD_PROBE_OK);
1173         sc = MMF_STREAMRECORDER_SUBCONTEXT(u_data);
1174
1175         mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK);
1176         mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK);
1177         mmf_return_val_if_fail(sc->info_file, GST_PAD_PROBE_OK);
1178
1179         videoinfo = sc->info_video;
1180         finfo = sc->info_file;
1181
1182         if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) {
1183                 _mmstreamrec_dbg_err("Buffer timestamp is invalid, check it");
1184                 return GST_PAD_PROBE_OK;
1185         }
1186
1187         rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_TIMESTAMP(buffer));
1188
1189         if (finfo->fileformat == MM_FILE_FORMAT_3GP || finfo->fileformat == MM_FILE_FORMAT_MP4) {
1190                 MMSTREAMRECORDER_G_OBJECT_GET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1191         } else {
1192                 trailer_size = 0;
1193         }
1194
1195         if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time))
1196                 remained_time = videoinfo->max_time - rec_pipe_time;
1197
1198         if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) {
1199                 _mmstreamrec_dbg_warn("Current time : [%" G_GUINT64_FORMAT "], Maximum time : [%" G_GUINT64_FORMAT "]", rec_pipe_time, videoinfo->max_time);
1200
1201                 if (!sc->isMaxtimePausing) {
1202                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1203
1204                         sc->isMaxtimePausing = TRUE;
1205
1206                         msg.id = MM_MESSAGE_STREAMRECORDER_RECORDING_STATUS;
1207                         msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1208                         msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1209                         msg.param.recording_status.remained_time = 0;
1210                         _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1211
1212                         msg.id = MM_MESSAGE_STREAMRECORDER_TIME_LIMIT;
1213                         _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1214                 }
1215
1216                 return GST_PAD_PROBE_DROP;
1217         }
1218
1219         msg.id = MM_MESSAGE_STREAMRECORDER_RECORDING_STATUS;
1220         msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1221         msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10);
1222         msg.param.recording_status.remained_time = remained_time;
1223         _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1224
1225         /*
1226            _mmstreamrec_dbg_log("audio data probe :: time [%" GST_TIME_FORMAT "], size [%lld KB]",
1227            GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize);
1228          */
1229
1230         return GST_PAD_PROBE_OK;
1231 }
1232
1233 void __mmstreamrecorder_audiorec_pad_added_cb(GstElement *element, GstPad *pad, MMHandleType handle)
1234 {
1235         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1236
1237         _mmstreamrec_dbg_log("ENTER(%s)", GST_PAD_NAME(pad));
1238         /* FIXME : the name of audio sink pad of wavparse, oggmux doesn't have 'audio'. How could I handle the name? */
1239         if ((strstr(GST_PAD_NAME(pad), "audio")) || (strstr(GST_PAD_NAME(pad), "sink"))) {
1240                 MMSTREAMRECORDER_ADD_BUFFER_PROBE(pad, _MMSTREAMRECORDER_HANDLER_AUDIOREC, __mmstreamrecorder_audio_dataprobe_record, hstreamrecorder);
1241         } else {
1242                 _mmstreamrec_dbg_warn("Unknow pad is added, check it : [%s]", GST_PAD_NAME(pad));
1243         }
1244
1245         return;
1246 }
1247
1248 GstPadProbeReturn __mmstreamrecorder_audio_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
1249 {
1250         static int count = 0;
1251         guint64 rec_pipe_time = 0;
1252         guint64 free_space = 0;
1253         guint64 buffer_size = 0;
1254         guint64 trailer_size = 0;
1255         char *filename = NULL;
1256         unsigned long long remained_time = 0;
1257         GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
1258
1259         _MMStreamRecorderSubContext *sc = NULL;
1260         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(u_data);
1261         _MMStreamRecorderAudioInfo *audioinfo = NULL;
1262         _MMStreamRecorderFileInfo *finfo = NULL;
1263         _MMStreamRecorderMsgItem msg;
1264
1265         mmf_return_val_if_fail(hstreamrecorder, GST_PAD_PROBE_DROP);
1266         mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
1267
1268         sc = MMF_STREAMRECORDER_SUBCONTEXT(hstreamrecorder);
1269         mmf_return_val_if_fail(sc && sc->info_audio && sc->info_file, FALSE);
1270         audioinfo = sc->info_audio;
1271         finfo = sc->info_file;
1272
1273         if (sc->isMaxtimePausing || sc->isMaxsizePausing) {
1274                 _mmstreamrec_dbg_warn("isMaxtimePausing[%d],isMaxsizePausing[%d]", sc->isMaxtimePausing, sc->isMaxsizePausing);
1275                 return GST_PAD_PROBE_DROP;
1276         }
1277
1278         buffer_size = gst_buffer_get_size(buffer);
1279
1280         if (audioinfo->filesize == 0) {
1281                 if (finfo->fileformat == MM_FILE_FORMAT_WAV) {
1282                         audioinfo->filesize += 44;      /* wave header size */
1283                 } else if (finfo->fileformat == MM_FILE_FORMAT_AMR) {
1284                         audioinfo->filesize += 6;       /* amr header size */
1285                 }
1286
1287                 audioinfo->filesize += buffer_size;
1288                 return GST_PAD_PROBE_OK;
1289         }
1290
1291         if (sc->ferror_send) {
1292                 _mmstreamrec_dbg_warn("file write error, drop frames");
1293                 return GST_PAD_PROBE_DROP;
1294         }
1295
1296         /* get trailer size */
1297         if (finfo->fileformat == MM_FILE_FORMAT_3GP || finfo->fileformat == MM_FILE_FORMAT_MP4 || finfo->fileformat == MM_FILE_FORMAT_AAC) {
1298                 MMSTREAMRECORDER_G_OBJECT_GET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
1299                 /*_mmstreamrec_dbg_log("trailer_size %d", trailer_size);*/
1300         } else {
1301                 trailer_size = 0;               /* no trailer */
1302         }
1303
1304         filename = finfo->filename;
1305
1306         /* to minimizing free space check overhead */
1307         count = count % _MMSTREAMRECORDER_AUDIO_FREE_SPACE_CHECK_INTERVAL;
1308         if (count++ == 0) {
1309                 gint free_space_ret = _mmstreamrecorder_get_freespace(filename, &free_space);
1310
1311                 /*_mmstreamrec_dbg_log("check free space for recording");*/
1312
1313                 switch (free_space_ret) {
1314                 case -2:                                /* file not exist */
1315                 case -1:                                /* failed to get free space */
1316                         _mmstreamrec_dbg_err("Error occured. [%d]", free_space_ret);
1317                         if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
1318                                 sc->ferror_send = TRUE;
1319                                 msg.id = MM_MESSAGE_STREAMRECORDER_ERROR;
1320                                 if (free_space_ret == -2) {
1321                                         msg.param.code = MM_ERROR_FILE_NOT_FOUND;
1322                                 } else {
1323                                         msg.param.code = MM_ERROR_FILE_READ;
1324                                 }
1325                                 _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1326                         } else {
1327                                 sc->ferror_count++;
1328                         }
1329
1330                         return GST_PAD_PROBE_DROP;      /* skip this buffer */
1331
1332                 default:                                /* succeeded to get free space */
1333                         /* check free space for recording */
1334                         if (free_space < (guint64) (_MMSTREAMRECORDER_AUDIO_MINIMUM_SPACE + buffer_size + trailer_size)) {
1335                                 _mmstreamrec_dbg_warn("No more space for recording!!!");
1336                                 _mmstreamrec_dbg_warn("Free Space : [%" G_GUINT64_FORMAT "], file size : [%" G_GUINT64_FORMAT "]", free_space, audioinfo->filesize);
1337
1338                                 if (audioinfo->bMuxing) {
1339                                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1340                                 } else {
1341                                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AQUE].gst, "empty-buffers", TRUE);
1342                                 }
1343
1344                                 sc->isMaxsizePausing = TRUE;
1345                                 msg.id = MM_MESSAGE_STREAMRECORDER_NO_FREE_SPACE;
1346                                 _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1347
1348                                 return FALSE;   /* skip this buffer */
1349                         }
1350                         break;
1351                 }
1352         }
1353
1354         if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) {
1355                 _mmstreamrec_dbg_err("Buffer timestamp is invalid, check it");
1356                 return GST_PAD_PROBE_DROP;
1357         }
1358
1359         rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_TIMESTAMP(buffer));
1360
1361         if (audioinfo->max_time > 0 && audioinfo->max_time < (remained_time + rec_pipe_time))
1362                 remained_time = audioinfo->max_time - rec_pipe_time;
1363
1364         /*_mmstreamrec_dbg_log("remained time : %u", remained_time);*/
1365
1366         /* check recording time limit and send recording status message */
1367         if (audioinfo->max_time > 0 && rec_pipe_time > audioinfo->max_time) {
1368                 _mmstreamrec_dbg_warn("Current time : [%" G_GUINT64_FORMAT "], Maximum time : [%" G_GUINT64_FORMAT "]", rec_pipe_time, audioinfo->max_time);
1369
1370                 if (audioinfo->bMuxing) {
1371                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
1372                 } else {
1373                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AQUE].gst, "empty-buffers", TRUE);
1374                 }
1375
1376                 sc->isMaxtimePausing = TRUE;
1377                 msg.id = MM_MESSAGE_STREAMRECORDER_TIME_LIMIT;
1378                 _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1379
1380                 /* skip this buffer */
1381                 return GST_PAD_PROBE_DROP;
1382         }
1383
1384         /* send message for recording time and recorded file size */
1385         if (audioinfo->b_commiting == FALSE) {
1386                 audioinfo->filesize += buffer_size;
1387
1388                 msg.id = MM_MESSAGE_STREAMRECORDER_RECORDING_STATUS;
1389                 msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time;
1390                 msg.param.recording_status.filesize = (unsigned long long)((audioinfo->filesize + trailer_size) >> 10);
1391                 msg.param.recording_status.remained_time = remained_time;
1392                 _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1393
1394                 return GST_PAD_PROBE_OK;
1395         } else {
1396                 /* skip this buffer if commit process has been started */
1397                 return GST_PAD_PROBE_DROP;
1398         }
1399 }