4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hyuntae Kim <ht1211.kim@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 /*=======================================================================================
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"
35 #include <gst/base/gstadapter.h>
36 #include <gst/app/gstappsrc.h>
37 #include <gst/app/gstappsink.h>
40 /*---------------------------------------------------------------------------------------
41 | GLOBAL VARIABLE DEFINITIONS for internal |
42 ---------------------------------------------------------------------------------------*/
44 /*---------------------------------------------------------------------------------------
45 | LOCAL VARIABLE DEFINITIONS for internal |
46 ---------------------------------------------------------------------------------------*/
48 /*-----------------------------------------------------------------------
49 | GLOBAL VARIABLE DEFINITIONS for internal |
50 -----------------------------------------------------------------------*/
52 /*---------------------------------------------------------------------------------------
53 | LOCAL FUNCTION PROTOTYPES: |
54 ---------------------------------------------------------------------------------------*/
55 /* STATIC INTERNAL FUNCTION */
57 /*=======================================================================================
58 | FUNCTION DEFINITIONS |
59 =======================================================================================*/
60 /*---------------------------------------------------------------------------------------
61 | GLOBAL FUNCTION DEFINITIONS: |
62 ---------------------------------------------------------------------------------------*/
63 int _mmstreamrecorder_create_pipeline(MMHandleType handle)
65 int ret = MM_ERROR_NONE;
66 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
67 _MMStreamRecorderSubContext *sc = NULL;
68 GstElement *pipeline = NULL;
70 _mmstreamrec_dbg_log("handle : %x", handle);
72 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
74 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
75 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
78 ret = _mmstreamrecorder_create_recorder_pipeline(handle);
80 pipeline = sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst;
82 ret = _mmstreamrecorder_gst_set_state(handle, pipeline, GST_STATE_READY);
84 _mmstreamrec_dbg_log("ret[%x]", ret);
88 void _mmstreamrecorder_destroy_pipeline(MMHandleType handle)
90 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
91 _MMStreamRecorderSubContext *sc = NULL;
94 _MMStreamRecorderGstElement *element = NULL;
97 mmf_return_if_fail(hstreamrecorder);
99 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
100 mmf_return_if_fail(sc);
102 _mmstreamrec_dbg_log("");
104 element = sc->encode_element;
105 element_num = sc->encode_element_num;
106 if (element == NULL) {
107 _mmstreamrec_dbg_log("encode element is null!!");
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));
114 _mmstreamrec_dbg_log("Pipeline clear!!");
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;
122 /* Remove remained message in 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);
130 gst_object_unref(bus);
134 /* Inside each pipeline destroy function, Set GST_STATE_NULL to Main pipeline */
135 _mmstreamrecorder_destroy_recorder_pipeline(handle);
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);
146 _mmstreamrec_dbg_warn("The element[%d] is still aliving, check it", element[i].id);
149 element[i].id = _MMSTREAMRECORDER_ENCODE_NONE;
150 element[i].gst = NULL;
157 int _mmstreamrecorder_create_recorder_pipeline(MMHandleType handle)
160 int err = MM_ERROR_NONE;
161 int audio_enable = FALSE;
163 GstPad *srcpad = NULL;
164 GstPad *sinkpad = NULL;
166 unsigned int video_codec = MM_VIDEO_CODEC_INVALID;
167 unsigned int file_format = MM_FILE_FORMAT_INVALID;
168 char *err_name = NULL;
170 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
171 _MMStreamRecorderSubContext *sc = NULL;
173 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
175 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
176 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
178 _mmstreamrec_dbg_warn("start");
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);
187 err = _mmstreamrecorder_check_videocodec_fileformat_compatibility(video_codec, file_format);
188 if (err != MM_ERROR_NONE)
192 _MMSTREAMRECORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCODE_MAIN_PIPE, "recorder_pipeline", err);
194 /* get audio disable */
195 mm_streamrecorder_get_attributes(handle, NULL, MMSTR_AUDIO_ENABLE, &audio_enable, NULL);
196 sc->audio_enable = audio_enable;
198 _mmstreamrec_dbg_log("AUDIO DISABLE : %d", sc->audio_enable);
200 if (sc->audio_enable == TRUE) {
201 /* create audiosrc bin */
202 err = _mmstreamrecorder_create_audiosrc_bin((MMHandleType) hstreamrecorder);
203 if (err != MM_ERROR_NONE)
207 err = _mmstreamrecorder_create_encodesink_bin((MMHandleType) hstreamrecorder, MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO);
208 if (err != MM_ERROR_NONE)
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);
214 /* add element and encodesink bin to encode main pipeline */
215 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 /* Link each element : appsrc - capsfilter - encodesink bin */
218 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "src");
219 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, "sink");
220 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
222 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, "src");
223 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, "video_sink0");
224 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
226 if (sc->audio_enable == TRUE) {
227 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, "src");
228 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, "audio_sink0");
229 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
232 if (sc->audio_enable == TRUE) {
233 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "sink");
234 MMSTREAMRECORDER_ADD_BUFFER_PROBE(sinkpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_audioque_dataprobe, hstreamrecorder);
235 gst_object_unref(sinkpad);
238 if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC_QUE].gst) {
239 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC_QUE].gst, "src");
240 MMSTREAMRECORDER_ADD_EVENT_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_eventprobe_monitor, hstreamrecorder);
241 gst_object_unref(srcpad);
246 if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC_QUE].gst) {
247 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC_QUE].gst, "src");
248 MMSTREAMRECORDER_ADD_EVENT_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_eventprobe_monitor, hstreamrecorder);
249 gst_object_unref(srcpad);
253 if (sc->audio_enable == FALSE) {
254 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "sink");
255 MMSTREAMRECORDER_ADD_BUFFER_PROBE(sinkpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_video_dataprobe_audio_disable, hstreamrecorder);
256 gst_object_unref(sinkpad);
260 if (!strcmp(/*gst_element_rsink_name */"filesink", "filesink")) {
261 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "src");
262 MMSTREAMRECORDER_ADD_BUFFER_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_video_dataprobe_record, hstreamrecorder);
263 gst_object_unref(srcpad);
266 if (sc->audio_enable == TRUE) {
267 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "src");
268 MMSTREAMRECORDER_ADD_BUFFER_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_audio_dataprobe_check, hstreamrecorder);
269 gst_object_unref(srcpad);
274 bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst));
276 /* register pipeline message callback */
277 hstreamrecorder->encode_pipeline_cb_event_id = gst_bus_add_watch(bus, (GstBusFunc) _mmstreamrecorder_pipeline_cb_message, hstreamrecorder);
279 gst_object_unref(bus);
282 return MM_ERROR_NONE;
284 pipeline_creation_error:
285 for (i = _MMSTREAMRECORDER_AUDIOSRC_BIN; i <= _MMSTREAMRECORDER_ENCSINK_SINK; i++)
286 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, i);
288 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCODE_MAIN_PIPE);
292 int _mmstreamrecorder_destroy_recorder_pipeline(MMHandleType handle)
294 int ret = MM_ERROR_NONE;
295 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
296 _MMStreamRecorderSubContext *sc = NULL;
300 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
301 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
302 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
304 _mmstreamrec_dbg_log("start");
306 if (!sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst) {
307 _mmstreamrec_dbg_warn("pipeline is not existed.");
308 return MM_ERROR_NONE;
311 _mmstreamrecorder_remove_all_handlers((MMHandleType) hstreamrecorder, _MMSTREAMRECORDER_HANDLER_VIDEOREC);
313 ret = _mmstreamrecorder_gst_set_state(handle, sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_NULL);
314 if (ret != MM_ERROR_NONE) {
315 _mmstreamrec_dbg_err("Faile to change encode main pipeline [0x%x]", ret);
319 bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst));
321 /* Remove remained message */
323 GstMessage *gst_msg = NULL;
324 while ((gst_msg = gst_bus_pop(bus)) != NULL) {
325 _mmstreamrecorder_pipeline_cb_message(bus, gst_msg, (gpointer) hstreamrecorder);
326 gst_message_unref(gst_msg);
329 gst_object_unref(bus);
333 /* remove audio pipeline first */
334 ret = _mmstreamrecorder_destroy_audiosrc_bin(handle);
335 if (ret != MM_ERROR_NONE) {
336 _mmstreamrec_dbg_err("Fail to remove audio pipeline");
340 ret = _mmstreamrecorder_destroy_encodesink_bin(handle);
341 if (ret != MM_ERROR_NONE) {
342 _mmstreamrec_dbg_err("Fail to remove encoder pipeline");
346 /* Remove pipeline message callback */
347 if (hstreamrecorder->encode_pipeline_cb_event_id != 0) {
348 g_source_remove(hstreamrecorder->encode_pipeline_cb_event_id);
349 hstreamrecorder->encode_pipeline_cb_event_id = 0;
352 _mmstreamrec_dbg_log("done");
357 int _mmstreamrecorder_create_encodesink_bin(MMHandleType handle, MMStreamRecorderEncodebinProfile profile)
359 int err = MM_ERROR_NONE;
367 int video_height = 0;
370 int audio_src_format = 0;
371 int video_src_format = 0;
372 int audio_samplerate = 0;
373 const char *str_profile = NULL;
374 const char *str_aac = NULL;
375 const char *str_aar = NULL;
376 const char *str_acs = NULL;
377 char *err_name = NULL;
379 GstCaps *caps = NULL;
381 GList *element_list = NULL;
382 char *temp_filename = NULL;
389 _MMStreamRecorderVideoInfo *info = NULL;
390 _MMStreamRecorderFileInfo *finfo = NULL;
392 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
393 _MMStreamRecorderSubContext *sc = NULL;
394 /* type_element *VideoencElement = NULL; */
395 /* type_element *AudioencElement = NULL; */
396 /* type_element *MuxElement = NULL; */
397 /* type_element *RecordsinkElement = NULL; */
399 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
401 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
402 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
404 _mmstreamrec_dbg_log("start - profile : %d", profile);
406 info = sc->info_video;
407 finfo = sc->info_file;
409 /* check element availability */
410 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 _mmstreamrec_dbg_err("audio encoder - %d , video encoder : %d", audio_enc, video_enc);
413 _mmstreamrec_dbg_err("audio channel - %d , video v_bitrate : %d", channel, v_bitrate);
414 _mmstreamrec_dbg_err("audio a_bitrate - %d , video video_width : %d ,video video_height : %d ", a_bitrate, video_width, video_height);
415 _mmstreamrec_dbg_err("video_fps - %d , video file_format : %d", video_fps, file_format);
417 /* Check existence */
418 if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst) {
419 if (((GObject *) sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst)->ref_count > 0)
420 gst_object_unref(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst);
422 _mmstreamrec_dbg_log("_MMSTREAMRECORDER_ENCSINK_BIN is Already existed.");
425 /* Create bin element */
426 _MMSTREAMRECORDER_BIN_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_BIN, "encodesink_bin", err);
428 /* Create child element */
429 if (hstreamrecorder->ini.encsink_bin_profile != MM_STREAMRECORDER_ENCBIN_PROFILE_AUDIO) {
430 /* create appsrc and capsfilter */
431 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SRC, hstreamrecorder->ini.name_of_encsink_src, "encodesink_src", element_list, err);
432 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_FILT, "capsfilter", "encodesink_filter", element_list, err);
434 caps = gst_set_videosrcpad_caps(video_src_format, video_width, video_height, video_fps, 1);
435 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "caps", caps);
437 gst_caps_unref(caps);
441 caps = gst_set_videosrcpad_caps(video_src_format, video_width, video_height, video_fps, 1);
442 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, "caps", caps);
444 gst_caps_unref(caps);
449 /* release element_list, they will be placed out of encodesink bin */
451 g_list_free(element_list);
454 if (rec_mode == MM_STREAMRECORDER_MODE_MEDIABUFFER) {
455 /* set appsrc as live source */
456 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "is-live", hstreamrecorder->ini.encsink_src_islive);
461 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_ENCBIN, "encodebin", "encodesink_encbin", element_list, err);
463 _mmstreamrec_dbg_log("Profile[%d]", profile);
465 /* Set information */
466 if (hstreamrecorder->ini.encsink_bin_profile == MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO) {
467 str_profile = "VideoProfile";
468 str_aac = "VideoAutoAudioConvert";
469 str_aar = "VideoAutoAudioResample";
470 str_acs = "VideoAutoColorSpace";
471 } else if (hstreamrecorder->ini.encsink_bin_profile == MM_STREAMRECORDER_ENCBIN_PROFILE_AUDIO) {
472 str_profile = "AudioProfile";
473 str_aac = "AudioAutoAudioConvert";
474 str_aar = "AudioAutoAudioResample";
475 str_acs = "AudioAutoColorSpace";
478 /* TODO : check the last value ( set ) */
479 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "profile", hstreamrecorder->ini.encsink_bin_profile);
480 if (rec_mode == MM_STREAMRECORDER_MODE_MEDIABUFFER)
481 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", hstreamrecorder->ini.encsink_bin_auto_audio_convert);
483 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-resample", hstreamrecorder->ini.encsink_bin_auto_audio_resample);
484 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-colorspace", hstreamrecorder->ini.encsink_bin_auto_colorspace);
485 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "use-video-toggle", hstreamrecorder->ini.encsink_bin_use_video_toggle);
488 if (hstreamrecorder->ini.encsink_bin_profile == MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO) {
490 case MM_VIDEO_CODEC_H263:
491 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "venc-name", hstreamrecorder->ini.h263_video_encoder);
493 case MM_VIDEO_CODEC_H264:
494 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "venc-name", hstreamrecorder->ini.h264_video_encoder);
496 case MM_VIDEO_CODEC_MPEG4:
497 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "venc-name", hstreamrecorder->ini.mpeg4_video_encoder);
500 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "venc-name", hstreamrecorder->ini.h264_video_encoder);
503 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_VENC, "video-encode", err);
505 /* set color converter size */
506 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "vconv-name", hstreamrecorder->ini.name_of_encsink_bin_video_converter);
507 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_VCONV, "video-convert", err);
509 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-colorspace", hstreamrecorder->ini.encsink_bin_auto_colorspace);
511 if (video_src_format == MM_STREAMRECORDER_INPUT_FORMAT_NV12)
512 video_src_format = MM_STREAMRECORDER_INPUT_FORMAT_I420;
514 caps = gst_set_videosrcpad_caps(video_src_format, video_width, video_height, video_fps, 1);
515 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "vcaps", caps);
516 if (video_src_format != MM_STREAMRECORDER_INPUT_FORMAT_NV12)
517 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VCONV].gst, "dst-buffer-num", hstreamrecorder->ini.convert_output_buffer_num);
520 err = gst_pad_set_caps(gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "sink"), caps);
522 /* MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "state-tuning", TRUE); */
525 gst_caps_unref(caps);
528 _mmstreamrec_dbg_log("size %dx%d, dst-buffer-num %d", video_width, video_height, hstreamrecorder->ini.convert_output_buffer_num);
530 _mmstreamrec_dbg_warn("encoder set caps result : 0x%x", err);
532 if (hstreamrecorder->ini.encsink_bin_use_parser[0]) {
533 GstElement *parser = gst_element_factory_make(hstreamrecorder->ini.encsink_bin_use_parser, "parse");
534 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "use-venc-queue", parser);
535 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_PARSER, "use-venc-queue", err);
539 if (sc->audio_enable == TRUE) {
541 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "aenc-name", hstreamrecorder->ini.name_of_encsink_bin_audio_encoder);
542 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_AENC, "audio-encode", err);
543 _mmstreamrec_dbg_err("audio-encode err = %x ", err);
545 /* Set basic infomation */
546 if (audio_enc != MM_AUDIO_CODEC_VORBIS) {
549 if (audio_src_format == MM_STREAMRECORDER_AUDIO_FORMAT_PCM_S16_LE) {
551 } else { /* MM_STREAMRECORDER_AUDIO_FORMAT_PCM_U8 */
555 /* TODO : set rate , channel , depth */
557 caps = gst_set_audiosrcpad_caps(audio_samplerate, 2, depth, 16, 1);
558 /* MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE); */
559 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "acaps", caps);
561 gchar *type = gst_caps_to_string(caps);
563 _mmstreamrec_dbg_warn("Set srcpad caps: %s", type);
565 gst_caps_unref(caps);
568 /* what are the audio encoder which should get audio/x-raw-float? */
569 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);
570 _mmstreamrec_dbg_log("caps [x-raw-float, rate:%d, channel:%d, endianness:%d, width:32]", audio_samplerate, channel, BYTE_ORDER);
571 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE);
572 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "acaps", caps);
573 gst_caps_unref(caps);
578 if (audio_enc == MM_AUDIO_CODEC_AMR && channel == 2) {
579 caps = gst_caps_new_simple("audio/x-raw-int", "channels", G_TYPE_INT, 1, NULL);
580 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE);
581 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "acaps", caps);
582 gst_caps_unref(caps);
586 if (audio_enc == MM_AUDIO_CODEC_OGG) {
587 caps = gst_caps_new_simple("audio/x-raw-int", NULL);
588 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE);
589 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "acaps", caps);
590 gst_caps_unref(caps);
595 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_AENC_QUE, "use-aenc-queue", err);
599 switch (file_format) {
600 case MM_FILE_FORMAT_3GP:{
601 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "mux-name", hstreamrecorder->ini.name_of_encsink_bin_3GPMUXER);
605 case MM_FILE_FORMAT_MP4:{
606 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "mux-name", hstreamrecorder->ini.name_of_encsink_bin_MP4MUXER);
611 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "mux-name", hstreamrecorder->ini.name_of_encsink_bin_MP4MUXER);
616 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_MUX, "mux", err);
620 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SINK, "filesink", NULL, element_list, err);
621 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SINK].gst, "async", 0);
623 err = mm_streamrecorder_get_attributes(handle, &err_name,
624 MMSTR_FILE_FORMAT, &fileformat, MMSTR_FILENAME, &temp_filename, &size,
625 MMSTR_TARGET_MAX_SIZE, &imax_size,
626 MMSTR_TARGET_TIME_LIMIT, &imax_time,
629 if (err != MM_ERROR_NONE) {
630 _mmstreamrec_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
635 finfo->fileformat = fileformat;
639 info->max_size = 0; /* do not check */
641 info->max_size = ((guint64) imax_size) << 10; /* to byte */
645 info->max_time = 0; /* do not check */
647 info->max_time = ((guint64) imax_time) * 1000; /* to millisecond */
649 finfo->filename = g_strdup(temp_filename);
650 if (!finfo->filename) {
651 _mmstreamrec_dbg_err("strdup was failed");
655 _mmstreamrec_dbg_log("Record start : set file name using attribute - %s ", finfo->filename);
657 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SINK].gst, "location", finfo->filename);
659 if (profile == MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO) {
660 /* video encoder attribute setting */
662 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "bitrate", v_bitrate);
664 _mmstreamrec_dbg_warn("video bitrate is too small[%d], so skip setting. Use DEFAULT value.", v_bitrate);
667 if (sc->audio_enable == TRUE) {
668 /* audio encoder attribute setting */
671 case MM_AUDIO_CODEC_AMR:
672 result = _mmstreamrecorder_get_amrnb_bitrate_mode(a_bitrate);
673 _mmstreamrec_dbg_log("Set AMR encoder mode [%d]", result);
674 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "band-mode", result);
676 case MM_AUDIO_CODEC_AAC:
677 _mmstreamrec_dbg_log("Set AAC encoder bitrate [%d]", a_bitrate);
678 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "bitrate", a_bitrate);
681 _mmstreamrec_dbg_log("Audio codec is not AMR or AAC... you need to implement setting function for audio encoder bit-rate");
685 _mmstreamrec_dbg_warn("Setting bitrate is too small, so skip setting. Use DEFAULT value.");
689 _mmstreamrec_dbg_log("Element creation complete");
691 /* Add element to bin */
692 if (!_mmstreamrecorder_add_elements_to_bin(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst), element_list)) {
693 _mmstreamrec_dbg_err("element add error.");
694 err = MM_ERROR_STREAMRECORDER_RESOURCE_CREATION;
695 goto pipeline_creation_error;
698 _mmstreamrec_dbg_log("Element add complete");
700 if (profile == MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO) {
701 pad = gst_element_get_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "video");
702 if (gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("video_sink0", pad)) < 0) {
703 gst_object_unref(pad);
705 _mmstreamrec_dbg_err("failed to create ghost video_sink0 on _MMSTREAMRECORDER_ENCSINK_BIN.");
706 err = MM_ERROR_STREAMRECORDER_GST_LINK;
707 goto pipeline_creation_error;
709 gst_object_unref(pad);
712 if (sc->audio_enable == TRUE) {
713 pad = gst_element_get_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "audio");
714 if (gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("audio_sink0", pad)) < 0) {
715 gst_object_unref(pad);
717 _mmstreamrec_dbg_err("failed to create ghost audio_sink0 on _MMSTREAMRECORDER_ENCSINK_BIN.");
718 err = MM_ERROR_STREAMRECORDER_GST_LINK;
719 goto pipeline_creation_error;
721 gst_object_unref(pad);
724 } else if (profile == MM_STREAMRECORDER_ENCBIN_PROFILE_AUDIO) {
725 pad = gst_element_get_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "audio");
726 if (gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("audio_sink0", pad)) < 0) {
727 gst_object_unref(pad);
729 _mmstreamrec_dbg_err("failed to create ghost audio_sink0 on _MMSTREAMRECORDER_ENCSINK_BIN.");
730 err = MM_ERROR_STREAMRECORDER_GST_LINK;
731 goto pipeline_creation_error;
733 gst_object_unref(pad);
737 pad = gst_element_get_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "image");
738 if (gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("image_sink0", pad)) < 0) {
739 gst_object_unref(pad);
741 _mmstreamrec_dbg_err("failed to create ghost image_sink0 on _MMSTREAMRECORDER_ENCSINK_BIN.");
742 err = MM_ERROR_STREAMRECORDER_GST_LINK;
743 goto pipeline_creation_error;
745 gst_object_unref(pad);
749 _mmstreamrec_dbg_log("Get pad complete");
751 /* Link internal element */
752 if (!_mmstreamrecorder_link_elements(element_list)) {
753 _mmstreamrec_dbg_err("element link error.");
754 err = MM_ERROR_STREAMRECORDER_GST_LINK;
755 goto pipeline_creation_error;
759 g_list_free(element_list);
763 _mmstreamrec_dbg_log("done");
765 return MM_ERROR_NONE;
767 pipeline_creation_error:
768 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_ENCBIN);
769 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SRC);
770 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_FILT);
771 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_VENC);
772 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_AENC);
773 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_IENC);
774 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_MUX);
775 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SINK);
776 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_BIN);
779 g_list_free(element_list);
786 int _mmstreamrecorder_destroy_encodesink_bin(MMHandleType handle)
788 GstPad *reqpad = NULL;
789 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
790 _MMStreamRecorderSubContext *sc = NULL;
792 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
794 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
795 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
797 _mmstreamrec_dbg_log("");
799 if (sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst != NULL) {
800 /* release request pad */
801 reqpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "audio");
803 gst_element_release_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, reqpad);
804 gst_object_unref(reqpad);
808 reqpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "video");
810 gst_element_release_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, reqpad);
811 gst_object_unref(reqpad);
815 /* release encode main pipeline */
816 gst_object_unref(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst);
818 _mmstreamrec_dbg_log("Encoder pipeline removed");
821 return MM_ERROR_NONE;
824 int _mmstreamrecorder_create_audiosrc_bin(MMHandleType handle)
826 int err = MM_ERROR_NONE;
831 unsigned int a_enc = MM_AUDIO_CODEC_INVALID;
832 unsigned int file_format = MM_FILE_FORMAT_INVALID;
833 char *err_name = NULL;
836 GstCaps *caps = NULL;
838 GList *element_list = NULL;
840 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
841 _MMStreamRecorderSubContext *sc = NULL;
842 _MMStreamRecorderGstElement *last_element = NULL;
843 /* type_element *AudiosrcElement = NULL; */
845 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
847 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
848 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
850 _mmstreamrec_dbg_log("");
852 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);
854 if (err != MM_ERROR_NONE) {
855 _mmstreamrec_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
860 err = _mmstreamrecorder_check_audiocodec_fileformat_compatibility(a_enc, file_format);
861 if (err != MM_ERROR_NONE) {
862 _mmstreamrec_dbg_err("error name :%s , audio format %d , fileformat %d. error : %x)", err_name, a_enc, file_format, err);
867 /* Check existence */
868 if (sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst) {
869 if (((GObject *) sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst)->ref_count > 0)
870 gst_object_unref(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst);
872 _mmstreamrec_dbg_log("_MMSTREAMRECORDER_AUDIOSRC_BIN is Already existed. Unref once...");
875 /* Create bin element */
876 _MMSTREAMRECORDER_BIN_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_BIN, "audiosource_bin", err);
878 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_SRC, "appsrc", hstreamrecorder->ini.name_of_audio_src, element_list, err);
880 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_FILT, "capsfilter", "audiosrc_capsfilter", element_list, err);
882 /* Set basic infomation */
883 if (a_enc != MM_AUDIO_CODEC_VORBIS) {
886 if (format == MM_STREAMRECORDER_AUDIO_FORMAT_PCM_S16_LE) {
888 } else { /* MM_STREAMRECORDER_AUDIO_FORMAT_PCM_U8 */
892 caps = gst_set_audiosrcpad_caps(rate, channel, depth, 16, 1);
894 _mmstreamrec_dbg_log("caps [x-raw-int, rate:%d, channel:%d, depth:%d]", rate, channel, depth);
896 /* what are the audio encoder which should get audio/x-raw-float? */
897 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);
898 _mmstreamrec_dbg_log("caps [x-raw-float, rate:%d, channel:%d, endianness:%d, width:32]", rate, channel, BYTE_ORDER);
902 if (rec_mode == MM_STREAMRECORDER_MODE_MEDIABUFFER)
903 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "caps", caps);
905 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_FILT].gst), "caps", caps);
907 gchar *type = gst_caps_to_string(caps);
909 _mmstreamrec_dbg_err("_MMSTREAMRECORDER_AUDIOSRC_FILT %s", type);
912 gst_caps_unref(caps);
915 _mmstreamrec_dbg_err("create caps error");
916 err = MM_ERROR_STREAMRECORDER_RESOURCE_CREATION;
917 goto pipeline_creation_error;
920 if (rec_mode == MM_STREAMRECORDER_MODE_SCREENRECORD) {
922 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "do-timestamp", TRUE);
923 #else /* speaker mode with alsasrc */
924 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "device", "hw:0,8");
925 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "latency-time", 256000);
926 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "buffer-time", 10000);
927 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "do-timestamp", FALSE);
930 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "do-timestamp", FALSE);
933 if (!_mmstreamrecorder_add_elements_to_bin(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst), element_list)) {
934 _mmstreamrec_dbg_err("element add error.");
935 err = MM_ERROR_STREAMRECORDER_RESOURCE_CREATION;
936 goto pipeline_creation_error;
939 if (!_mmstreamrecorder_link_elements(element_list)) {
940 _mmstreamrec_dbg_err("element link error.");
941 err = MM_ERROR_STREAMRECORDER_GST_LINK;
942 goto pipeline_creation_error;
945 last_element = (_MMStreamRecorderGstElement *) (g_list_last(element_list)->data);
946 pad = gst_element_get_static_pad(last_element->gst, "src");
947 if ((gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, gst_ghost_pad_new("src", pad))) < 0) {
948 gst_object_unref(pad);
950 _mmstreamrec_dbg_err("failed to create ghost pad on _MMSTREAMRECORDER_AUDIOSRC_BIN.");
951 err = MM_ERROR_STREAMRECORDER_GST_LINK;
952 goto pipeline_creation_error;
955 gst_object_unref(pad);
959 g_list_free(element_list);
963 return MM_ERROR_NONE;
965 pipeline_creation_error:
966 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_SRC);
967 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_FILT);
968 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_BIN);
971 g_list_free(element_list);
978 int _mmstreamrecorder_destroy_audiosrc_bin(MMHandleType handle)
980 GstPad *srcpad = NULL;
981 GstPad *sinkpad = NULL;
982 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
983 _MMStreamRecorderSubContext *sc = NULL;
985 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
987 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
988 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
990 _mmstreamrec_dbg_log("");
992 if (sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst != NULL) {
993 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, "src");
994 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, "audio_sink0");
995 _MM_GST_PAD_UNLINK_UNREF(srcpad, sinkpad);
997 /* release audiosrc bin */
998 gst_bin_remove(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst);
1000 _mmstreamrecorder_remove_element_handle(handle, (void *)sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_BIN, _MMSTREAMRECORDER_AUDIOSRC_FILT);
1002 _mmstreamrec_dbg_log("Audio pipeline removed");
1005 return MM_ERROR_NONE;
1008 /* COMMAND - VIDEO */
1009 int _mmstreamrecorder_video_command(MMHandleType handle, int command)
1011 int ret = MM_ERROR_NONE;
1012 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1013 _MMStreamRecorderVideoInfo *info = NULL;
1014 _MMStreamRecorderAudioInfo *info_audio = NULL;
1015 _MMStreamRecorderFileInfo *finfo = NULL;
1016 _MMStreamRecorderSubContext *sc = NULL;
1017 GstElement *pipeline = NULL;
1021 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1023 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1024 mmf_return_val_if_fail(sc && sc->encode_element, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1026 mmf_return_val_if_fail(sc->info_video, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1027 if (sc->audio_enable == TRUE)
1028 mmf_return_val_if_fail(sc->info_audio, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1030 mmf_return_val_if_fail(sc->info_file, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1032 info = sc->info_video;
1033 if (sc->audio_enable == TRUE)
1034 info_audio = sc->info_audio;
1036 finfo = sc->info_file;
1038 _mmstreamrec_dbg_log("command %d", command);
1040 pipeline = sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst;
1043 case _MM_STREAMRECORDER_CMD_RECORD:
1047 _mmstreamrec_dbg_log("Record Start");
1048 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1050 /* Adjust display FPS */
1051 info->video_frame_count = 0;
1053 info_audio->audio_frame_count = 0;
1056 sc->ferror_send = FALSE;
1057 sc->ferror_count = 0;
1058 sc->error_occurs = FALSE;
1059 sc->bget_eos = FALSE;
1061 ret = _mmstreamrecorder_gst_set_state(handle, sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PLAYING);
1062 if (ret != MM_ERROR_NONE) {
1063 /* Remove recorder pipeline and recording file which size maybe zero */
1064 ret = _mmstreamrecorder_destroy_recorder_pipeline(handle);
1066 if (finfo->filename) {
1067 _mmstreamrec_dbg_log("file delete(%s)", finfo->filename);
1068 unlink(finfo->filename);
1069 g_free(finfo->filename);
1070 finfo->filename = NULL;
1072 goto _ERR_STREAMRECORDER_VIDEO_COMMAND;
1077 case _MM_STREAMRECORDER_CMD_PAUSE:
1080 if (info->b_commiting) {
1081 _mmstreamrec_dbg_warn("now on commiting previous file!!(command : %d)", command);
1082 return MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING;
1085 for (count = 0; count <= hstreamrecorder->ini.retrial_count; count++) {
1086 if (sc->audio_enable == FALSE) {
1087 /* check only video frame */
1088 if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame) {
1090 } else if (count == hstreamrecorder->ini.retrial_count) {
1091 _mmstreamrec_dbg_err("Pause fail, frame count %" G_GUINT64_FORMAT "", info->video_frame_count);
1092 return MM_ERROR_STREAMRECORDER_INVALID_CONDITION;
1094 _mmstreamrec_dbg_warn("Waiting for enough video frame, retrial[%d], frame %" G_GUINT64_FORMAT "", count, info->video_frame_count);
1097 usleep(hstreamrecorder->ini.video_frame_wait_time);
1099 /* check both of video and audio frame */
1100 if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame && info_audio->audio_frame_count) {
1102 } else if (count == hstreamrecorder->ini.retrial_count) {
1103 _mmstreamrec_dbg_err("Pause fail, frame count VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]", info->video_frame_count, info_audio->audio_frame_count);
1104 return MM_ERROR_STREAMRECORDER_INVALID_CONDITION;
1106 _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);
1109 usleep(hstreamrecorder->ini.video_frame_wait_time);
1113 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "runtime-pause", TRUE);
1118 case _MM_STREAMRECORDER_CMD_CANCEL:
1120 if (info->b_commiting) {
1121 _mmstreamrec_dbg_warn("now on commiting previous file!!(command : %d)", command);
1122 return MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING;
1125 ret = _mmstreamrecorder_destroy_recorder_pipeline(handle);
1126 if (ret != MM_ERROR_NONE)
1127 goto _ERR_STREAMRECORDER_VIDEO_COMMAND;
1129 /* remove target file */
1130 if (finfo->filename) {
1131 _mmstreamrec_dbg_log("file delete(%s)", finfo->filename);
1132 unlink(finfo->filename);
1133 g_free(finfo->filename);
1134 finfo->filename = NULL;
1137 sc->isMaxsizePausing = FALSE;
1138 sc->isMaxtimePausing = FALSE;
1140 info->video_frame_count = 0;
1142 info_audio->audio_frame_count = 0;
1148 case _MM_STREAMRECORDER_CMD_COMMIT:
1149 /* video recording command */
1152 if (info->b_commiting) {
1153 _mmstreamrec_dbg_err("now on commiting previous file!!(command : %d)", command);
1154 return MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING;
1156 _mmstreamrec_dbg_log("_MM_STREAMRECORDER_CMD_COMMIT : start");
1157 info->b_commiting = TRUE;
1160 for (count = 0; count <= hstreamrecorder->ini.retrial_count; count++) {
1161 if (sc->audio_enable == FALSE) {
1162 /* check only video frame */
1163 if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame) {
1165 } else if (count == hstreamrecorder->ini.retrial_count) {
1166 _mmstreamrec_dbg_err("Commit fail, frame count is %" G_GUINT64_FORMAT "", info->video_frame_count);
1167 info->b_commiting = FALSE;
1168 return MM_ERROR_STREAMRECORDER_INVALID_CONDITION;
1170 _mmstreamrec_dbg_warn("Waiting for enough video frame, retrial [%d], frame %" G_GUINT64_FORMAT "", count, info->video_frame_count);
1173 usleep(hstreamrecorder->ini.video_frame_wait_time);
1175 /* check both of video and audio frame */
1176 if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame && info_audio->audio_frame_count) {
1178 } else if (count == hstreamrecorder->ini.retrial_count) {
1179 _mmstreamrec_dbg_err("Commit fail, VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]", info->video_frame_count, info_audio->audio_frame_count);
1181 info->b_commiting = FALSE;
1182 return MM_ERROR_STREAMRECORDER_INVALID_CONDITION;
1184 _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);
1187 usleep(hstreamrecorder->ini.video_frame_wait_time);
1191 if (sc->error_occurs) {
1192 GstPad *video = NULL;
1193 GstPad *audio = NULL;
1195 _mmstreamrec_dbg_err("Committing Error case");
1197 video = gst_element_get_static_pad(sc->element[_MMSTREAMRECORDER_VIDEOSINK_SINK].gst, "sink");
1198 ret = gst_pad_send_event(video, gst_event_new_eos());
1199 _mmstreamrec_dbg_err("Sending EOS video sink : %d", ret);
1200 gst_object_unref(video);
1202 video = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "src");
1203 gst_pad_push_event(video, gst_event_new_flush_start());
1204 gst_pad_push_event(video, gst_event_new_flush_stop(TRUE));
1205 ret = gst_pad_push_event(video, gst_event_new_eos());
1206 _mmstreamrec_dbg_err("Sending EOS video encoder src pad : %d", ret);
1207 gst_object_unref(video);
1209 if (sc->audio_enable == TRUE) {
1210 audio = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "src");
1211 gst_pad_push_event(audio, gst_event_new_flush_start());
1212 gst_pad_push_event(audio, gst_event_new_flush_stop(TRUE));
1213 ret = gst_element_send_event(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, gst_event_new_eos());
1214 _mmstreamrec_dbg_err("Sending EOS audio encoder src pad : %d", ret);
1215 gst_object_unref(audio);
1218 if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst != NULL) {
1219 ret = gst_element_send_event(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, gst_event_new_eos());
1220 _mmstreamrec_dbg_warn("send eos to appsrc result : %d", ret);
1223 if (sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst != NULL) {
1224 pad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, "src");
1225 ret = gst_element_send_event(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, gst_event_new_eos());
1226 gst_object_unref(pad);
1229 _mmstreamrec_dbg_warn("send eos to audiosrc result : %d", ret);
1234 _mmstreamrec_dbg_log("Start to wait EOS");
1235 ret = _mmstreamrecorder_get_eos_message(handle);
1236 if (ret != MM_ERROR_NONE) {
1237 info->b_commiting = FALSE;
1238 goto _ERR_STREAMRECORDER_VIDEO_COMMAND;
1243 ret = MM_ERROR_STREAMRECORDER_INVALID_ARGUMENT;
1246 return MM_ERROR_NONE;
1248 _ERR_STREAMRECORDER_VIDEO_COMMAND:
1249 if (ret != MM_ERROR_NONE)
1250 _mmstreamrec_dbg_err("Current Videosrc status");
1255 int _mmstreamrecorder_video_handle_eos(MMHandleType handle)
1257 int ret = MM_ERROR_NONE;
1259 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1260 _MMStreamRecorderSubContext *sc = NULL;
1261 _MMStreamRecorderVideoInfo *info = NULL;
1262 _MMStreamRecorderAudioInfo *info_audio = NULL;
1263 _MMStreamRecorderFileInfo *finfo = NULL;
1264 _MMStreamRecorderMsgItem msg;
1265 MMStreamRecordingReport *report = NULL;
1267 mmf_return_val_if_fail(hstreamrecorder, FALSE);
1269 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1270 mmf_return_val_if_fail(sc, FALSE);
1271 mmf_return_val_if_fail(sc->info_video, FALSE);
1272 if (sc->audio_enable == TRUE)
1273 mmf_return_val_if_fail(sc->info_audio, FALSE);
1275 mmf_return_val_if_fail(sc->info_file, FALSE);
1277 info = sc->info_video;
1278 if (sc->audio_enable == TRUE)
1279 info_audio = sc->info_audio;
1281 finfo = sc->info_file;
1283 _mmstreamrec_dbg_err("");
1285 /* remove blocking part */
1286 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1288 ret = _mmstreamrecorder_destroy_recorder_pipeline(handle);
1289 if (ret != MM_ERROR_NONE)
1290 _mmstreamrec_dbg_warn("_mmstreamrecorder_destroy_recorder_pipeline failed. error[%x]", ret);
1292 /* Send recording report to application */
1293 msg.id = MM_MESSAGE_STREAMRECORDER_VIDEO_CAPTURED;
1294 report = (MMStreamRecordingReport *) g_malloc(sizeof(MMStreamRecordingReport));
1296 _mmstreamrec_dbg_err("Recording report fail(%s). Out of memory.", finfo->filename);
1298 report->recording_filename = g_strdup(finfo->filename);
1299 msg.param.data = report;
1301 _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1305 sc->pipeline_time = 0;
1307 sc->isMaxsizePausing = FALSE; /*In async function, this variable should set in callback function. */
1308 sc->isMaxtimePausing = FALSE;
1309 sc->error_occurs = FALSE;
1311 info->video_frame_count = 0;
1313 info_audio->audio_frame_count = 0;
1316 g_free(finfo->filename);
1317 finfo->filename = NULL;
1318 info->b_commiting = FALSE;
1320 _mmstreamrec_dbg_err("_mmstreamrecorder_video_handle_eos : end");
1325 int _mmstreamrecorder_push_videostream_buffer(MMHandleType handle, unsigned long timestamp, GstBuffer *buffer, int size)
1327 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1328 _MMStreamRecorderSubContext *sc = NULL;
1329 /* GstPad *srcpad = NULL; */
1330 GstCaps *srccaps = NULL;
1331 char *err_name = NULL;
1334 int video_width = 0;
1335 int video_height = 0;
1336 int ret = MM_ERROR_NONE;
1337 int video_source_format = 0;
1339 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1341 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1342 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1344 if (buffer == NULL || size == 0) {
1345 _mmstreamrec_dbg_err("video : Buffer is %p , size %d, time stamp is %ld", buffer, size, timestamp);
1346 return MM_ERROR_STREAMRECORDER_RESOURCE_CREATION;
1349 _mmstreamrec_dbg_log("video : Buffer is %p , size %d, time stamp is %ld", buffer, size, timestamp);
1351 /* check element availability */
1352 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);
1354 if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst) {
1356 /*_mmstreamrec_dbg_log("Buffer Push start , time stamp %ld",timestamp);*/
1357 /* srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "src"); */
1358 /* srccaps = gst_pad_get_current_caps(srcpad); */
1359 srccaps = gst_set_videosrcpad_caps(video_src, video_width, video_height, video_fps, 1);
1361 gst_app_src_set_caps((GstAppSrc *) sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, srccaps);
1362 gst_caps_unref(srccaps);
1366 /*_mmstreamrec_dbg_err("newbuf streamrecorder(%p) ",newbuf);*/
1367 ret = gst_app_src_push_buffer((GstAppSrc *) sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, buffer);
1369 _mmstreamrec_dbg_err("video gst_app_src_push_buffer %d", ret);
1370 ret = MM_ERROR_STREAMRECORDER_VIDEOBUFFER_PUSH;
1373 /* g_signal_emit_by_name(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "push-buffer", newbuf, &ret); */
1379 int _mmstreamrecorder_push_audiostream_buffer(MMHandleType handle, unsigned long timestamp, GstBuffer *buffer, int size)
1381 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1382 _MMStreamRecorderSubContext *sc = NULL;
1383 _MMStreamRecorderAudioInfo *info = NULL;
1384 GstFlowReturn err = GST_FLOW_OK;
1385 GstPad *srcpad = NULL;
1386 GstCaps *srccaps = NULL;
1391 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1393 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1394 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1396 info = (_MMStreamRecorderAudioInfo *) sc->info_audio;
1397 mmf_return_val_if_fail(info, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1399 rate = info->iSamplingRate;
1400 depth = info->audio_encode_depth;
1401 channel = info->iChannels;
1403 /*_mmstreamrec_dbg_log("Audio Buffer Push start , time stamp %ld",timestamp); */
1405 if (sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst) {
1407 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, "src");
1408 /* TODO : CHANNEL , WIDTH, DATATYPE */
1409 srccaps = gst_pad_get_current_caps(srcpad);
1410 srccaps = gst_set_audiosrcpad_caps(rate, channel, depth, 16, 1);
1411 gst_base_src_set_caps(GST_BASE_SRC(srcpad), srccaps);
1413 err = gst_app_src_push_buffer((GstAppSrc *) sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, buffer);
1416 _mmstreamrec_dbg_err("Audio gst_app_src_push_buffer %d", err);
1417 return MM_ERROR_STREAMRECORDER_AUDIOBUFFER_PUSH;
1421 return MM_ERROR_NONE;