02cb2b181ba366a72db8e5b0da2d47cc2afc8801
[platform/core/multimedia/libmm-streamrecorder.git] / src / mm_streamrecorder_recorder.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 "mm_streamrecorder_internal.h"
26 #include "mm_streamrecorder_video.h"
27 #include "mm_streamrecorder_gstcommon.h"
28 #include "mm_streamrecorder_recorder.h"
29 #include "mm_streamrecorder_util.h"
30 #include "mm_streamrecorder_buffer_manager.h"
31 #include "mm_streamrecorder_fileinfo.h"
32 #include "mm_streamrecorder_attribute.h"
33
34 #include <gst/gst.h>
35 #include <gst/base/gstadapter.h>
36 #include <gst/app/gstappsrc.h>
37 #include <gst/app/gstappsink.h>
38
39
40 /*---------------------------------------------------------------------------------------
41 |    GLOBAL VARIABLE DEFINITIONS for internal                                           |
42 ---------------------------------------------------------------------------------------*/
43
44 /*---------------------------------------------------------------------------------------
45 |    LOCAL VARIABLE DEFINITIONS for internal                                            |
46 ---------------------------------------------------------------------------------------*/
47
48 /*-----------------------------------------------------------------------
49 |    GLOBAL VARIABLE DEFINITIONS for internal                           |
50 -----------------------------------------------------------------------*/
51
52 /*---------------------------------------------------------------------------------------
53 |    LOCAL FUNCTION PROTOTYPES:                                                         |
54 ---------------------------------------------------------------------------------------*/
55 /* STATIC INTERNAL FUNCTION */
56
57 /*=======================================================================================
58 |  FUNCTION DEFINITIONS                                                                 |
59 =======================================================================================*/
60 /*---------------------------------------------------------------------------------------
61 |    GLOBAL FUNCTION DEFINITIONS:                                                       |
62 ---------------------------------------------------------------------------------------*/
63 int _mmstreamrecorder_create_pipeline(MMHandleType handle)
64 {
65         int ret = MM_ERROR_NONE;
66         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
67         _MMStreamRecorderSubContext *sc = NULL;
68         GstElement *pipeline = NULL;
69
70         _mmstreamrec_dbg_log("handle : %x", handle);
71
72         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
73
74         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
75         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
76
77         /* ENCODER MODE */
78         ret = _mmstreamrecorder_create_recorder_pipeline(handle);
79
80         pipeline = sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst;
81
82         ret = _mmstreamrecorder_gst_set_state(handle, pipeline, GST_STATE_READY);
83
84         _mmstreamrec_dbg_log("ret[%x]", ret);
85         return ret;
86 }
87
88 void _mmstreamrecorder_destroy_pipeline(MMHandleType handle)
89 {
90         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
91         _MMStreamRecorderSubContext *sc = NULL;
92         gint i = 0;
93         int element_num = 0;
94         _MMStreamRecorderGstElement *element = NULL;
95         GstBus *bus = NULL;
96
97         mmf_return_if_fail(hstreamrecorder);
98
99         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
100         mmf_return_if_fail(sc);
101
102         _mmstreamrec_dbg_log("");
103
104         element = sc->encode_element;
105         element_num = sc->encode_element_num;
106         if (element == NULL) {
107                 _mmstreamrec_dbg_log("encode element is null!!");
108                 return;
109         }
110
111         if (sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst != NULL) {
112                 bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst));
113
114                 _mmstreamrec_dbg_log("Pipeline clear!!");
115
116                 /* Remove pipeline message callback */
117                 if (hstreamrecorder->pipeline_cb_event_id != 0) {
118                         g_source_remove(hstreamrecorder->pipeline_cb_event_id);
119                         hstreamrecorder->pipeline_cb_event_id = 0;
120                 }
121
122                 /* Remove remained message in bus */
123                 if (bus) {
124                         GstMessage *gst_msg = NULL;
125                         while ((gst_msg = gst_bus_pop(bus)) != NULL) {
126                                 _mmstreamrecorder_pipeline_cb_message(bus, gst_msg, (gpointer) hstreamrecorder);
127                                 gst_message_unref(gst_msg);
128                                 gst_msg = NULL;
129                         }
130                         gst_object_unref(bus);
131                         bus = NULL;
132                 }
133
134                 /* Inside each pipeline destroy function, Set GST_STATE_NULL to Main pipeline */
135                 _mmstreamrecorder_destroy_recorder_pipeline(handle);
136         }
137
138         if (element != NULL) {
139                 /* checking unreleased element */
140                 for (i = 0; i < element_num; i++) {
141                         if (element[i].gst) {
142                                 if (GST_IS_ELEMENT(element[i].gst)) {
143                                         _mmstreamrec_dbg_warn("Still alive element - ID[%d], name [%s], ref count[%d], status[%s]", element[i].id, GST_OBJECT_NAME(element[i].gst), GST_OBJECT_REFCOUNT(element[i].gst), gst_element_state_get_name(GST_STATE(element[i].gst)));
144                                         g_object_weak_unref(G_OBJECT(element[i].gst), (GWeakNotify) _mmstreamrecorder_element_release_noti, sc);
145                                 } else {
146                                         _mmstreamrec_dbg_warn("The element[%d] is still aliving, check it", element[i].id);
147                                 }
148
149                                 element[i].id = _MMSTREAMRECORDER_ENCODE_NONE;
150                                 element[i].gst = NULL;
151                         }
152                 }
153         }
154         return;
155 }
156
157 int _mmstreamrecorder_create_recorder_pipeline(MMHandleType handle)
158 {
159         int i = 0;
160         int err = MM_ERROR_NONE;
161         int audio_enable = FALSE;
162         GstBus *bus = NULL;
163         GstPad *srcpad = NULL;
164         GstPad *sinkpad = NULL;
165
166         unsigned int video_codec = MM_VIDEO_CODEC_INVALID;
167         unsigned int file_format = MM_FILE_FORMAT_INVALID;
168         char *err_name = NULL;
169
170         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
171         _MMStreamRecorderSubContext *sc = NULL;
172
173         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
174
175         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
176         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
177
178         _mmstreamrec_dbg_warn("start");
179
180         err = mm_streamrecorder_get_attributes(handle, &err_name, MMSTR_VIDEO_ENCODER, &video_codec, MMSTR_FILE_FORMAT, &file_format, NULL);
181         if (err != MM_ERROR_NONE) {
182                 _mmstreamrec_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
183                 SAFE_FREE(err_name);
184                 return err;
185         }
186
187         err = _mmstreamrecorder_check_videocodec_fileformat_compatibility(video_codec, file_format);
188         if (err != MM_ERROR_NONE)
189                 return err;
190
191         /* Main pipeline */
192         _MMSTREAMRECORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCODE_MAIN_PIPE, "recorder_pipeline", err);
193
194         /* get audio disable */
195         mm_streamrecorder_get_attributes(handle, NULL, MMSTR_AUDIO_ENABLE, &audio_enable, NULL);
196         sc->audio_enable = audio_enable;
197
198         _mmstreamrec_dbg_log("AUDIO DISABLE : %d", sc->audio_enable);
199
200         if (sc->audio_enable == TRUE) {
201                 /* create audiosrc bin */
202                 err = _mmstreamrecorder_create_audiosrc_bin((MMHandleType) hstreamrecorder);
203                 if (err != MM_ERROR_NONE)
204                         return err;
205         }
206
207         err = _mmstreamrecorder_create_encodesink_bin((MMHandleType) hstreamrecorder, MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO);
208         if (err != MM_ERROR_NONE)
209                 return err;
210
211         if (sc->audio_enable == TRUE) {
212                 gst_bin_add(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst);
213         }
214
215         /* add element and encodesink bin to encode main pipeline */
216         gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, NULL);
217
218         /* Link each element : appsrc - capsfilter - encodesink bin */
219         srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "src");
220         sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, "sink");
221         _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
222
223         srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, "src");
224         sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, "video_sink0");
225         _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
226
227         if (sc->audio_enable == TRUE) {
228                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, "src");
229                 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, "audio_sink0");
230                 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
231         }
232
233         if (sc->audio_enable == TRUE) {
234                 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "sink");
235                 MMSTREAMRECORDER_ADD_BUFFER_PROBE(sinkpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_audioque_dataprobe, hstreamrecorder);
236                 gst_object_unref(sinkpad);
237                 sinkpad = NULL;
238
239                 if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC_QUE].gst) {
240                         srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC_QUE].gst, "src");
241                         MMSTREAMRECORDER_ADD_EVENT_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_eventprobe_monitor, hstreamrecorder);
242                         gst_object_unref(srcpad);
243                         srcpad = NULL;
244                 }
245         }
246
247         if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC_QUE].gst) {
248                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC_QUE].gst, "src");
249                 MMSTREAMRECORDER_ADD_EVENT_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_eventprobe_monitor, hstreamrecorder);
250                 gst_object_unref(srcpad);
251                 srcpad = NULL;
252         }
253
254         if (sc->audio_enable == FALSE) {
255                 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "sink");
256                 MMSTREAMRECORDER_ADD_BUFFER_PROBE(sinkpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_video_dataprobe_audio_disable, hstreamrecorder);
257                 gst_object_unref(sinkpad);
258                 sinkpad = NULL;
259         }
260
261         if (!strcmp(/*gst_element_rsink_name */"filesink", "filesink")) {
262                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "src");
263                 MMSTREAMRECORDER_ADD_BUFFER_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_video_dataprobe_record, hstreamrecorder);
264                 gst_object_unref(srcpad);
265                 srcpad = NULL;
266
267                 if (sc->audio_enable == TRUE) {
268                         srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "src");
269                         MMSTREAMRECORDER_ADD_BUFFER_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_audio_dataprobe_check, hstreamrecorder);
270                         gst_object_unref(srcpad);
271                         srcpad = NULL;
272                 }
273         }
274
275         bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst));
276
277         /* register pipeline message callback */
278         hstreamrecorder->encode_pipeline_cb_event_id = gst_bus_add_watch(bus, (GstBusFunc) _mmstreamrecorder_pipeline_cb_message, hstreamrecorder);
279
280         gst_object_unref(bus);
281         bus = NULL;
282
283         return MM_ERROR_NONE;
284
285  pipeline_creation_error:
286         for (i = _MMSTREAMRECORDER_AUDIOSRC_BIN; i <= _MMSTREAMRECORDER_ENCSINK_SINK; i++) {
287                 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, i);
288         }
289         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCODE_MAIN_PIPE);
290         return err;
291 }
292
293 int _mmstreamrecorder_destroy_recorder_pipeline(MMHandleType handle)
294 {
295         int ret = MM_ERROR_NONE;
296         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
297         _MMStreamRecorderSubContext *sc = NULL;
298
299         GstBus *bus = NULL;
300
301         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
302         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
303         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
304
305         _mmstreamrec_dbg_log("start");
306
307         if (!sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst) {
308                 _mmstreamrec_dbg_warn("pipeline is not existed.");
309                 return MM_ERROR_NONE;
310         }
311
312         _mmstreamrecorder_remove_all_handlers((MMHandleType) hstreamrecorder, _MMSTREAMRECORDER_HANDLER_VIDEOREC);
313
314         ret = _mmstreamrecorder_gst_set_state(handle, sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_NULL);
315         if (ret != MM_ERROR_NONE) {
316                 _mmstreamrec_dbg_err("Faile to change encode main pipeline [0x%x]", ret);
317                 return ret;
318         }
319
320         bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst));
321
322         /* Remove remained message */
323         if (bus) {
324                 GstMessage *gst_msg = NULL;
325                 while ((gst_msg = gst_bus_pop(bus)) != NULL) {
326                         _mmstreamrecorder_pipeline_cb_message(bus, gst_msg, (gpointer) hstreamrecorder);
327                         gst_message_unref(gst_msg);
328                         gst_msg = NULL;
329                 }
330                 gst_object_unref(bus);
331                 bus = NULL;
332         }
333
334         /* remove audio pipeline first */
335         ret = _mmstreamrecorder_destroy_audiosrc_bin(handle);
336         if (ret != MM_ERROR_NONE) {
337                 _mmstreamrec_dbg_err("Fail to remove audio pipeline");
338                 return ret;
339         }
340
341         ret = _mmstreamrecorder_destroy_encodesink_bin(handle);
342         if (ret != MM_ERROR_NONE) {
343                 _mmstreamrec_dbg_err("Fail to remove encoder pipeline");
344                 return ret;
345         }
346
347         /* Remove pipeline message callback */
348         if (hstreamrecorder->encode_pipeline_cb_event_id != 0) {
349                 g_source_remove(hstreamrecorder->encode_pipeline_cb_event_id);
350                 hstreamrecorder->encode_pipeline_cb_event_id = 0;
351         }
352
353         _mmstreamrec_dbg_log("done");
354
355         return ret;
356 }
357
358 int _mmstreamrecorder_create_encodesink_bin(MMHandleType handle, MMStreamRecorderEncodebinProfile profile)
359 {
360         int err = MM_ERROR_NONE;
361         int result = 0;
362         int channel = 0;
363         int audio_enc = 0;
364         int video_enc = 0;
365         int v_bitrate = 0;
366         int a_bitrate = 0;
367         int video_width = 0;
368         int video_height = 0;
369         int video_fps = 0;
370         int file_format = 0;
371         int audio_src_format = 0;
372         int video_src_format = 0;
373         int audio_samplerate = 0;
374         const char *str_profile = NULL;
375         const char *str_aac = NULL;
376         const char *str_aar = NULL;
377         const char *str_acs = NULL;
378         char *err_name = NULL;
379
380         GstCaps *caps = NULL;
381         GstPad *pad = NULL;
382         GList *element_list = NULL;
383         char *temp_filename = NULL;
384         int fileformat = 0;
385         int size = 0;
386         guint imax_size = 0;
387         guint imax_time = 0;
388         int rec_mode = 0;
389
390         _MMStreamRecorderVideoInfo *info = NULL;
391         _MMStreamRecorderFileInfo *finfo = NULL;
392
393         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
394         _MMStreamRecorderSubContext *sc = NULL;
395         /* type_element *VideoencElement = NULL; */
396         /* type_element *AudioencElement = NULL; */
397         /* type_element *MuxElement = NULL; */
398         /* type_element *RecordsinkElement = NULL; */
399
400         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
401
402         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
403         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
404
405         _mmstreamrec_dbg_log("start - profile : %d", profile);
406
407         info = sc->info_video;
408         finfo = sc->info_file;
409
410         /* check element availability */
411         mm_streamrecorder_get_attributes(handle, &err_name, MMSTR_AUDIO_ENCODER, &audio_enc, MMSTR_AUDIO_CHANNEL, &channel, MMSTR_VIDEO_BITRATE, &v_bitrate, MMSTR_VIDEO_ENCODER, &video_enc, MMSTR_AUDIO_BITRATE, &a_bitrate, MMSTR_VIDEO_RESOLUTION_WIDTH, &video_width, MMSTR_VIDEO_RESOLUTION_HEIGHT, &video_height, MMSTR_VIDEO_FRAMERATE, &video_fps, MMSTR_FILE_FORMAT, &file_format, MMSTR_AUDIO_SAMPLERATE, &audio_samplerate, MMSTR_AUDIO_SOURCE_FORMAT, &audio_src_format, MMSTR_VIDEO_SOURCE_FORMAT, &video_src_format, MMSTR_RECORDER_MODE, &rec_mode, NULL);
412
413         _mmstreamrec_dbg_err("audio encoder - %d , video encoder : %d", audio_enc, video_enc);
414         _mmstreamrec_dbg_err("audio channel - %d , video v_bitrate : %d", channel, v_bitrate);
415         _mmstreamrec_dbg_err("audio a_bitrate - %d , video video_width : %d ,video video_height : %d ", a_bitrate, video_width, video_height);
416         _mmstreamrec_dbg_err("video_fps - %d , video file_format : %d", video_fps, file_format);
417
418         /* Check existence */
419         if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst) {
420                 if (((GObject *) sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst)->ref_count > 0)
421                         gst_object_unref(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst);
422
423                 _mmstreamrec_dbg_log("_MMSTREAMRECORDER_ENCSINK_BIN is Already existed.");
424         }
425
426         /* Create bin element */
427         _MMSTREAMRECORDER_BIN_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_BIN, "encodesink_bin", err);
428
429         /* Create child element */
430         if (hstreamrecorder->ini.encsink_bin_profile != MM_STREAMRECORDER_ENCBIN_PROFILE_AUDIO) {
431                 /* create appsrc and capsfilter */
432                 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SRC, hstreamrecorder->ini.name_of_encsink_src, "encodesink_src", element_list, err);
433                 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_FILT, "capsfilter", "encodesink_filter", element_list, err);
434
435                 caps = gst_set_videosrcpad_caps(video_src_format, video_width, video_height, video_fps, 1);
436                 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "caps", caps);
437                 if (caps) {
438                         gst_caps_unref(caps);
439                         caps = NULL;
440                 }
441
442                 caps = gst_set_videosrcpad_caps(video_src_format, video_width, video_height, video_fps, 1);
443                 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, "caps", caps);
444                 if (caps) {
445                         gst_caps_unref(caps);
446                         caps = NULL;
447                 }
448
449
450                 /* release element_list, they will be placed out of encodesink bin */
451                 if (element_list) {
452                         g_list_free(element_list);
453                         element_list = NULL;
454                 }
455                 if (rec_mode == MM_STREAMRECORDER_MODE_MEDIABUFFER) {
456                         /* set appsrc as live source */
457                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "is-live", hstreamrecorder->ini.encsink_src_islive);
458                 }
459
460         }
461
462         _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_ENCBIN, "encodebin", "encodesink_encbin", element_list, err);
463
464         _mmstreamrec_dbg_log("Profile[%d]", profile);
465
466         /* Set information */
467         if (hstreamrecorder->ini.encsink_bin_profile == MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO) {
468                 str_profile = "VideoProfile";
469                 str_aac = "VideoAutoAudioConvert";
470                 str_aar = "VideoAutoAudioResample";
471                 str_acs = "VideoAutoColorSpace";
472         } else if (hstreamrecorder->ini.encsink_bin_profile == MM_STREAMRECORDER_ENCBIN_PROFILE_AUDIO) {
473                 str_profile = "AudioProfile";
474                 str_aac = "AudioAutoAudioConvert";
475                 str_aar = "AudioAutoAudioResample";
476                 str_acs = "AudioAutoColorSpace";
477         }
478
479         /* TODO : check the last value ( set ) */
480         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "profile", hstreamrecorder->ini.encsink_bin_profile);
481         if (rec_mode == MM_STREAMRECORDER_MODE_MEDIABUFFER) {
482                 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", hstreamrecorder->ini.encsink_bin_auto_audio_convert);
483         }
484         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-resample", hstreamrecorder->ini.encsink_bin_auto_audio_resample);
485         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-colorspace", hstreamrecorder->ini.encsink_bin_auto_colorspace);
486         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "use-video-toggle", hstreamrecorder->ini.encsink_bin_use_video_toggle);
487
488         /* Codec */
489         if (hstreamrecorder->ini.encsink_bin_profile == MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO) {
490                 switch (video_enc) {
491                 case MM_VIDEO_CODEC_H263:
492                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "venc-name", hstreamrecorder->ini.h263_video_encoder);
493                         break;
494                 case MM_VIDEO_CODEC_H264:
495                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "venc-name", hstreamrecorder->ini.h264_video_encoder);
496                         break;
497                 case MM_VIDEO_CODEC_MPEG4:
498                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "venc-name", hstreamrecorder->ini.mpeg4_video_encoder);
499                         break;
500                 default:
501                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "venc-name", hstreamrecorder->ini.h264_video_encoder);
502                         break;
503                 }
504                 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_VENC, "video-encode", err);
505                 /* _mmstreamrec_dbg_err(" hyuntae log = %p sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst = %p" ,sc, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst); */
506
507
508                 /* set color converter size */
509                 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "vconv-name", hstreamrecorder->ini.name_of_encsink_bin_video_converter);
510                 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_VCONV, "video-convert", err);
511
512                 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-colorspace", hstreamrecorder->ini.encsink_bin_auto_colorspace);
513
514                 if (video_src_format == MM_STREAMRECORDER_INPUT_FORMAT_NV12) {
515                         video_src_format = MM_STREAMRECORDER_INPUT_FORMAT_I420;
516                 }
517                 caps = gst_set_videosrcpad_caps(video_src_format, video_width, video_height, video_fps, 1);
518                 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "vcaps", caps);
519                 if (video_src_format != MM_STREAMRECORDER_INPUT_FORMAT_NV12) {
520                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VCONV].gst, "dst-buffer-num", hstreamrecorder->ini.convert_output_buffer_num);
521                 }
522                 /* state tuning */
523                 err = gst_pad_set_caps(gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "sink"), caps);
524                 err = MM_ERROR_NONE;
525                 /* MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "state-tuning", TRUE); */
526
527                 if (caps) {
528                         gst_caps_unref(caps);
529                         caps = NULL;
530                 }
531                 _mmstreamrec_dbg_log("size %dx%d, dst-buffer-num %d", video_width, video_height, hstreamrecorder->ini.convert_output_buffer_num);
532
533                 _mmstreamrec_dbg_warn("encoder set caps result : 0x%x", err);
534
535                 if (hstreamrecorder->ini.encsink_bin_use_parser[0]) {
536                         GstElement *parser = gst_element_factory_make(hstreamrecorder->ini.encsink_bin_use_parser, "parse");
537                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "use-venc-queue", parser);
538                         _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_PARSER, "use-venc-queue", err);
539                 }
540         }
541
542         if (sc->audio_enable == TRUE) {
543
544                 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "aenc-name", hstreamrecorder->ini.name_of_encsink_bin_audio_encoder);
545                 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_AENC, "audio-encode", err);
546                 _mmstreamrec_dbg_err("audio-encode err = %x ", err);
547
548                 /* Set basic infomation */
549                 if (audio_enc != MM_AUDIO_CODEC_VORBIS) {
550                         int depth = 0;
551
552                         if (audio_src_format == MM_STREAMRECORDER_AUDIO_FORMAT_PCM_S16_LE) {
553                                 depth = 16;
554                         } else {                        /* MM_STREAMRECORDER_AUDIO_FORMAT_PCM_U8 */
555                                 depth = 8;
556                         }
557
558                         /* TODO : set rate , channel , depth */
559
560                         caps = gst_set_audiosrcpad_caps(audio_samplerate, 2, depth, 16, 1);
561                         /* MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE); */
562                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "acaps", caps);
563                         {
564                                 gchar *type = gst_caps_to_string(caps);
565
566                                 _mmstreamrec_dbg_warn("Set srcpad caps: %s", type);
567                         }
568                         gst_caps_unref(caps);
569                         caps = NULL;
570                 } else {
571                         /* what are the audio encoder which should get audio/x-raw-float? */
572                         caps = gst_caps_new_simple("audio/x-raw", "rate", G_TYPE_INT, audio_samplerate, "channels", G_TYPE_INT, channel, "endianness", G_TYPE_INT, BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
573                         _mmstreamrec_dbg_log("caps [x-raw-float, rate:%d, channel:%d, endianness:%d, width:32]", audio_samplerate, channel, BYTE_ORDER);
574                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE);
575                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "acaps", caps);
576                         gst_caps_unref(caps);
577                         caps = NULL;
578                 }
579
580 #if 0
581                 if (audio_enc == MM_AUDIO_CODEC_AMR && channel == 2) {
582                         caps = gst_caps_new_simple("audio/x-raw-int", "channels", G_TYPE_INT, 1, NULL);
583                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE);
584                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "acaps", caps);
585                         gst_caps_unref(caps);
586                         caps = NULL;
587                 }
588
589                 if (audio_enc == MM_AUDIO_CODEC_OGG) {
590                         caps = gst_caps_new_simple("audio/x-raw-int", NULL);
591                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE);
592                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "acaps", caps);
593                         gst_caps_unref(caps);
594                         caps = NULL;
595                 }
596 #endif
597
598                 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_AENC_QUE, "use-aenc-queue", err);
599         }
600
601         /* Mux */
602         switch (file_format) {
603         case MM_FILE_FORMAT_3GP:{
604                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "mux-name", hstreamrecorder->ini.name_of_encsink_bin_3GPMUXER);
605                 }
606                 break;
607
608         case MM_FILE_FORMAT_MP4:{
609                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "mux-name", hstreamrecorder->ini.name_of_encsink_bin_MP4MUXER);
610                 }
611                 break;
612
613         default:{
614                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "mux-name", hstreamrecorder->ini.name_of_encsink_bin_MP4MUXER);
615                 }
616                 break;
617
618         }
619         _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_MUX, "mux", err);
620
621         /* Sink */
622         /* for recording */
623         _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SINK, "filesink", NULL, element_list, err);
624         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SINK].gst, "async", 0);
625
626         err = mm_streamrecorder_get_attributes(handle, &err_name,
627                                                                                    MMSTR_FILE_FORMAT, &fileformat, MMSTR_FILENAME, &temp_filename, &size,
628                                                                                    MMSTR_TARGET_MAX_SIZE, &imax_size,
629                                                                                    MMSTR_TARGET_TIME_LIMIT, &imax_time,
630                                                                                    NULL);
631
632         if (err != MM_ERROR_NONE) {
633                 _mmstreamrec_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
634                 SAFE_FREE(err_name);
635                 return err;
636         }
637
638         finfo->fileformat = fileformat;
639
640         /* set max size */
641         if (imax_size <= 0)
642                 info->max_size = 0;             /* do not check */
643         else
644                 info->max_size = ((guint64) imax_size) << 10;   /* to byte */
645
646         /* set max time */
647         if (imax_time <= 0)
648                 info->max_time = 0;             /* do not check */
649         else
650                 info->max_time = ((guint64) imax_time) * 1000;  /* to millisecond */
651
652         finfo->filename = strdup(temp_filename);
653         if (!finfo->filename) {
654                 _mmstreamrec_dbg_err("strdup was failed");
655                 return err;
656         }
657
658         _mmstreamrec_dbg_log("Record start : set file name using attribute - %s ", finfo->filename);
659
660         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SINK].gst, "location", finfo->filename);
661
662         if (profile == MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO) {
663                 /* video encoder attribute setting */
664                 if (v_bitrate > 0) {
665                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "bitrate", v_bitrate);
666                 } else {
667                         _mmstreamrec_dbg_warn("video bitrate is too small[%d], so skip setting. Use DEFAULT value.", v_bitrate);
668                 }
669         }
670
671         if (sc->audio_enable == TRUE) {
672                 /* audio encoder attribute setting */
673                 if (a_bitrate > 0) {
674                         switch (audio_enc) {
675                         case MM_AUDIO_CODEC_AMR:
676                                 result = _mmstreamrecorder_get_amrnb_bitrate_mode(a_bitrate);
677                                 _mmstreamrec_dbg_log("Set AMR encoder mode [%d]", result);
678                                 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "band-mode", result);
679                                 break;
680                         case MM_AUDIO_CODEC_AAC:
681                                 _mmstreamrec_dbg_log("Set AAC encoder bitrate [%d]", a_bitrate);
682                                 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "bitrate", a_bitrate);
683                                 break;
684                         default:
685                                 _mmstreamrec_dbg_log("Audio codec is not AMR or AAC... you need to implement setting function for audio encoder bit-rate");
686                                 break;
687                         }
688                 } else {
689                         _mmstreamrec_dbg_warn("Setting bitrate is too small, so skip setting. Use DEFAULT value.");
690                 }
691         }
692
693         _mmstreamrec_dbg_log("Element creation complete");
694
695         /* Add element to bin */
696         if (!_mmstreamrecorder_add_elements_to_bin(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst), element_list)) {
697                 _mmstreamrec_dbg_err("element add error.");
698                 err = MM_ERROR_STREAMRECORDER_RESOURCE_CREATION;
699                 goto pipeline_creation_error;
700         }
701
702         _mmstreamrec_dbg_log("Element add complete");
703
704         if (profile == MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO) {
705                 pad = gst_element_get_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "video");
706                 if (gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("video_sink0", pad)) < 0) {
707                         gst_object_unref(pad);
708                         pad = NULL;
709                         _mmstreamrec_dbg_err("failed to create ghost video_sink0 on _MMSTREAMRECORDER_ENCSINK_BIN.");
710                         err = MM_ERROR_STREAMRECORDER_GST_LINK;
711                         goto pipeline_creation_error;
712                 }
713                 gst_object_unref(pad);
714                 pad = NULL;
715
716                 if (sc->audio_enable == TRUE) {
717                         pad = gst_element_get_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "audio");
718                         if (gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("audio_sink0", pad)) < 0) {
719                                 gst_object_unref(pad);
720                                 pad = NULL;
721                                 _mmstreamrec_dbg_err("failed to create ghost audio_sink0 on _MMSTREAMRECORDER_ENCSINK_BIN.");
722                                 err = MM_ERROR_STREAMRECORDER_GST_LINK;
723                                 goto pipeline_creation_error;
724                         }
725                         gst_object_unref(pad);
726                         pad = NULL;
727                 }
728         } else if (profile == MM_STREAMRECORDER_ENCBIN_PROFILE_AUDIO) {
729                 pad = gst_element_get_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "audio");
730                 if (gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("audio_sink0", pad)) < 0) {
731                         gst_object_unref(pad);
732                         pad = NULL;
733                         _mmstreamrec_dbg_err("failed to create ghost audio_sink0 on _MMSTREAMRECORDER_ENCSINK_BIN.");
734                         err = MM_ERROR_STREAMRECORDER_GST_LINK;
735                         goto pipeline_creation_error;
736                 }
737                 gst_object_unref(pad);
738                 pad = NULL;
739         } else {
740                 /* for stillshot */
741                 pad = gst_element_get_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "image");
742                 if (gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("image_sink0", pad)) < 0) {
743                         gst_object_unref(pad);
744                         pad = NULL;
745                         _mmstreamrec_dbg_err("failed to create ghost image_sink0 on _MMSTREAMRECORDER_ENCSINK_BIN.");
746                         err = MM_ERROR_STREAMRECORDER_GST_LINK;
747                         goto pipeline_creation_error;
748                 }
749                 gst_object_unref(pad);
750                 pad = NULL;
751         }
752
753         _mmstreamrec_dbg_log("Get pad complete");
754
755         /* Link internal element */
756         if (!_mmstreamrecorder_link_elements(element_list)) {
757                 _mmstreamrec_dbg_err("element link error.");
758                 err = MM_ERROR_STREAMRECORDER_GST_LINK;
759                 goto pipeline_creation_error;
760         }
761
762         if (element_list) {
763                 g_list_free(element_list);
764                 element_list = NULL;
765         }
766
767         _mmstreamrec_dbg_log("done");
768
769         return MM_ERROR_NONE;
770
771  pipeline_creation_error:
772         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_ENCBIN);
773         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SRC);
774         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_FILT);
775         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_VENC);
776         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_AENC);
777         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_IENC);
778         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_MUX);
779         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SINK);
780         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_BIN);
781
782         if (element_list) {
783                 g_list_free(element_list);
784                 element_list = NULL;
785         }
786
787         return err;
788 }
789
790 int _mmstreamrecorder_destroy_encodesink_bin(MMHandleType handle)
791 {
792         GstPad *reqpad = NULL;
793         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
794         _MMStreamRecorderSubContext *sc = NULL;
795
796         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
797
798         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
799         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
800
801         _mmstreamrec_dbg_log("");
802
803         if (sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst != NULL) {
804                 /* release request pad */
805                 reqpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "audio");
806                 if (reqpad) {
807                         gst_element_release_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, reqpad);
808                         gst_object_unref(reqpad);
809                         reqpad = NULL;
810                 }
811
812                 reqpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "video");
813                 if (reqpad) {
814                         gst_element_release_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, reqpad);
815                         gst_object_unref(reqpad);
816                         reqpad = NULL;
817                 }
818
819                 /* release encode main pipeline */
820                 gst_object_unref(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst);
821
822                 _mmstreamrec_dbg_log("Encoder pipeline removed");
823         }
824
825         return MM_ERROR_NONE;
826 }
827
828 int _mmstreamrecorder_create_audiosrc_bin(MMHandleType handle)
829 {
830         int err = MM_ERROR_NONE;
831         int val = 0;
832         int rate = 0;
833         int format = 0;
834         int channel = 0;
835         unsigned int a_enc = MM_AUDIO_CODEC_INVALID;
836         unsigned int file_format = MM_FILE_FORMAT_INVALID;
837         char *err_name = NULL;
838         int rec_mode = 0;
839
840         GstCaps *caps = NULL;
841         GstPad *pad = NULL;
842         GList *element_list = NULL;
843
844         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
845         _MMStreamRecorderSubContext *sc = NULL;
846         _MMStreamRecorderGstElement *last_element = NULL;
847         /* type_element *AudiosrcElement = NULL; */
848
849         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
850
851         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
852         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
853
854         _mmstreamrec_dbg_log("");
855
856         err = mm_streamrecorder_get_attributes(handle, &err_name, MMSTR_AUDIO_ENCODER, &a_enc, MMSTR_AUDIO_BITRATE, &val, MMSTR_AUDIO_SAMPLERATE, &rate, MMSTR_AUDIO_SOURCE_FORMAT, &format, MMSTR_AUDIO_CHANNEL, &channel, MMSTR_FILE_FORMAT, &file_format, MMSTR_RECORDER_MODE, &rec_mode, NULL);
857
858         if (err != MM_ERROR_NONE) {
859                 _mmstreamrec_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
860                 SAFE_FREE(err_name);
861                 return err;
862         }
863
864         err = _mmstreamrecorder_check_audiocodec_fileformat_compatibility(a_enc, file_format);
865         if (err != MM_ERROR_NONE) {
866                 _mmstreamrec_dbg_err("error name :%s , audio format %d , fileformat %d. error : %x)", err_name, a_enc, file_format, err);
867                 SAFE_FREE(err_name);
868                 return err;
869         }
870
871         /* Check existence */
872         if (sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst) {
873                 if (((GObject *) sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst)->ref_count > 0)
874                         gst_object_unref(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst);
875
876                 _mmstreamrec_dbg_log("_MMSTREAMRECORDER_AUDIOSRC_BIN is Already existed. Unref once...");
877         }
878
879         /* Create bin element */
880         _MMSTREAMRECORDER_BIN_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_BIN, "audiosource_bin", err);
881
882         _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_SRC, "appsrc", hstreamrecorder->ini.name_of_audio_src, element_list, err);
883
884         _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_FILT, "capsfilter", "audiosrc_capsfilter", element_list, err);
885
886         /* Set basic infomation */
887         if (a_enc != MM_AUDIO_CODEC_VORBIS) {
888                 int depth = 0;
889
890                 if (format == MM_STREAMRECORDER_AUDIO_FORMAT_PCM_S16_LE) {
891                         depth = 16;
892                 } else {                                /* MM_STREAMRECORDER_AUDIO_FORMAT_PCM_U8 */
893                         depth = 8;
894                 }
895
896                 caps = gst_set_audiosrcpad_caps(rate, channel, depth, 16, 1);
897
898                 _mmstreamrec_dbg_log("caps [x-raw-int, rate:%d, channel:%d, depth:%d]", rate, channel, depth);
899         } else {
900                 /* what are the audio encoder which should get audio/x-raw-float? */
901                 caps = gst_caps_new_simple("audio/x-raw-float", "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, channel, "endianness", G_TYPE_INT, BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
902                 _mmstreamrec_dbg_log("caps [x-raw-float, rate:%d, channel:%d, endianness:%d, width:32]", rate, channel, BYTE_ORDER);
903         }
904
905         if (caps) {
906                 if (rec_mode == MM_STREAMRECORDER_MODE_MEDIABUFFER) {
907                         MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "caps", caps);
908                 }
909                 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_FILT].gst), "caps", caps);
910                 {
911                         gchar *type = gst_caps_to_string(caps);
912
913                         _mmstreamrec_dbg_err("_MMSTREAMRECORDER_AUDIOSRC_FILT %s", type);
914
915                 }
916                 gst_caps_unref(caps);
917                 caps = NULL;
918         } else {
919                 _mmstreamrec_dbg_err("create caps error");
920                 err = MM_ERROR_STREAMRECORDER_RESOURCE_CREATION;
921                 goto pipeline_creation_error;
922         }
923
924         if (rec_mode == MM_STREAMRECORDER_MODE_SCREENRECORD) {
925 #if 1                                                   /* mic mode */
926                 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "do-timestamp", TRUE);
927 #else                                                   /* speaker mode with alsasrc */
928                 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "device", "hw:0,8");
929                 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "latency-time", 256000);
930                 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "buffer-time", 10000);
931                 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "do-timestamp", FALSE);
932 #endif
933         } else {
934                 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "do-timestamp", FALSE);
935         }
936
937         if (!_mmstreamrecorder_add_elements_to_bin(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst), element_list)) {
938                 _mmstreamrec_dbg_err("element add error.");
939                 err = MM_ERROR_STREAMRECORDER_RESOURCE_CREATION;
940                 goto pipeline_creation_error;
941         }
942
943         if (!_mmstreamrecorder_link_elements(element_list)) {
944                 _mmstreamrec_dbg_err("element link error.");
945                 err = MM_ERROR_STREAMRECORDER_GST_LINK;
946                 goto pipeline_creation_error;
947         }
948
949         last_element = (_MMStreamRecorderGstElement *) (g_list_last(element_list)->data);
950         pad = gst_element_get_static_pad(last_element->gst, "src");
951         if ((gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, gst_ghost_pad_new("src", pad))) < 0) {
952                 gst_object_unref(pad);
953                 pad = NULL;
954                 _mmstreamrec_dbg_err("failed to create ghost pad on _MMSTREAMRECORDER_AUDIOSRC_BIN.");
955                 err = MM_ERROR_STREAMRECORDER_GST_LINK;
956                 goto pipeline_creation_error;
957         }
958
959         gst_object_unref(pad);
960         pad = NULL;
961
962         if (element_list) {
963                 g_list_free(element_list);
964                 element_list = NULL;
965         }
966
967         return MM_ERROR_NONE;
968
969  pipeline_creation_error:
970         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_SRC);
971         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_FILT);
972         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_BIN);
973
974         if (element_list) {
975                 g_list_free(element_list);
976                 element_list = NULL;
977         }
978
979         return err;
980 }
981
982 int _mmstreamrecorder_destroy_audiosrc_bin(MMHandleType handle)
983 {
984         GstPad *srcpad = NULL;
985         GstPad *sinkpad = NULL;
986         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
987         _MMStreamRecorderSubContext *sc = NULL;
988
989         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
990
991         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
992         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
993
994         _mmstreamrec_dbg_log("");
995
996         if (sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst != NULL) {
997                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, "src");
998                 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, "audio_sink0");
999                 _MM_GST_PAD_UNLINK_UNREF(srcpad, sinkpad);
1000
1001                 /* release audiosrc bin */
1002                 gst_bin_remove(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst);
1003
1004                 _mmstreamrecorder_remove_element_handle(handle, (void *)sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_BIN, _MMSTREAMRECORDER_AUDIOSRC_FILT);
1005
1006                 _mmstreamrec_dbg_log("Audio pipeline removed");
1007         }
1008
1009         return MM_ERROR_NONE;
1010 }
1011
1012 /* COMMAND - VIDEO */
1013 int _mmstreamrecorder_video_command(MMHandleType handle, int command)
1014 {
1015         int ret = MM_ERROR_NONE;
1016         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1017         _MMStreamRecorderVideoInfo *info = NULL;
1018         _MMStreamRecorderAudioInfo *info_audio = NULL;
1019         _MMStreamRecorderFileInfo *finfo = NULL;
1020         _MMStreamRecorderSubContext *sc = NULL;
1021         GstElement *pipeline = NULL;
1022         GstPad *pad = NULL;
1023         guint count = 0;
1024
1025         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1026
1027         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1028         mmf_return_val_if_fail(sc && sc->encode_element, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1029
1030         mmf_return_val_if_fail(sc->info_video, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1031         if (sc->audio_enable == TRUE) {
1032                 mmf_return_val_if_fail(sc->info_audio, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1033         }
1034         mmf_return_val_if_fail(sc->info_file, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1035
1036         info = sc->info_video;
1037         if (sc->audio_enable == TRUE)
1038                 info_audio = sc->info_audio;
1039
1040         finfo = sc->info_file;
1041
1042         _mmstreamrec_dbg_log("command %d", command);
1043
1044         pipeline = sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst;
1045
1046         switch (command) {
1047         case _MM_STREAMRECORDER_CMD_RECORD:
1048                 {
1049
1050                         /* Recording */
1051                         _mmstreamrec_dbg_log("Record Start");
1052                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1053
1054                         /* Adjust display FPS */
1055                         info->video_frame_count = 0;
1056                         if (info_audio)
1057                                 info_audio->audio_frame_count = 0;
1058
1059                         info->filesize = 0;
1060                         sc->ferror_send = FALSE;
1061                         sc->ferror_count = 0;
1062                         sc->error_occurs = FALSE;
1063                         sc->bget_eos = FALSE;
1064
1065                         ret = _mmstreamrecorder_gst_set_state(handle, sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PLAYING);
1066                         if (ret != MM_ERROR_NONE) {
1067                                 /* Remove recorder pipeline and recording file which size maybe zero */
1068                                 ret = _mmstreamrecorder_destroy_recorder_pipeline(handle);
1069
1070                                 if (finfo->filename) {
1071                                         _mmstreamrec_dbg_log("file delete(%s)", finfo->filename);
1072                                         unlink(finfo->filename);
1073                                         g_free(finfo->filename);
1074                                         finfo->filename = NULL;
1075                                 }
1076                                 goto _ERR_STREAMRECORDER_VIDEO_COMMAND;
1077                         }
1078
1079                 }
1080                 break;
1081         case _MM_STREAMRECORDER_CMD_PAUSE:
1082                 {
1083
1084                         if (info->b_commiting) {
1085                                 _mmstreamrec_dbg_warn("now on commiting previous file!!(command : %d)", command);
1086                                 return MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING;
1087                         }
1088
1089                         for (count = 0; count <= hstreamrecorder->ini.retrial_count; count++) {
1090                                 if (sc->audio_enable == FALSE) {
1091                                         /* check only video frame */
1092                                         if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame) {
1093                                                 break;
1094                                         } else if (count == hstreamrecorder->ini.retrial_count) {
1095                                                 _mmstreamrec_dbg_err("Pause fail, frame count %" G_GUINT64_FORMAT "", info->video_frame_count);
1096                                                 return MM_ERROR_STREAMRECORDER_INVALID_CONDITION;
1097                                         } else {
1098                                                 _mmstreamrec_dbg_warn("Waiting for enough video frame, retrial[%d], frame %" G_GUINT64_FORMAT "", count, info->video_frame_count);
1099                                         }
1100
1101                                         usleep(hstreamrecorder->ini.video_frame_wait_time);
1102                                 } else {
1103                                         /* check both of video and audio frame */
1104                                         if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame && info_audio->audio_frame_count) {
1105                                                 break;
1106                                         } else if (count == hstreamrecorder->ini.retrial_count) {
1107                                                 _mmstreamrec_dbg_err("Pause fail, frame count VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]", info->video_frame_count, info_audio->audio_frame_count);
1108                                                 return MM_ERROR_STREAMRECORDER_INVALID_CONDITION;
1109                                         } else {
1110                                                 _mmstreamrec_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]", count, info->video_frame_count, info_audio->audio_frame_count);
1111                                         }
1112
1113                                         usleep(hstreamrecorder->ini.video_frame_wait_time);
1114                                 }
1115                         }
1116                         /* tee block */
1117                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "runtime-pause", TRUE);
1118
1119                         break;
1120                 }
1121                 break;
1122         case _MM_STREAMRECORDER_CMD_CANCEL:
1123                 {
1124                         if (info->b_commiting) {
1125                                 _mmstreamrec_dbg_warn("now on commiting previous file!!(command : %d)", command);
1126                                 return MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING;
1127                         }
1128
1129                         ret = _mmstreamrecorder_destroy_recorder_pipeline(handle);
1130                         if (ret != MM_ERROR_NONE)
1131                                 goto _ERR_STREAMRECORDER_VIDEO_COMMAND;
1132
1133                         /* remove target file */
1134                         if (finfo->filename) {
1135                                 _mmstreamrec_dbg_log("file delete(%s)", finfo->filename);
1136                                 unlink(finfo->filename);
1137                                 g_free(finfo->filename);
1138                                 finfo->filename = NULL;
1139                         }
1140
1141                         sc->isMaxsizePausing = FALSE;
1142                         sc->isMaxtimePausing = FALSE;
1143
1144                         info->video_frame_count = 0;
1145                         if (info_audio)
1146                                 info_audio->audio_frame_count = 0;
1147
1148                         info->filesize = 0;
1149                         break;
1150                 }
1151                 break;
1152         case _MM_STREAMRECORDER_CMD_COMMIT:
1153                 /* video recording command */
1154                 {
1155
1156                         if (info->b_commiting) {
1157                                 _mmstreamrec_dbg_err("now on commiting previous file!!(command : %d)", command);
1158                                 return MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING;
1159                         } else {
1160                                 _mmstreamrec_dbg_log("_MM_STREAMRECORDER_CMD_COMMIT : start");
1161                                 info->b_commiting = TRUE;
1162                         }
1163
1164                         for (count = 0; count <= hstreamrecorder->ini.retrial_count; count++) {
1165                                 if (sc->audio_enable == FALSE) {
1166                                         /* check only video frame */
1167                                         if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame) {
1168                                                 break;
1169                                         } else if (count == hstreamrecorder->ini.retrial_count) {
1170                                                 _mmstreamrec_dbg_err("Commit fail, frame count is %" G_GUINT64_FORMAT "", info->video_frame_count);
1171                                                 info->b_commiting = FALSE;
1172                                                 return MM_ERROR_STREAMRECORDER_INVALID_CONDITION;
1173                                         } else {
1174                                                 _mmstreamrec_dbg_warn("Waiting for enough video frame, retrial [%d], frame %" G_GUINT64_FORMAT "", count, info->video_frame_count);
1175                                         }
1176
1177                                         usleep(hstreamrecorder->ini.video_frame_wait_time);
1178                                 } else {
1179                                         /* check both of video and audio frame */
1180                                         if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame && info_audio->audio_frame_count) {
1181                                                 break;
1182                                         } else if (count == hstreamrecorder->ini.retrial_count) {
1183                                                 _mmstreamrec_dbg_err("Commit fail, VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]", info->video_frame_count, info_audio->audio_frame_count);
1184
1185                                                 info->b_commiting = FALSE;
1186                                                 return MM_ERROR_STREAMRECORDER_INVALID_CONDITION;
1187                                         } else {
1188                                                 _mmstreamrec_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]", count, info->video_frame_count, info_audio->audio_frame_count);
1189                                         }
1190
1191                                         usleep(hstreamrecorder->ini.video_frame_wait_time);
1192                                 }
1193                         }
1194
1195                         if (sc->error_occurs) {
1196                                 GstPad *video = NULL;
1197                                 GstPad *audio = NULL;
1198
1199                                 _mmstreamrec_dbg_err("Committing Error case");
1200 #if 0
1201                                 video = gst_element_get_static_pad(sc->element[_MMSTREAMRECORDER_VIDEOSINK_SINK].gst, "sink");
1202                                 ret = gst_pad_send_event(video, gst_event_new_eos());
1203                                 _mmstreamrec_dbg_err("Sending EOS video sink  : %d", ret);
1204                                 gst_object_unref(video);
1205 #endif
1206                                 video = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "src");
1207                                 gst_pad_push_event(video, gst_event_new_flush_start());
1208                                 gst_pad_push_event(video, gst_event_new_flush_stop(TRUE));
1209                                 ret = gst_pad_push_event(video, gst_event_new_eos());
1210                                 _mmstreamrec_dbg_err("Sending EOS video encoder src pad  : %d", ret);
1211                                 gst_object_unref(video);
1212
1213                                 if (sc->audio_enable == TRUE) {
1214                                         audio = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "src");
1215                                         gst_pad_push_event(audio, gst_event_new_flush_start());
1216                                         gst_pad_push_event(audio, gst_event_new_flush_stop(TRUE));
1217                                         ret = gst_element_send_event(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, gst_event_new_eos());
1218                                         _mmstreamrec_dbg_err("Sending EOS audio encoder src pad  : %d", ret);
1219                                         gst_object_unref(audio);
1220                                 }
1221                         } else {
1222                                 if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst != NULL) {
1223                                         ret = gst_element_send_event(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, gst_event_new_eos());
1224                                         _mmstreamrec_dbg_warn("send eos to appsrc result : %d", ret);
1225                                 }
1226
1227                                 if (sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst != NULL) {
1228                                         pad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, "src");
1229                                         ret = gst_element_send_event(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, gst_event_new_eos());
1230                                         gst_object_unref(pad);
1231                                         pad = NULL;
1232
1233                                         _mmstreamrec_dbg_warn("send eos to audiosrc result : %d", ret);
1234                                 }
1235                         }
1236
1237                         /* Wait EOS */
1238                         _mmstreamrec_dbg_log("Start to wait EOS");
1239                         ret = _mmstreamrecorder_get_eos_message(handle);
1240                         if (ret != MM_ERROR_NONE) {
1241                                 info->b_commiting = FALSE;
1242                                 goto _ERR_STREAMRECORDER_VIDEO_COMMAND;
1243                         }
1244                 }
1245                 break;
1246         default:
1247                 ret = MM_ERROR_STREAMRECORDER_INVALID_ARGUMENT;
1248                 break;
1249         }
1250         return MM_ERROR_NONE;
1251
1252  _ERR_STREAMRECORDER_VIDEO_COMMAND:
1253         if (ret != MM_ERROR_NONE)
1254                 _mmstreamrec_dbg_err("Current Videosrc status");
1255
1256         return ret;
1257 }
1258
1259 int _mmstreamrecorder_video_handle_eos(MMHandleType handle)
1260 {
1261         int ret = MM_ERROR_NONE;
1262
1263         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1264         _MMStreamRecorderSubContext *sc = NULL;
1265         _MMStreamRecorderVideoInfo *info = NULL;
1266         _MMStreamRecorderAudioInfo *info_audio = NULL;
1267         _MMStreamRecorderFileInfo *finfo = NULL;
1268         _MMStreamRecorderMsgItem msg;
1269         MMStreamRecordingReport *report = NULL;
1270
1271         mmf_return_val_if_fail(hstreamrecorder, FALSE);
1272
1273         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1274         mmf_return_val_if_fail(sc, FALSE);
1275         mmf_return_val_if_fail(sc->info_video, FALSE);
1276         if (sc->audio_enable == TRUE)
1277                 mmf_return_val_if_fail(sc->info_audio, FALSE);
1278
1279         mmf_return_val_if_fail(sc->info_file, FALSE);
1280
1281         info = sc->info_video;
1282         if (sc->audio_enable == TRUE)
1283                 info_audio = sc->info_audio;
1284
1285         finfo = sc->info_file;
1286
1287         _mmstreamrec_dbg_err("");
1288
1289         /* remove blocking part */
1290         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1291
1292         ret = _mmstreamrecorder_destroy_recorder_pipeline(handle);
1293         if (ret != MM_ERROR_NONE)
1294                 _mmstreamrec_dbg_warn("_mmstreamrecorder_destroy_recorder_pipeline failed. error[%x]", ret);
1295
1296         /* Send recording report to application */
1297         msg.id = MM_MESSAGE_STREAMRECORDER_VIDEO_CAPTURED;
1298         report = (MMStreamRecordingReport *) malloc(sizeof(MMStreamRecordingReport));
1299         if (!report) {
1300                 _mmstreamrec_dbg_err("Recording report fail(%s). Out of memory.", finfo->filename);
1301         } else {
1302                 report->recording_filename = strdup(finfo->filename);
1303                 msg.param.data = report;
1304                 msg.param.code = 1;
1305                 _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1306         }
1307
1308         /* Finishing */
1309         sc->pipeline_time = 0;
1310         sc->pause_time = 0;
1311         sc->isMaxsizePausing = FALSE;   /*In async function, this variable should set in callback function. */
1312         sc->isMaxtimePausing = FALSE;
1313         sc->error_occurs = FALSE;
1314
1315         info->video_frame_count = 0;
1316         if (info_audio)
1317                 info_audio->audio_frame_count = 0;
1318
1319         info->filesize = 0;
1320         g_free(finfo->filename);
1321         finfo->filename = NULL;
1322         info->b_commiting = FALSE;
1323
1324         _mmstreamrec_dbg_err("_mmstreamrecorder_video_handle_eos : end");
1325
1326         return TRUE;
1327 }
1328
1329 /* AUDIO */
1330
1331 int _mmstreamrecorder_create_audio_pipeline(MMHandleType handle)
1332 {
1333         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1334         _MMStreamRecorderSubContext *sc = NULL;
1335
1336         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1337         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1338
1339         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1340
1341         return _mmstreamrecorder_create_audiop_with_encodebin(handle);
1342 }
1343
1344 /**
1345  * This function destroy audio pipeline.
1346  *
1347  * @param[in]   handle          Handle of streamrecorder.
1348  * @return      void
1349  * @remarks
1350  * @see         _mmstreamrecorder_destroy_audio_pipeline()
1351  *
1352  */
1353 void _mmstreamrecorder_destroy_audio_pipeline(MMHandleType handle)
1354 {
1355         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1356         _MMStreamRecorderSubContext *sc = NULL;
1357         _MMStreamRecorderAudioInfo *info = NULL;
1358         mmf_return_if_fail(hstreamrecorder);
1359         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1360
1361         mmf_return_if_fail(sc && sc->info_audio);
1362
1363         info = sc->info_audio;
1364
1365         _mmstreamrec_dbg_log("start");
1366
1367         if (sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst) {
1368                 _mmstreamrec_dbg_warn("release audio pipeline");
1369
1370                 _mmstreamrecorder_gst_set_state(handle, sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_NULL);
1371
1372                 _mmstreamrecorder_remove_all_handlers((MMHandleType) hstreamrecorder, _MMSTREAMRECORDER_HANDLER_CATEGORY_ALL);
1373
1374                 if (info->bMuxing) {
1375                         GstPad *reqpad = NULL;
1376                         /* FIXME:
1377                            Release request pad
1378                            The ref_count of mux is always # of streams in here, i don't know why it happens.
1379                            So, i unref the mux manually
1380                          */
1381                         reqpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "audio");
1382                         gst_element_release_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, reqpad);
1383                         gst_object_unref(reqpad);
1384
1385                         if (GST_IS_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_MUX].gst) && GST_OBJECT_REFCOUNT(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_MUX].gst) > 1) {
1386                                 gst_object_unref(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_MUX].gst);
1387                         }
1388                 }
1389                 gst_object_unref(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst);
1390         }
1391
1392         _mmstreamrec_dbg_log("done");
1393
1394         return;
1395 }
1396
1397 int _mmstreamrecorder_create_audiop_with_encodebin(MMHandleType handle)
1398 {
1399         int err = MM_ERROR_NONE;
1400         char *aenc_name = NULL;
1401         char *mux_name = NULL;
1402         char *err_name = NULL;
1403         int rec_mode = 0;
1404
1405         GstBus *bus = NULL;
1406         GstPad *srcpad = NULL;
1407         GstPad *sinkpad = NULL;
1408         GList *element_list = NULL;
1409
1410         _MMStreamRecorderAudioInfo *info = NULL;
1411         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1412         _MMStreamRecorderSubContext *sc = NULL;
1413         /* type_element *aenc_elem = NULL; */
1414         /* type_element *mux_elem = NULL; */
1415
1416         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1417         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1418
1419         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1420         mmf_return_val_if_fail(sc->info_audio, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1421
1422         info = (_MMStreamRecorderAudioInfo *) sc->info_audio;
1423
1424         _mmstreamrec_dbg_log("");
1425
1426         err = mm_streamrecorder_get_attributes(handle, &err_name, MMSTR_RECORDER_MODE, &rec_mode, NULL);
1427
1428         if (!mux_name || !strcmp(mux_name, "wavenc")) {
1429                 /* IF MUX in not chosen then record in raw file */
1430                 _mmstreamrec_dbg_log("Record without muxing.");
1431                 info->bMuxing = FALSE;
1432         } else {
1433                 _mmstreamrec_dbg_log("Record with mux.");
1434                 info->bMuxing = TRUE;
1435         }
1436
1437         /* Create GStreamer pipeline */
1438         _MMSTREAMRECORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCODE_MAIN_PIPE, "recorder_pipeline", err);
1439
1440         err = _mmstreamrecorder_create_audiosrc_bin(handle);
1441         if (err != MM_ERROR_NONE)
1442                 return err;
1443
1444         if (info->bMuxing) {
1445                 /* Muxing. can use encodebin. */
1446                 err = _mmstreamrecorder_create_encodesink_bin((MMHandleType) hstreamrecorder, MM_STREAMRECORDER_ENCBIN_PROFILE_AUDIO);
1447                 if (err != MM_ERROR_NONE)
1448                         return err;
1449
1450         } else {
1451                 /* without muxing. can't use encodebin. */
1452
1453                 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_AQUE, "queue", NULL, element_list, err);
1454
1455                 if (rec_mode == MM_STREAMRECORDER_MODE_MEDIABUFFER) {
1456                         if (strcmp(hstreamrecorder->ini.name_of_encsink_bin_audio_encoder, "wavenc") != 0) {
1457                                 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_CONV, "audioconvert", NULL, element_list, err);
1458                         }
1459                 }
1460
1461                 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_AENC, aenc_name, NULL, element_list, err);
1462
1463                 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SINK, hstreamrecorder->ini.name_of_encsink_sink, NULL, element_list, err);
1464         }
1465
1466         /* Add and link elements */
1467         if (info->bMuxing) {
1468                 /* IF MUX is indicated create MUX */
1469                 gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, NULL);
1470
1471                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, "src");
1472                 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, "audio_sink0");
1473                 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
1474         } else {
1475                 /* IF MUX in not chosen then record in raw amr file */
1476                 if (!strcmp(aenc_name, "wavenc")) {
1477                         gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AQUE].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SINK].gst, NULL);
1478
1479                         if (!_MM_GST_ELEMENT_LINK_MANY(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AQUE].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SINK].gst, NULL)) {
1480                                 err = MM_ERROR_STREAMRECORDER_GST_LINK;
1481                                 goto pipeline_creation_error;
1482                         }
1483                 } else {
1484                         if (rec_mode == MM_STREAMRECORDER_MODE_MEDIABUFFER) {
1485                                 gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AQUE].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_CONV].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SINK].gst, NULL);
1486
1487                                 if (!_MM_GST_ELEMENT_LINK_MANY(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AQUE].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_CONV].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SINK].gst, NULL)) {
1488                                         err = MM_ERROR_STREAMRECORDER_GST_LINK;
1489                                         goto pipeline_creation_error;
1490                                 }
1491                         } else {
1492                                 gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AQUE].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SINK].gst, NULL);
1493
1494                                 if (!_MM_GST_ELEMENT_LINK_MANY(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AQUE].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SINK].gst, NULL)) {
1495                                         err = MM_ERROR_STREAMRECORDER_GST_LINK;
1496                                         goto pipeline_creation_error;
1497                                 }
1498                         }
1499                 }
1500         }
1501
1502         if (info->bMuxing) {
1503                 MMSTREAMRECORDER_SIGNAL_CONNECT(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_MUX].gst, _MMSTREAMRECORDER_HANDLER_AUDIOREC, "pad-added", __mmstreamrecorder_audiorec_pad_added_cb, hstreamrecorder);
1504         } else {
1505                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "src");
1506                 MMSTREAMRECORDER_ADD_BUFFER_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_AUDIOREC, __mmstreamrecorder_audio_dataprobe_record, hstreamrecorder);
1507                 gst_object_unref(srcpad);
1508                 srcpad = NULL;
1509         }
1510
1511         bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst));
1512
1513         /* register message callback  */
1514         hstreamrecorder->pipeline_cb_event_id = gst_bus_add_watch(bus, (GstBusFunc) _mmstreamrecorder_pipeline_cb_message, hstreamrecorder);
1515
1516         /* set sync callback */
1517         gst_bus_set_sync_handler(bus, gst_bus_sync_signal_handler, hstreamrecorder, NULL);
1518
1519         gst_object_unref(bus);
1520         bus = NULL;
1521
1522         if (element_list) {
1523                 g_list_free(element_list);
1524                 element_list = NULL;
1525         }
1526
1527         return MM_ERROR_NONE;
1528
1529  pipeline_creation_error:
1530         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCODE_MAIN_PIPE);
1531         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_BIN);
1532         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_AQUE);
1533         if (rec_mode == MM_STREAMRECORDER_MODE_MEDIABUFFER) {
1534                 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_CONV);
1535         }
1536         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_AENC);
1537         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SINK);
1538         _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_BIN);
1539
1540         if (element_list) {
1541                 g_list_free(element_list);
1542                 element_list = NULL;
1543         }
1544
1545         return err;
1546 }
1547
1548 int _mmstreamrecorder_audio_command(MMHandleType handle, int command)
1549 {
1550         int cmd = command;
1551         int ret = MM_ERROR_NONE;
1552         int err = 0;
1553         guint64 free_space = 0;
1554         guint64 cal_space = 0;
1555         char *dir_name = NULL;
1556         char *err_attr_name = NULL;
1557         guint count = 0;
1558         int size = 0;
1559
1560         GstElement *pipeline = NULL;
1561         GstElement *audioSrc = NULL;
1562
1563         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1564         _MMStreamRecorderSubContext *sc = NULL;
1565         _MMStreamRecorderAudioInfo *info = NULL;
1566         _MMStreamRecorderFileInfo *finfo = NULL;
1567
1568         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1569         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1570
1571         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1572         mmf_return_val_if_fail(sc->info_audio, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1573         mmf_return_val_if_fail(sc->info_file, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1574         pipeline = sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst;
1575         info = sc->info_audio;
1576         finfo = sc->info_file;
1577
1578         _mmstreamrec_dbg_log("");
1579
1580         pipeline = sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst;
1581         audioSrc = sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst;
1582         switch (cmd) {
1583         case _MM_STREAMRECORDER_CMD_RECORD:
1584                 /* check status for resume case */
1585                 {
1586                         guint imax_size = 0;
1587                         guint imax_time = 0;
1588                         char *temp_filename = NULL;
1589
1590                         if (sc->pipeline_time)
1591                                 gst_element_set_start_time((GstElement *) GST_PIPELINE(pipeline), sc->pipeline_time);
1592
1593                         sc->pipeline_time = hstreamrecorder->ini.reset_pause_time;
1594
1595                         ret = mm_streamrecorder_get_attributes(handle, &err_attr_name, MMSTR_TARGET_MAX_SIZE, &imax_size, MMSTR_TARGET_TIME_LIMIT, &imax_time, MMSTR_FILE_FORMAT, &(finfo->fileformat), MMSTR_FILENAME, &temp_filename, &size, NULL);
1596                         if (ret != MM_ERROR_NONE) {
1597                                 _mmstreamrec_dbg_warn("failed to get attribute. (%s:%x)", err_attr_name, ret);
1598                                 SAFE_FREE(err_attr_name);
1599                                 goto _ERR_STREAMRECORDER_AUDIO_COMMAND;
1600                         }
1601
1602                         finfo->filename = strdup(temp_filename);
1603                         if (!finfo->filename) {
1604                                 _mmstreamrec_dbg_err("STRDUP was failed");
1605                                 goto _ERR_STREAMRECORDER_AUDIO_COMMAND;
1606                         }
1607
1608                         _mmstreamrec_dbg_log("Record start : set file name using attribute - %s\n ", finfo->filename);
1609
1610                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SINK].gst, "location", finfo->filename);
1611
1612                         sc->ferror_send = FALSE;
1613                         sc->ferror_count = 0;
1614                         sc->bget_eos = FALSE;
1615                         info->filesize = 0;
1616
1617                         /* set max size */
1618                         if (imax_size <= 0)
1619                                 info->max_size = 0;     /* do not check */
1620                         else
1621                                 info->max_size = ((guint64) imax_size) << 10;   /* to byte */
1622
1623                         /* set max time */
1624                         if (imax_time <= 0)
1625                                 info->max_time = 0;     /* do not check */
1626                         else
1627                                 info->max_time = ((guint64) imax_time) * 1000;  /* to millisecond */
1628
1629                         /* TODO : check free space before recording start, need to more discussion */
1630                         dir_name = g_path_get_dirname(finfo->filename);
1631                         err = _mmstreamrecorder_get_freespace(dir_name, &free_space);
1632
1633                         _mmstreamrec_dbg_warn("current space for recording - %s : [%" G_GUINT64_FORMAT "]", dir_name, free_space);
1634
1635                         if (dir_name) {
1636                                 g_free(dir_name);
1637                                 dir_name = NULL;
1638                         }
1639                         cal_space = (guint64)(hstreamrecorder->ini.audio_frame_minimum_space);
1640                         cal_space = cal_space + (5 * 1024);
1641                         if ((err == -1) || free_space <= cal_space) {
1642                                 _mmstreamrec_dbg_err("No more space for recording");
1643                                 return MM_MESSAGE_STREAMRECORDER_NO_FREE_SPACE;
1644                         }
1645                 }
1646
1647                 ret = _mmstreamrecorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
1648                 if (ret != MM_ERROR_NONE)
1649                         goto _ERR_STREAMRECORDER_AUDIO_COMMAND;
1650
1651                 break;
1652
1653         case _MM_STREAMRECORDER_CMD_PAUSE:
1654                 {
1655                         GstClock *l_clock = NULL;
1656
1657                         if (info->b_commiting) {
1658                                 _mmstreamrec_dbg_warn("now on commiting previous file!!(cmd : %d)", cmd);
1659                                 return MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING;
1660                         }
1661
1662                         for (count = 0; count <= hstreamrecorder->ini.retrial_count; count++) {
1663                                 if (info->filesize > 0) {
1664                                         break;
1665                                 } else if (count == hstreamrecorder->ini.retrial_count) {
1666                                         _mmstreamrec_dbg_err("Pause fail, wait 200 ms, but file size is %lld", info->filesize);
1667                                         return MM_ERROR_STREAMRECORDER_INVALID_CONDITION;
1668                                 } else {
1669                                         _mmstreamrec_dbg_warn("Wait for enough audio frame, retry count[%d], file size is %lld", count, info->filesize);
1670                                 }
1671                                 usleep(hstreamrecorder->ini.audio_frame_wait_time);
1672                         }
1673
1674                         ret = _mmstreamrecorder_gst_set_state(handle, pipeline, GST_STATE_PAUSED);
1675                         if (ret != MM_ERROR_NONE)
1676                                 goto _ERR_STREAMRECORDER_AUDIO_COMMAND;
1677
1678                         /* FIXME: consider delay. */
1679                         l_clock = gst_pipeline_get_clock(GST_PIPELINE(pipeline));
1680                         sc->pipeline_time = gst_clock_get_time(l_clock) - gst_element_get_base_time(GST_ELEMENT(pipeline));
1681                         break;
1682                 }
1683
1684         case _MM_STREAMRECORDER_CMD_CANCEL:
1685                 if (info->b_commiting) {
1686                         _mmstreamrec_dbg_warn("now on commiting previous file!!(cmd : %d)", cmd);
1687                         return MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING;
1688                 }
1689
1690                 ret = _mmstreamrecorder_gst_set_state(handle, pipeline, GST_STATE_READY);
1691                 if (ret != MM_ERROR_NONE)
1692                         goto _ERR_STREAMRECORDER_AUDIO_COMMAND;
1693
1694                 if (info->bMuxing) {
1695                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1696                 } else {
1697                         MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AQUE].gst, "empty-buffers", FALSE);
1698                 }
1699
1700                 _mmstreamrecorder_gst_set_state(handle, sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SINK].gst, GST_STATE_NULL);
1701
1702                 sc->pipeline_time = 0;
1703                 sc->pause_time = 0;
1704                 sc->isMaxsizePausing = FALSE;
1705                 sc->isMaxtimePausing = FALSE;
1706
1707                 if (finfo->filename) {
1708                         _mmstreamrec_dbg_log("file delete(%s)", finfo->filename);
1709                         unlink(finfo->filename);
1710                         g_free(finfo->filename);
1711                         finfo->filename = NULL;
1712                 }
1713                 break;
1714
1715         case _MM_STREAMRECORDER_CMD_COMMIT:
1716                 {
1717
1718                         _mmstreamrec_dbg_log("_MM_STREAMRECORDER_CMD_COMMIT");
1719
1720                         if (info->b_commiting) {
1721                                 _mmstreamrec_dbg_warn("now on commiting previous file!!(cmd : %d)", cmd);
1722                                 return MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING;
1723                         } else {
1724                                 _mmstreamrec_dbg_log("_MM_STREAMRECORDER_CMD_COMMIT : start");
1725                                 info->b_commiting = TRUE;
1726                         }
1727
1728                         for (count = 0; count <= hstreamrecorder->ini.retrial_count; count++) {
1729                                 if (info->filesize > 0) {
1730                                         break;
1731                                 } else if (count == hstreamrecorder->ini.retrial_count) {
1732                                         _mmstreamrec_dbg_err("Commit fail, waited 200 ms, but file size is %lld", info->filesize);
1733                                         info->b_commiting = FALSE;
1734                                         return MM_ERROR_STREAMRECORDER_INVALID_CONDITION;
1735                                 } else {
1736                                         _mmstreamrec_dbg_warn("Waiting for enough audio frame, re-count[%d], file size is %lld", count, info->filesize);
1737                                 }
1738                                 usleep(hstreamrecorder->ini.audio_frame_wait_time);
1739                         }
1740
1741                         if (audioSrc) {
1742                                 GstPad *pad = gst_element_get_static_pad(audioSrc, "src");
1743                                 ret = gst_element_send_event(audioSrc, gst_event_new_eos());
1744                                 gst_object_unref(pad);
1745                                 pad = NULL;
1746                                 /* for pause -> commit case */
1747                                 /*if (_mmstreamrecorder_get_state((MMHandleType)hstreamrecorder) == MM_STREAMRECORDER_STATE_PAUSED) {
1748                                    ret = _mmstreamrecorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
1749                                    if (ret != MM_ERROR_NONE) {
1750                                    goto _ERR_STREAMRECORDER_AUDIO_COMMAND;
1751                                    }
1752                                    } */
1753                         }
1754
1755                         /* wait until finishing EOS */
1756                         _mmstreamrec_dbg_log("Start to wait EOS");
1757                         if ((ret = _mmstreamrecorder_get_eos_message(handle)) != MM_ERROR_NONE)
1758                                 goto _ERR_STREAMRECORDER_AUDIO_COMMAND;
1759
1760                         break;
1761                 }
1762         default:
1763                 ret = MM_ERROR_STREAMRECORDER_INVALID_ARGUMENT;
1764                 break;
1765         }
1766
1767  _ERR_STREAMRECORDER_AUDIO_COMMAND:
1768         return ret;
1769 }
1770
1771 int _mmstreamrecorder_audio_handle_eos(MMHandleType handle)
1772 {
1773         int err = MM_ERROR_NONE;
1774         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1775         _MMStreamRecorderSubContext *sc = NULL;
1776         _MMStreamRecorderAudioInfo *info = NULL;
1777         _MMStreamRecorderFileInfo *finfo = NULL;
1778         GstElement *pipeline = NULL;
1779         _MMStreamRecorderMsgItem msg;
1780         MMStreamRecordingReport *report;
1781
1782         mmf_return_val_if_fail(hstreamrecorder, FALSE);
1783         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1784
1785         mmf_return_val_if_fail(sc, FALSE);
1786         mmf_return_val_if_fail(sc->info_audio, FALSE);
1787         mmf_return_val_if_fail(sc->info_file, FALSE);
1788
1789         _mmstreamrec_dbg_err("");
1790
1791         info = sc->info_audio;
1792         finfo = sc->info_file;
1793
1794         pipeline = sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst;
1795
1796         err = _mmstreamrecorder_gst_set_state(handle, pipeline, GST_STATE_READY);
1797
1798         if (err != MM_ERROR_NONE)
1799                 _mmstreamrec_dbg_warn("Failed:_MM_STREAMRECORDER_CMD_COMMIT:GST_STATE_READY. err[%x]", err);
1800
1801         /* Send recording report message to application */
1802         msg.id = MM_MESSAGE_STREAMRECORDER_AUDIO_CAPTURED;
1803         report = (MMStreamRecordingReport *) malloc(sizeof(MMStreamRecordingReport));
1804         if (!report) {
1805                 _mmstreamrec_dbg_err("Recording report fail(%s). Out of memory.", finfo->filename);
1806                 return FALSE;
1807         }
1808
1809         /* START TAG HERE */
1810         /* MM_AUDIO_CODEC_AAC + MM_FILE_FORMAT_MP4 */
1811         if (finfo->fileformat == MM_FILE_FORMAT_3GP || finfo->fileformat == MM_FILE_FORMAT_MP4)
1812                 _mmstreamrecorder_audio_add_metadata_info_m4a(handle);
1813         /* END TAG HERE */
1814
1815         report->recording_filename = strdup(finfo->filename);
1816         msg.param.data = report;
1817
1818         _mmstreamrecorder_send_message(handle, &msg);
1819
1820         if (info->bMuxing) {
1821                 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1822         } else {
1823                 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AQUE].gst, "empty-buffers", FALSE);
1824         }
1825
1826         _mmstreamrecorder_gst_set_state(handle, pipeline, GST_STATE_NULL);
1827
1828         sc->pipeline_time = 0;
1829         sc->pause_time = 0;
1830         sc->isMaxsizePausing = FALSE;
1831         sc->isMaxtimePausing = FALSE;
1832
1833         g_free(finfo->filename);
1834         finfo->filename = NULL;
1835
1836         _mmstreamrec_dbg_err("_MM_STREAMRECORDER_CMD_COMMIT : end");
1837
1838         info->b_commiting = FALSE;
1839
1840         return TRUE;
1841 }
1842
1843 int _mmstreamrecorder_push_videostream_buffer(MMHandleType handle, unsigned long timestamp, GstBuffer *buffer, int size)
1844 {
1845         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1846         _MMStreamRecorderSubContext *sc = NULL;
1847         GstPad *srcpad = NULL;
1848         GstCaps *srccaps = NULL;
1849         char *err_name = NULL;
1850         int video_fps = 0;
1851         int video_src = 0;
1852         int video_width = 0;
1853         int video_height = 0;
1854         int ret = MM_ERROR_NONE;
1855         int video_source_format = 0;
1856
1857         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1858
1859         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1860         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1861
1862         if (buffer == NULL || size == 0) {
1863                 _mmstreamrec_dbg_err("video : Buffer is %p , size %d, time stamp is %ld", buffer, size, timestamp);
1864                 return MM_ERROR_STREAMRECORDER_RESOURCE_CREATION;
1865         }
1866
1867         _mmstreamrec_dbg_log("video : Buffer is %p , size %d, time stamp is %ld", buffer, size, timestamp);
1868
1869         /* check element availability */
1870         ret = mm_streamrecorder_get_attributes(handle, &err_name, MMSTR_VIDEO_FRAMERATE, &video_fps, MMSTR_VIDEO_SOURCE_FORMAT, &video_src, MMSTR_VIDEO_RESOLUTION_WIDTH, &video_width, MMSTR_VIDEO_RESOLUTION_HEIGHT, &video_height, MMSTR_VIDEO_SOURCE_FORMAT, &video_source_format, NULL);
1871
1872         if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst) {
1873
1874                 /*_mmstreamrec_dbg_log("Buffer Push start , time stamp %ld",timestamp);*/
1875                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "src");
1876                 srccaps = gst_pad_get_current_caps(srcpad);
1877                 srccaps = gst_set_videosrcpad_caps(video_src, video_width, video_height, video_fps, 1);
1878                 gst_app_src_set_caps((GstAppSrc *) sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, srccaps);
1879                 /*_mmstreamrec_dbg_err("newbuf streamrecorder(%p) ",newbuf);*/
1880
1881                 ret = gst_app_src_push_buffer((GstAppSrc *) sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, buffer);
1882                 if (ret) {
1883                         _mmstreamrec_dbg_err("video gst_app_src_push_buffer %d", ret);
1884                         ret = MM_ERROR_STREAMRECORDER_VIDEOBUFFER_PUSH;
1885                 }
1886
1887                 /* g_signal_emit_by_name(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "push-buffer", newbuf, &ret); */
1888         }
1889
1890         return ret;
1891 }
1892
1893 int _mmstreamrecorder_push_audiostream_buffer(MMHandleType handle, unsigned long timestamp, GstBuffer *buffer, int size)
1894 {
1895         mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1896         _MMStreamRecorderSubContext *sc = NULL;
1897         _MMStreamRecorderAudioInfo *info = NULL;
1898         GstFlowReturn err = GST_FLOW_OK;
1899         GstPad *srcpad = NULL;
1900         GstCaps *srccaps = NULL;
1901         int rate = 0;
1902         int channel = 0;
1903         int depth = 0;
1904
1905         mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1906
1907         sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1908         mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1909
1910         info = (_MMStreamRecorderAudioInfo *) sc->info_audio;
1911         mmf_return_val_if_fail(info, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1912
1913         rate = info->iSamplingRate;
1914         depth = info->audio_encode_depth;
1915         channel = info->iChannels;
1916
1917         /*_mmstreamrec_dbg_log("Audio Buffer Push start , time stamp %ld",timestamp); */
1918
1919         if (sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst) {
1920
1921                 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, "src");
1922                 /* TODO : CHANNEL , WIDTH, DATATYPE */
1923                 srccaps = gst_pad_get_current_caps(srcpad);
1924                 srccaps = gst_set_audiosrcpad_caps(rate, channel, depth, 16, 1);
1925                 gst_base_src_set_caps(GST_BASE_SRC(srcpad), srccaps);
1926
1927                 err = gst_app_src_push_buffer((GstAppSrc *) sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, buffer);
1928
1929                 if (err) {
1930                         _mmstreamrec_dbg_err("Audio gst_app_src_push_buffer %d", err);
1931                         return MM_ERROR_STREAMRECORDER_AUDIOBUFFER_PUSH;
1932                 }
1933         }
1934
1935         return MM_ERROR_NONE;
1936 }
1937