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 : %p", 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;
164 int video_src_format = 0;
166 int filename_size = 0;
167 gboolean audio_enable = FALSE;
169 GstPad *srcpad = NULL;
170 GstPad *sinkpad = NULL;
171 GstCaps *caps = NULL;
172 GList *element_list = NULL;
173 GstStructure* pulse_property = NULL;
174 unsigned int video_codec = MM_VIDEO_CODEC_INVALID;
175 unsigned int file_format = MM_FILE_FORMAT_INVALID;
176 char *err_name = NULL;
177 char *filename = NULL;
178 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
179 _MMStreamRecorderSubContext *sc = NULL;
181 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
183 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
184 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
186 _mmstreamrec_dbg_warn("start");
188 err = mm_streamrecorder_get_attributes(handle, &err_name, MMSTR_VIDEO_ENCODER, &video_codec, MMSTR_FILE_FORMAT, &file_format, MMSTR_RECORDER_MODE, &rec_mode, NULL);
189 if (err != MM_ERROR_NONE) {
190 _mmstreamrec_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
195 if (rec_mode == MM_STREAMRECORDER_MODE_STREAM_BUFFER) {
196 _mmstreamrec_dbg_log("Recording Mode [%d]", MM_STREAMRECORDER_MODE_STREAM_BUFFER);
197 err = _mmstreamrecorder_check_videocodec_fileformat_compatibility(video_codec, file_format);
198 if (err != MM_ERROR_NONE)
202 _MMSTREAMRECORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCODE_MAIN_PIPE, "recorder_pipeline", err);
204 /* get audio disable */
205 mm_streamrecorder_get_attributes(handle, NULL, MMSTR_AUDIO_ENABLE, &audio_enable, NULL);
206 sc->audio_enable = audio_enable;
208 _mmstreamrec_dbg_log("AUDIO DISABLE : %d", sc->audio_enable);
210 if (sc->audio_enable == TRUE) {
211 /* create audiosrc bin */
212 err = _mmstreamrecorder_create_audiosrc_bin((MMHandleType) hstreamrecorder);
213 if (err != MM_ERROR_NONE)
217 err = _mmstreamrecorder_create_encodesink_bin((MMHandleType) hstreamrecorder, MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO);
218 if (err != MM_ERROR_NONE)
221 if (sc->audio_enable == TRUE)
222 gst_bin_add(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst);
224 /* add element and encodesink bin to encode main pipeline */
225 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);
227 /* Link each element : appsrc - capsfilter - encodesink bin */
228 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "src");
229 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, "sink");
230 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
232 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, "src");
233 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, "video_sink0");
234 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
236 if (sc->audio_enable == TRUE) {
237 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, "src");
238 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, "audio_sink0");
239 _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
242 if (sc->audio_enable == TRUE) {
243 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "sink");
244 MMSTREAMRECORDER_ADD_BUFFER_PROBE(sinkpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_audioque_dataprobe, hstreamrecorder);
245 gst_object_unref(sinkpad);
248 if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC_QUE].gst) {
249 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC_QUE].gst, "src");
250 MMSTREAMRECORDER_ADD_EVENT_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_eventprobe_monitor, hstreamrecorder);
251 gst_object_unref(srcpad);
256 if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC_QUE].gst) {
257 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC_QUE].gst, "src");
258 MMSTREAMRECORDER_ADD_EVENT_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_eventprobe_monitor, hstreamrecorder);
259 gst_object_unref(srcpad);
263 if (sc->audio_enable == FALSE) {
264 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "sink");
265 MMSTREAMRECORDER_ADD_BUFFER_PROBE(sinkpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_video_dataprobe_audio_disable, hstreamrecorder);
266 gst_object_unref(sinkpad);
270 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "src");
271 MMSTREAMRECORDER_ADD_BUFFER_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_video_dataprobe_record, hstreamrecorder);
272 gst_object_unref(srcpad);
275 if (sc->audio_enable == TRUE) {
276 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "src");
277 MMSTREAMRECORDER_ADD_BUFFER_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_audio_dataprobe_check, hstreamrecorder);
278 gst_object_unref(srcpad);
281 } else if (rec_mode == MM_STREAMRECORDER_MODE_DEVICE_LOOPBACK) {
282 _mmstreamrec_dbg_log("Recording Mode [%d]", MM_STREAMRECORDER_MODE_DEVICE_LOOPBACK);
283 err = mm_streamrecorder_get_attributes(handle, NULL, MMSTR_VIDEO_RESOLUTION_WIDTH, &width, MMSTR_VIDEO_RESOLUTION_HEIGHT, &height, MMSTR_AUDIO_ENABLE, &audio_enable, MMSTR_VIDEO_SOURCE_FORMAT, &video_src_format, MMSTR_VIDEO_FRAMERATE, &frame_rate, MMSTR_FILENAME, &filename, &filename_size, NULL);
284 _mmstreamrec_dbg_log("width [%d], height [%d], audio enable[%d], format [%d], framerate [%d] filename [%s]", width, height, audio_enable, video_src_format, frame_rate, filename);
286 _MMSTREAMRECORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCODE_MAIN_PIPE, "recorder_pipeline", err);
288 if (!hstreamrecorder->ini.hw_encoder_supported) {
289 _mmstreamrec_dbg_log("Screen is recorded with SW encoder.");
291 _mmstreamrec_dbg_log("Audio is enabled!");
294 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_SRC, "pulsesrc", "audio_source", element_list, err);
296 pulse_property = gst_structure_new_from_string("props,media.role=loopback-mirroring");
297 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst, "stream-properties", pulse_property);
298 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst, "do-timestamp", true);
299 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst, "provide-clock", false);
301 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_CONV, "audioconvert", "audio_converter", element_list, err);
302 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_ENC, "avenc_aac", "audio_encoder", element_list, err);
303 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_ENC].gst, "compliance", -2);
305 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_QUE, "queue", "audio_queue", element_list, err);
307 gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst),
308 sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst,
309 sc->encode_element[_MMSTREAMRECORDER_AUDIO_CONV].gst,
310 sc->encode_element[_MMSTREAMRECORDER_AUDIO_ENC].gst,
311 sc->encode_element[_MMSTREAMRECORDER_AUDIO_QUE].gst, NULL);
315 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_SRC, "waylandsrc", "video_source", element_list, err);
316 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_CAPS, "capsfilter", "video_capsfilter", element_list, err);
318 caps = gst_set_videosrcpad_caps_sw(MM_STREAMRECORDER_INPUT_FORMAT_BGRA, width, height, frame_rate, 1);
319 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_VIDEO_CAPS].gst, "caps", caps);
320 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_CONV, "videoconvert", "video_conveter", element_list, err);
321 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_ENC, "avenc_mpeg4", "video_encoder", element_list, err);
322 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_QUE, "queue", "video_queue", element_list, err);
324 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_MUX, "avimux", "av_muxer", element_list, err);
326 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_SINK, "filesink", "av_sink", element_list, err);
327 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_SINK].gst, "location", filename);
330 gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst),
331 sc->encode_element[_MMSTREAMRECORDER_VIDEO_SRC].gst,
332 sc->encode_element[_MMSTREAMRECORDER_VIDEO_CAPS].gst,
333 sc->encode_element[_MMSTREAMRECORDER_VIDEO_CONV].gst,
334 sc->encode_element[_MMSTREAMRECORDER_VIDEO_ENC].gst,
335 sc->encode_element[_MMSTREAMRECORDER_VIDEO_QUE].gst, NULL);
337 gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst),
338 sc->encode_element[_MMSTREAMRECORDER_MUX].gst,
339 sc->encode_element[_MMSTREAMRECORDER_SINK].gst, NULL);
341 if (!_MM_GST_ELEMENT_LINK_MANY(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst),
342 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_CONV].gst),
343 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_ENC].gst),
344 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_QUE].gst), NULL)) {
345 _mmstreamrec_dbg_log("AUDIO PIPELINE LINK MANY FAILED");
348 if (!_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_QUE].gst),
349 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_MUX].gst))) {
350 _mmstreamrec_dbg_log("LINK BETWEEN AUDIO QUE AND MUX FAILED");
354 if (!_MM_GST_ELEMENT_LINK_MANY(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_SRC].gst),
355 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_CAPS].gst),
356 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_CONV].gst),
357 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_ENC].gst),
358 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_QUE].gst), NULL)) {
359 _mmstreamrec_dbg_log("VIDEO PIPELINE LINK MANY FAILED");
362 if (!_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_QUE].gst),
363 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_MUX].gst))) {
364 _mmstreamrec_dbg_log("LINK BETWEEN VIDEO QUE AND MUX FAILED");
367 if (!_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_MUX].gst),
368 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_SINK].gst))) {
369 _mmstreamrec_dbg_log("LINK BETWEEN MUX AND SINK FAILED");
372 _mmstreamrec_dbg_log("Screen is recorded with HW encoder.");
374 _mmstreamrec_dbg_log("Audio is enabled!");
377 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_SRC, "pulsesrc", "audio_source", element_list, err);
379 pulse_property = gst_structure_new_from_string("props,media.role=loopback-mirroring");
380 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst, "stream-properties", pulse_property);
381 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst, "do-timestamp", true);
382 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst, "provide-clock", false);
384 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_CONV, "audioconvert", "audio_converter", element_list, err);
386 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_ENC, "avenc_aac", "audio_encoder", element_list, err);
387 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_ENC].gst, "compliance", -2);
389 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_QUE, "queue", "audio_queue", element_list, err);
391 gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst),
392 sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst,
393 sc->encode_element[_MMSTREAMRECORDER_AUDIO_CONV].gst,
394 sc->encode_element[_MMSTREAMRECORDER_AUDIO_ENC].gst,
395 sc->encode_element[_MMSTREAMRECORDER_AUDIO_QUE].gst,
396 sc->encode_element[_MMSTREAMRECORDER_VIDEO_SRC].gst, NULL);
399 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_SRC, "waylandsrc", "video_source", element_list, err);
401 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_CAPS, "capsfilter", "video_capsfilter", element_list, err);
403 caps = gst_set_videosrcpad_caps_hw(hstreamrecorder->ini.video_codec_element_hw, width, height, frame_rate, 1);
404 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_VIDEO_CAPS].gst, "caps", caps);
406 if (!g_strcmp0(hstreamrecorder->ini.video_codec_element_hw, "sprd")){
407 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_ENC, "sprdenc_h264", "video_encoder", element_list, err);
409 _mmstreamrec_dbg_warn("no matched hw codec element found.");
410 goto pipeline_creation_error;
413 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_QUE, "queue", "video_queue", element_list, err);
415 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_MUX, "avmux_mp4", "av_muxer", element_list, err);
417 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_SINK, "filesink", "av_sink", element_list, err);
418 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_SINK].gst, "location", filename);
420 gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst),
421 sc->encode_element[_MMSTREAMRECORDER_VIDEO_SRC].gst,
422 sc->encode_element[_MMSTREAMRECORDER_VIDEO_CAPS].gst,
423 sc->encode_element[_MMSTREAMRECORDER_VIDEO_ENC].gst,
424 sc->encode_element[_MMSTREAMRECORDER_VIDEO_QUE].gst, NULL);
426 gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst),
427 sc->encode_element[_MMSTREAMRECORDER_MUX].gst,
428 sc->encode_element[_MMSTREAMRECORDER_SINK].gst, NULL);
430 if (!_MM_GST_ELEMENT_LINK_MANY(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst),
431 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_CONV].gst),
432 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_ENC].gst),
433 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_QUE].gst), NULL)) {
434 _mmstreamrec_dbg_log("AUDIO PIPELINE LINK MANY FAILED");
437 if (!_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_QUE].gst),
438 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_MUX].gst))) {
439 _mmstreamrec_dbg_log("LINK BETWEEN AUDIO QUE AND MUX FAILED");
443 if (!_MM_GST_ELEMENT_LINK_MANY(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_SRC].gst),
444 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_CAPS].gst),
445 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_ENC].gst),
446 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_QUE].gst), NULL)) {
447 _mmstreamrec_dbg_log("VIDEO PIPELINE LINK MANY FAILED");
450 if (!_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_QUE].gst),
451 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_MUX].gst))) {
452 _mmstreamrec_dbg_log("LINK BETWEEN VIDEO QUE AND MUX FAILED");
455 if (!_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_MUX].gst),
456 GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_SINK].gst))) {
457 _mmstreamrec_dbg_log("LINK BETWEEN MUX AND SINK FAILED");
462 bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst));
464 /* register pipeline message callback */
465 hstreamrecorder->encode_pipeline_cb_event_id = gst_bus_add_watch(bus, (GstBusFunc) _mmstreamrecorder_pipeline_cb_message, hstreamrecorder);
467 gst_object_unref(bus);
469 return MM_ERROR_NONE;
471 pipeline_creation_error:
472 for (i = _MMSTREAMRECORDER_AUDIOSRC_BIN; i <= _MMSTREAMRECORDER_ENCSINK_SINK; i++)
473 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, i);
475 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCODE_MAIN_PIPE);
479 int _mmstreamrecorder_destroy_recorder_pipeline(MMHandleType handle)
481 int ret = MM_ERROR_NONE;
482 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
483 _MMStreamRecorderSubContext *sc = NULL;
487 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
488 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
489 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
491 _mmstreamrec_dbg_log("start");
493 if (!sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst) {
494 _mmstreamrec_dbg_warn("pipeline is not existed.");
495 return MM_ERROR_NONE;
498 _mmstreamrecorder_remove_all_handlers((MMHandleType) hstreamrecorder, _MMSTREAMRECORDER_HANDLER_VIDEOREC);
500 ret = _mmstreamrecorder_gst_set_state(handle, sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_NULL);
501 if (ret != MM_ERROR_NONE) {
502 _mmstreamrec_dbg_err("Faile to change encode main pipeline [0x%x]", ret);
506 bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst));
508 /* Remove remained message */
510 GstMessage *gst_msg = NULL;
511 while ((gst_msg = gst_bus_pop(bus)) != NULL) {
512 _mmstreamrecorder_pipeline_cb_message(bus, gst_msg, (gpointer) hstreamrecorder);
513 gst_message_unref(gst_msg);
516 gst_object_unref(bus);
520 /* remove audio pipeline first */
521 ret = _mmstreamrecorder_destroy_audiosrc_bin(handle);
522 if (ret != MM_ERROR_NONE) {
523 _mmstreamrec_dbg_err("Fail to remove audio pipeline");
527 ret = _mmstreamrecorder_destroy_encodesink_bin(handle);
528 if (ret != MM_ERROR_NONE) {
529 _mmstreamrec_dbg_err("Fail to remove encoder pipeline");
533 /* Remove pipeline message callback */
534 if (hstreamrecorder->encode_pipeline_cb_event_id != 0) {
535 g_source_remove(hstreamrecorder->encode_pipeline_cb_event_id);
536 hstreamrecorder->encode_pipeline_cb_event_id = 0;
539 _mmstreamrec_dbg_log("done");
544 int _mmstreamrecorder_create_encodesink_bin(MMHandleType handle, MMStreamRecorderEncodebinProfile profile)
546 int err = MM_ERROR_NONE;
554 int video_height = 0;
557 int audio_src_format = 0;
558 int video_src_format = 0;
559 int audio_samplerate = 0;
560 const char *str_profile = NULL;
561 const char *str_aac = NULL;
562 const char *str_aar = NULL;
563 const char *str_acs = NULL;
564 char *err_name = NULL;
565 int ret = MM_ERROR_NONE;
566 GstCaps *caps = NULL;
568 GList *element_list = NULL;
569 char *temp_filename = NULL;
576 _MMStreamRecorderVideoInfo *info = NULL;
577 _MMStreamRecorderFileInfo *finfo = NULL;
579 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
580 _MMStreamRecorderSubContext *sc = NULL;
581 /* type_element *VideoencElement = NULL; */
582 /* type_element *AudioencElement = NULL; */
583 /* type_element *MuxElement = NULL; */
584 /* type_element *RecordsinkElement = NULL; */
586 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
588 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
589 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
591 _mmstreamrec_dbg_log("start - profile : %d", profile);
593 info = sc->info_video;
594 finfo = sc->info_file;
596 /* check element availability */
597 ret = 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);
598 if (ret != MM_ERROR_NONE) {
599 _mmstreamrec_dbg_err("Get attrs fail. (%s:%x)", err_name, ret);
604 _mmstreamrec_dbg_err("audio encoder - %d , video encoder : %d", audio_enc, video_enc);
605 _mmstreamrec_dbg_err("audio channel - %d , video v_bitrate : %d", channel, v_bitrate);
606 _mmstreamrec_dbg_err("audio a_bitrate - %d , video video_width : %d ,video video_height : %d ", a_bitrate, video_width, video_height);
607 _mmstreamrec_dbg_err("video_fps - %d , video file_format : %d", video_fps, file_format);
609 /* Check existence */
610 if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst) {
611 if (((GObject *) sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst)->ref_count > 0)
612 gst_object_unref(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst);
614 _mmstreamrec_dbg_log("_MMSTREAMRECORDER_ENCSINK_BIN is Already existed.");
617 /* Create bin element */
618 _MMSTREAMRECORDER_BIN_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_BIN, "encodesink_bin", err);
620 /* Create child element */
621 if (hstreamrecorder->ini.encsink_bin_profile != MM_STREAMRECORDER_ENCBIN_PROFILE_AUDIO) {
622 /* create appsrc and capsfilter */
623 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SRC, hstreamrecorder->ini.name_of_encsink_src, "encodesink_src", element_list, err);
624 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_FILT, "capsfilter", "encodesink_filter", element_list, err);
626 caps = gst_set_videosrcpad_caps_sw(video_src_format, video_width, video_height, video_fps, 1);
627 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "caps", caps);
629 gst_caps_unref(caps);
633 caps = gst_set_videosrcpad_caps_sw(video_src_format, video_width, video_height, video_fps, 1);
634 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, "caps", caps);
636 gst_caps_unref(caps);
641 /* release element_list, they will be placed out of encodesink bin */
643 g_list_free(element_list);
646 if (rec_mode == MM_STREAMRECORDER_MODE_STREAM_BUFFER) {
647 /* set appsrc as live source */
648 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "is-live", hstreamrecorder->ini.encsink_src_islive);
653 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_ENCBIN, "encodebin", "encodesink_encbin", element_list, err);
655 _mmstreamrec_dbg_log("Profile[%d]", profile);
657 /* Set information */
658 if (hstreamrecorder->ini.encsink_bin_profile == MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO) {
659 str_profile = "VideoProfile";
660 str_aac = "VideoAutoAudioConvert";
661 str_aar = "VideoAutoAudioResample";
662 str_acs = "VideoAutoColorSpace";
663 } else if (hstreamrecorder->ini.encsink_bin_profile == MM_STREAMRECORDER_ENCBIN_PROFILE_AUDIO) {
664 str_profile = "AudioProfile";
665 str_aac = "AudioAutoAudioConvert";
666 str_aar = "AudioAutoAudioResample";
667 str_acs = "AudioAutoColorSpace";
670 /* TODO : check the last value ( set ) */
671 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "profile", hstreamrecorder->ini.encsink_bin_profile);
672 if (rec_mode == MM_STREAMRECORDER_MODE_STREAM_BUFFER)
673 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", hstreamrecorder->ini.encsink_bin_auto_audio_convert);
675 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-resample", hstreamrecorder->ini.encsink_bin_auto_audio_resample);
676 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-colorspace", hstreamrecorder->ini.encsink_bin_auto_colorspace);
677 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "use-video-toggle", hstreamrecorder->ini.encsink_bin_use_video_toggle);
680 if (hstreamrecorder->ini.encsink_bin_profile == MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO) {
682 case MM_VIDEO_CODEC_H263:
683 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "venc-name", hstreamrecorder->ini.h263_video_encoder);
685 case MM_VIDEO_CODEC_H264:
686 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "venc-name", hstreamrecorder->ini.h264_video_encoder);
688 case MM_VIDEO_CODEC_MPEG4:
689 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "venc-name", hstreamrecorder->ini.mpeg4_video_encoder);
692 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "venc-name", hstreamrecorder->ini.h264_video_encoder);
695 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_VENC, "video-encode", err);
697 /* set color converter size */
698 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "vconv-name", hstreamrecorder->ini.name_of_encsink_bin_video_converter);
699 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_VCONV, "video-convert", err);
701 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-colorspace", hstreamrecorder->ini.encsink_bin_auto_colorspace);
703 if (video_src_format == MM_STREAMRECORDER_INPUT_FORMAT_NV12)
704 video_src_format = MM_STREAMRECORDER_INPUT_FORMAT_I420;
706 caps = gst_set_videosrcpad_caps_sw(video_src_format, video_width, video_height, video_fps, 1);
707 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "vcaps", caps);
708 if (video_src_format != MM_STREAMRECORDER_INPUT_FORMAT_NV12)
709 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VCONV].gst, "dst-buffer-num", hstreamrecorder->ini.convert_output_buffer_num);
712 err = gst_pad_set_caps(gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "sink"), caps);
714 /* MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "state-tuning", TRUE); */
717 gst_caps_unref(caps);
720 _mmstreamrec_dbg_log("size %dx%d, dst-buffer-num %d", video_width, video_height, hstreamrecorder->ini.convert_output_buffer_num);
722 _mmstreamrec_dbg_warn("encoder set caps result : 0x%x", err);
724 if (hstreamrecorder->ini.encsink_bin_use_parser[0]) {
725 GstElement *parser = gst_element_factory_make(hstreamrecorder->ini.encsink_bin_use_parser, "parse");
726 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "use-venc-queue", parser);
727 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_PARSER, "use-venc-queue", err);
731 if (sc->audio_enable == TRUE) {
733 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "aenc-name", hstreamrecorder->ini.name_of_encsink_bin_audio_encoder);
734 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_AENC, "audio-encode", err);
735 _mmstreamrec_dbg_err("audio-encode err = %x ", err);
737 /* Set basic infomation */
738 if (audio_enc != MM_AUDIO_CODEC_VORBIS) {
741 if (audio_src_format == MM_STREAMRECORDER_AUDIO_FORMAT_PCM_S16_LE) {
743 } else { /* MM_STREAMRECORDER_AUDIO_FORMAT_PCM_U8 */
747 /* TODO : set rate , channel , depth */
749 caps = gst_set_audiosrcpad_caps(audio_samplerate, 2, depth, 16, 1);
750 /* MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE); */
751 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "acaps", caps);
753 gchar *type = gst_caps_to_string(caps);
754 _mmstreamrec_dbg_warn("Set srcpad caps: %s", type);
757 gst_caps_unref(caps);
760 /* what are the audio encoder which should get audio/x-raw-float? */
761 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);
762 _mmstreamrec_dbg_log("caps [x-raw-float, rate:%d, channel:%d, endianness:%d, width:32]", audio_samplerate, channel, BYTE_ORDER);
763 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE);
764 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "acaps", caps);
765 gst_caps_unref(caps);
770 if (audio_enc == MM_AUDIO_CODEC_AMR && channel == 2) {
771 caps = gst_caps_new_simple("audio/x-raw-int", "channels", G_TYPE_INT, 1, NULL);
772 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE);
773 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "acaps", caps);
774 gst_caps_unref(caps);
778 if (audio_enc == MM_AUDIO_CODEC_OGG) {
779 caps = gst_caps_new_simple("audio/x-raw-int", NULL);
780 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE);
781 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "acaps", caps);
782 gst_caps_unref(caps);
787 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_AENC_QUE, "use-aenc-queue", err);
791 switch (file_format) {
792 case MM_FILE_FORMAT_3GP:{
793 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "mux-name", hstreamrecorder->ini.name_of_encsink_bin_3GPMUXER);
797 case MM_FILE_FORMAT_MP4:{
798 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "mux-name", hstreamrecorder->ini.name_of_encsink_bin_MP4MUXER);
803 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "mux-name", hstreamrecorder->ini.name_of_encsink_bin_MP4MUXER);
808 _MMSTREAMRECORDER_ENCODEBIN_ELMGET(sc, _MMSTREAMRECORDER_ENCSINK_MUX, "mux", err);
812 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SINK, "filesink", NULL, element_list, err);
813 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SINK].gst, "async", 0);
815 err = mm_streamrecorder_get_attributes(handle, &err_name,
816 MMSTR_FILE_FORMAT, &fileformat, MMSTR_FILENAME, &temp_filename, &size,
817 MMSTR_TARGET_MAX_SIZE, &imax_size,
818 MMSTR_TARGET_TIME_LIMIT, &imax_time,
821 if (err != MM_ERROR_NONE) {
822 _mmstreamrec_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
827 finfo->fileformat = fileformat;
831 info->max_size = 0; /* do not check */
833 info->max_size = ((guint64) imax_size) << 10; /* to byte */
837 info->max_time = 0; /* do not check */
839 info->max_time = ((guint64) imax_time) * 1000; /* to millisecond */
841 finfo->filename = g_strdup(temp_filename);
842 if (!finfo->filename) {
843 _mmstreamrec_dbg_err("strdup was failed");
847 _mmstreamrec_dbg_log("Record start : set file name using attribute - %s ", finfo->filename);
849 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SINK].gst, "location", finfo->filename);
851 if (profile == MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO) {
852 /* video encoder attribute setting */
854 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "bitrate", v_bitrate);
856 _mmstreamrec_dbg_warn("video bitrate is too small[%d], so skip setting. Use DEFAULT value.", v_bitrate);
859 if (sc->audio_enable == TRUE) {
860 /* audio encoder attribute setting */
863 case MM_AUDIO_CODEC_AMR:
864 result = _mmstreamrecorder_get_amrnb_bitrate_mode(a_bitrate);
865 _mmstreamrec_dbg_log("Set AMR encoder mode [%d]", result);
866 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "band-mode", result);
868 case MM_AUDIO_CODEC_AAC:
869 _mmstreamrec_dbg_log("Set AAC encoder bitrate [%d]", a_bitrate);
870 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "bitrate", a_bitrate);
873 _mmstreamrec_dbg_log("Audio codec is not AMR or AAC... you need to implement setting function for audio encoder bit-rate");
877 _mmstreamrec_dbg_warn("Setting bitrate is too small, so skip setting. Use DEFAULT value.");
881 _mmstreamrec_dbg_log("Element creation complete");
883 /* Add element to bin */
884 if (!_mmstreamrecorder_add_elements_to_bin(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst), element_list)) {
885 _mmstreamrec_dbg_err("element add error.");
886 err = MM_ERROR_STREAMRECORDER_RESOURCE_CREATION;
887 goto pipeline_creation_error;
890 _mmstreamrec_dbg_log("Element add complete");
892 if (profile == MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO) {
893 pad = gst_element_get_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "video");
894 if (gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("video_sink0", pad)) < 0) {
895 gst_object_unref(pad);
897 _mmstreamrec_dbg_err("failed to create ghost video_sink0 on _MMSTREAMRECORDER_ENCSINK_BIN.");
898 err = MM_ERROR_STREAMRECORDER_GST_LINK;
899 goto pipeline_creation_error;
901 gst_object_unref(pad);
904 if (sc->audio_enable == TRUE) {
905 pad = gst_element_get_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "audio");
906 if (gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("audio_sink0", pad)) < 0) {
907 gst_object_unref(pad);
909 _mmstreamrec_dbg_err("failed to create ghost audio_sink0 on _MMSTREAMRECORDER_ENCSINK_BIN.");
910 err = MM_ERROR_STREAMRECORDER_GST_LINK;
911 goto pipeline_creation_error;
913 gst_object_unref(pad);
916 } else if (profile == MM_STREAMRECORDER_ENCBIN_PROFILE_AUDIO) {
917 pad = gst_element_get_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "audio");
918 if (gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("audio_sink0", pad)) < 0) {
919 gst_object_unref(pad);
921 _mmstreamrec_dbg_err("failed to create ghost audio_sink0 on _MMSTREAMRECORDER_ENCSINK_BIN.");
922 err = MM_ERROR_STREAMRECORDER_GST_LINK;
923 goto pipeline_creation_error;
925 gst_object_unref(pad);
929 pad = gst_element_get_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "image");
930 if (gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("image_sink0", pad)) < 0) {
931 gst_object_unref(pad);
933 _mmstreamrec_dbg_err("failed to create ghost image_sink0 on _MMSTREAMRECORDER_ENCSINK_BIN.");
934 err = MM_ERROR_STREAMRECORDER_GST_LINK;
935 goto pipeline_creation_error;
937 gst_object_unref(pad);
941 _mmstreamrec_dbg_log("Get pad complete");
943 /* Link internal element */
944 if (!_mmstreamrecorder_link_elements(element_list)) {
945 _mmstreamrec_dbg_err("element link error.");
946 err = MM_ERROR_STREAMRECORDER_GST_LINK;
947 goto pipeline_creation_error;
951 g_list_free(element_list);
955 _mmstreamrec_dbg_log("done");
957 return MM_ERROR_NONE;
959 pipeline_creation_error:
960 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_ENCBIN);
961 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SRC);
962 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_FILT);
963 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_VENC);
964 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_AENC);
965 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_IENC);
966 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_MUX);
967 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SINK);
968 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_BIN);
971 g_list_free(element_list);
978 int _mmstreamrecorder_destroy_encodesink_bin(MMHandleType handle)
980 GstPad *reqpad = NULL;
981 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
982 _MMStreamRecorderSubContext *sc = NULL;
984 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
986 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
987 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
989 _mmstreamrec_dbg_log("");
991 if (sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst != NULL) {
992 /* release request pad */
993 reqpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "audio");
995 gst_element_release_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, reqpad);
996 gst_object_unref(reqpad);
1000 reqpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "video");
1002 gst_element_release_request_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, reqpad);
1003 gst_object_unref(reqpad);
1007 /* release encode main pipeline */
1008 gst_object_unref(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst);
1010 _mmstreamrec_dbg_log("Encoder pipeline removed");
1013 return MM_ERROR_NONE;
1016 int _mmstreamrecorder_create_audiosrc_bin(MMHandleType handle)
1018 int err = MM_ERROR_NONE;
1023 unsigned int a_enc = MM_AUDIO_CODEC_INVALID;
1024 unsigned int file_format = MM_FILE_FORMAT_INVALID;
1025 char *err_name = NULL;
1028 GstCaps *caps = NULL;
1030 GList *element_list = NULL;
1032 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1033 _MMStreamRecorderSubContext *sc = NULL;
1034 _MMStreamRecorderGstElement *last_element = NULL;
1035 /* type_element *AudiosrcElement = NULL; */
1037 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1039 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1040 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1042 _mmstreamrec_dbg_log("");
1044 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);
1046 if (err != MM_ERROR_NONE) {
1047 _mmstreamrec_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
1048 SAFE_FREE(err_name);
1052 err = _mmstreamrecorder_check_audiocodec_fileformat_compatibility(a_enc, file_format);
1053 if (err != MM_ERROR_NONE) {
1054 _mmstreamrec_dbg_err("error name :%s , audio format %d , fileformat %d. error : %x)", err_name, a_enc, file_format, err);
1055 SAFE_FREE(err_name);
1059 /* Check existence */
1060 if (sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst) {
1061 if (((GObject *) sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst)->ref_count > 0)
1062 gst_object_unref(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst);
1064 _mmstreamrec_dbg_log("_MMSTREAMRECORDER_AUDIOSRC_BIN is Already existed. Unref once...");
1067 /* Create bin element */
1068 _MMSTREAMRECORDER_BIN_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_BIN, "audiosource_bin", err);
1070 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_SRC, "appsrc", hstreamrecorder->ini.name_of_audio_src, element_list, err);
1072 _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_FILT, "capsfilter", "audiosrc_capsfilter", element_list, err);
1074 /* Set basic infomation */
1075 if (a_enc != MM_AUDIO_CODEC_VORBIS) {
1078 if (format == MM_STREAMRECORDER_AUDIO_FORMAT_PCM_S16_LE) {
1080 } else { /* MM_STREAMRECORDER_AUDIO_FORMAT_PCM_U8 */
1084 caps = gst_set_audiosrcpad_caps(rate, channel, depth, 16, 1);
1086 _mmstreamrec_dbg_log("caps [x-raw-int, rate:%d, channel:%d, depth:%d]", rate, channel, depth);
1088 /* what are the audio encoder which should get audio/x-raw-float? */
1089 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);
1090 _mmstreamrec_dbg_log("caps [x-raw-float, rate:%d, channel:%d, endianness:%d, width:32]", rate, channel, BYTE_ORDER);
1094 if (rec_mode == MM_STREAMRECORDER_MODE_STREAM_BUFFER)
1095 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "caps", caps);
1097 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_FILT].gst), "caps", caps);
1099 gchar *type = gst_caps_to_string(caps);
1100 _mmstreamrec_dbg_err("_MMSTREAMRECORDER_AUDIOSRC_FILT %s", type);
1103 gst_caps_unref(caps);
1106 _mmstreamrec_dbg_err("create caps error");
1107 err = MM_ERROR_STREAMRECORDER_RESOURCE_CREATION;
1108 goto pipeline_creation_error;
1111 if (rec_mode == MM_STREAMRECORDER_MODE_DEVICE_LOOPBACK) {
1112 #if 1 /* mic mode */
1113 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "do-timestamp", TRUE);
1114 #else /* speaker mode with alsasrc */
1115 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "device", "hw:0,8");
1116 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "latency-time", 256000);
1117 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "buffer-time", 10000);
1118 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "do-timestamp", FALSE);
1121 MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "do-timestamp", FALSE);
1124 if (!_mmstreamrecorder_add_elements_to_bin(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst), element_list)) {
1125 _mmstreamrec_dbg_err("element add error.");
1126 err = MM_ERROR_STREAMRECORDER_RESOURCE_CREATION;
1127 goto pipeline_creation_error;
1130 if (!_mmstreamrecorder_link_elements(element_list)) {
1131 _mmstreamrec_dbg_err("element link error.");
1132 err = MM_ERROR_STREAMRECORDER_GST_LINK;
1133 goto pipeline_creation_error;
1136 last_element = (_MMStreamRecorderGstElement *) (g_list_last(element_list)->data);
1137 pad = gst_element_get_static_pad(last_element->gst, "src");
1138 if ((gst_element_add_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, gst_ghost_pad_new("src", pad))) < 0) {
1139 gst_object_unref(pad);
1141 _mmstreamrec_dbg_err("failed to create ghost pad on _MMSTREAMRECORDER_AUDIOSRC_BIN.");
1142 err = MM_ERROR_STREAMRECORDER_GST_LINK;
1143 goto pipeline_creation_error;
1146 gst_object_unref(pad);
1150 g_list_free(element_list);
1151 element_list = NULL;
1154 return MM_ERROR_NONE;
1156 pipeline_creation_error:
1157 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_SRC);
1158 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_FILT);
1159 _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_BIN);
1162 g_list_free(element_list);
1163 element_list = NULL;
1169 int _mmstreamrecorder_destroy_audiosrc_bin(MMHandleType handle)
1171 GstPad *srcpad = NULL;
1172 GstPad *sinkpad = NULL;
1173 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1174 _MMStreamRecorderSubContext *sc = NULL;
1176 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1178 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1179 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1181 _mmstreamrec_dbg_log("");
1183 if (sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst != NULL) {
1184 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, "src");
1185 sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, "audio_sink0");
1186 _MM_GST_PAD_UNLINK_UNREF(srcpad, sinkpad);
1188 /* release audiosrc bin */
1189 gst_bin_remove(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst);
1191 _mmstreamrecorder_remove_element_handle(handle, (void *)sc->encode_element, _MMSTREAMRECORDER_AUDIOSRC_BIN, _MMSTREAMRECORDER_AUDIOSRC_FILT);
1193 _mmstreamrec_dbg_log("Audio pipeline removed");
1196 return MM_ERROR_NONE;
1199 /* COMMAND - VIDEO */
1200 int _mmstreamrecorder_video_command(MMHandleType handle, int command)
1202 int ret = MM_ERROR_NONE;
1203 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1204 _MMStreamRecorderVideoInfo *info = NULL;
1205 _MMStreamRecorderAudioInfo *info_audio = NULL;
1206 _MMStreamRecorderFileInfo *finfo = NULL;
1207 _MMStreamRecorderSubContext *sc = NULL;
1208 GstElement *pipeline = NULL;
1211 gboolean audio_enable = FALSE;
1213 char *err_name = NULL;
1215 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1217 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1218 mmf_return_val_if_fail(sc && sc->encode_element, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1220 mmf_return_val_if_fail(sc->info_video, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1221 if (sc->audio_enable == TRUE)
1222 mmf_return_val_if_fail(sc->info_audio, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1224 mmf_return_val_if_fail(sc->info_file, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1226 ret = mm_streamrecorder_get_attributes(handle, &err_name, MMSTR_RECORDER_MODE, &rec_mode, MMSTR_AUDIO_ENABLE, &audio_enable, NULL);
1228 if (ret != MM_ERROR_NONE) {
1229 _mmstreamrec_dbg_err("Get attrs fail. (%s:%x)", err_name, ret);
1230 SAFE_FREE(err_name);
1234 info = sc->info_video;
1235 if (sc->audio_enable == TRUE)
1236 info_audio = sc->info_audio;
1238 finfo = sc->info_file;
1240 _mmstreamrec_dbg_log("command %d", command);
1242 pipeline = sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst;
1245 case _MM_STREAMRECORDER_CMD_RECORD:
1249 _mmstreamrec_dbg_log("Record Start");
1250 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1252 /* Adjust display FPS */
1253 info->video_frame_count = 0;
1255 info_audio->audio_frame_count = 0;
1258 sc->ferror_send = FALSE;
1259 sc->ferror_count = 0;
1260 sc->error_occurs = FALSE;
1261 sc->bget_eos = FALSE;
1262 ret = _mmstreamrecorder_gst_set_state(handle, sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PAUSED);
1263 ret = _mmstreamrecorder_gst_set_state(handle, sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PLAYING);
1264 if (ret != MM_ERROR_NONE) {
1265 /* Remove recorder pipeline and recording file which size maybe zero */
1266 ret = _mmstreamrecorder_destroy_recorder_pipeline(handle);
1268 if (finfo->filename) {
1269 _mmstreamrec_dbg_log("file delete(%s)", finfo->filename);
1270 unlink(finfo->filename);
1271 g_free(finfo->filename);
1272 finfo->filename = NULL;
1274 goto _ERR_STREAMRECORDER_VIDEO_COMMAND;
1279 case _MM_STREAMRECORDER_CMD_PAUSE:
1282 if (info->b_commiting) {
1283 _mmstreamrec_dbg_warn("now on commiting previous file!!(command : %d)", command);
1284 return MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING;
1287 for (count = 0; count <= hstreamrecorder->ini.retrial_count; count++) {
1288 if (sc->audio_enable == FALSE) {
1289 /* check only video frame */
1290 if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame) {
1292 } else if (count == hstreamrecorder->ini.retrial_count) {
1293 _mmstreamrec_dbg_err("Pause fail, frame count %" G_GUINT64_FORMAT "", info->video_frame_count);
1294 return MM_ERROR_STREAMRECORDER_INVALID_CONDITION;
1296 _mmstreamrec_dbg_warn("Waiting for enough video frame, retrial[%d], frame %" G_GUINT64_FORMAT "", count, info->video_frame_count);
1299 usleep(hstreamrecorder->ini.video_frame_wait_time);
1301 /* check both of video and audio frame */
1302 if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame && info_audio->audio_frame_count) {
1304 } else if (count == hstreamrecorder->ini.retrial_count) {
1305 _mmstreamrec_dbg_err("Pause fail, frame count VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]", info->video_frame_count, info_audio->audio_frame_count);
1306 return MM_ERROR_STREAMRECORDER_INVALID_CONDITION;
1308 _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);
1311 usleep(hstreamrecorder->ini.video_frame_wait_time);
1315 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "runtime-pause", TRUE);
1320 case _MM_STREAMRECORDER_CMD_CANCEL:
1322 if (info->b_commiting) {
1323 _mmstreamrec_dbg_warn("now on commiting previous file!!(command : %d)", command);
1324 return MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING;
1327 ret = _mmstreamrecorder_destroy_recorder_pipeline(handle);
1328 if (ret != MM_ERROR_NONE)
1329 goto _ERR_STREAMRECORDER_VIDEO_COMMAND;
1331 /* remove target file */
1332 if (finfo->filename) {
1333 _mmstreamrec_dbg_log("file delete(%s)", finfo->filename);
1334 unlink(finfo->filename);
1335 g_free(finfo->filename);
1336 finfo->filename = NULL;
1339 sc->isMaxsizePausing = FALSE;
1340 sc->isMaxtimePausing = FALSE;
1342 info->video_frame_count = 0;
1344 info_audio->audio_frame_count = 0;
1350 case _MM_STREAMRECORDER_CMD_COMMIT:
1351 /* video recording command */
1353 if(rec_mode == MM_STREAMRECORDER_MODE_DEVICE_LOOPBACK) {
1354 if (sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst != NULL) {\
1356 ret = gst_element_send_event(gst_bin_get_by_name(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), "audio_source"), gst_event_new_eos());
1358 ret = gst_element_send_event(gst_bin_get_by_name(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), "video_source"), gst_event_new_eos());
1362 if (info->b_commiting) {
1363 _mmstreamrec_dbg_err("now on commiting previous file!!(command : %d)", command);
1364 return MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING;
1366 _mmstreamrec_dbg_log("_MM_STREAMRECORDER_CMD_COMMIT : start");
1367 info->b_commiting = TRUE;
1370 for (count = 0; count <= hstreamrecorder->ini.retrial_count; count++) {
1371 if (sc->audio_enable == FALSE) {
1372 /* check only video frame */
1373 if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame) {
1375 } else if (count == hstreamrecorder->ini.retrial_count) {
1376 _mmstreamrec_dbg_err("Commit fail, frame count is %" G_GUINT64_FORMAT "", info->video_frame_count);
1377 info->b_commiting = FALSE;
1378 return MM_ERROR_STREAMRECORDER_INVALID_CONDITION;
1380 _mmstreamrec_dbg_warn("Waiting for enough video frame, retrial [%d], frame %" G_GUINT64_FORMAT "", count, info->video_frame_count);
1383 usleep(hstreamrecorder->ini.video_frame_wait_time);
1385 /* check both of video and audio frame */
1386 if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame && info_audio->audio_frame_count) {
1388 } else if (count == hstreamrecorder->ini.retrial_count) {
1389 _mmstreamrec_dbg_err("Commit fail, VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]", info->video_frame_count, info_audio->audio_frame_count);
1391 info->b_commiting = FALSE;
1392 return MM_ERROR_STREAMRECORDER_INVALID_CONDITION;
1394 _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);
1397 usleep(hstreamrecorder->ini.video_frame_wait_time);
1401 if (sc->error_occurs) {
1402 GstPad *video = NULL;
1403 GstPad *audio = NULL;
1405 _mmstreamrec_dbg_err("Committing Error case");
1407 video = gst_element_get_static_pad(sc->element[_MMSTREAMRECORDER_VIDEOSINK_SINK].gst, "sink");
1408 ret = gst_pad_send_event(video, gst_event_new_eos());
1409 _mmstreamrec_dbg_err("Sending EOS video sink : %d", ret);
1410 gst_object_unref(video);
1412 video = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "src");
1413 gst_pad_push_event(video, gst_event_new_flush_start());
1414 gst_pad_push_event(video, gst_event_new_flush_stop(TRUE));
1415 ret = gst_pad_push_event(video, gst_event_new_eos());
1416 _mmstreamrec_dbg_err("Sending EOS video encoder src pad : %d", ret);
1417 gst_object_unref(video);
1419 if (sc->audio_enable == TRUE) {
1420 audio = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "src");
1421 gst_pad_push_event(audio, gst_event_new_flush_start());
1422 gst_pad_push_event(audio, gst_event_new_flush_stop(TRUE));
1423 ret = gst_element_send_event(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, gst_event_new_eos());
1424 _mmstreamrec_dbg_err("Sending EOS audio encoder src pad : %d", ret);
1425 gst_object_unref(audio);
1428 if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst != NULL) {
1429 ret = gst_element_send_event(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, gst_event_new_eos());
1430 _mmstreamrec_dbg_warn("send eos to appsrc result : %d", ret);
1433 if (sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst != NULL) {
1434 pad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, "src");
1435 ret = gst_element_send_event(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, gst_event_new_eos());
1436 gst_object_unref(pad);
1439 _mmstreamrec_dbg_warn("send eos to audiosrc result : %d", ret);
1444 _mmstreamrec_dbg_log("Start to wait EOS");
1445 ret = _mmstreamrecorder_get_eos_message(handle);
1446 if (ret != MM_ERROR_NONE) {
1447 info->b_commiting = FALSE;
1448 goto _ERR_STREAMRECORDER_VIDEO_COMMAND;
1453 ret = MM_ERROR_STREAMRECORDER_INVALID_ARGUMENT;
1456 return MM_ERROR_NONE;
1458 _ERR_STREAMRECORDER_VIDEO_COMMAND:
1459 if (ret != MM_ERROR_NONE)
1460 _mmstreamrec_dbg_err("Current Videosrc status");
1465 int _mmstreamrecorder_video_handle_eos(MMHandleType handle)
1467 int ret = MM_ERROR_NONE;
1469 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1470 _MMStreamRecorderSubContext *sc = NULL;
1471 _MMStreamRecorderVideoInfo *info = NULL;
1472 _MMStreamRecorderAudioInfo *info_audio = NULL;
1473 _MMStreamRecorderFileInfo *finfo = NULL;
1474 _MMStreamRecorderMsgItem msg;
1475 MMStreamRecordingReport *report = NULL;
1477 mmf_return_val_if_fail(hstreamrecorder, FALSE);
1479 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1480 mmf_return_val_if_fail(sc, FALSE);
1481 mmf_return_val_if_fail(sc->info_video, FALSE);
1482 if (sc->audio_enable == TRUE)
1483 mmf_return_val_if_fail(sc->info_audio, FALSE);
1485 mmf_return_val_if_fail(sc->info_file, FALSE);
1487 info = sc->info_video;
1488 if (sc->audio_enable == TRUE)
1489 info_audio = sc->info_audio;
1491 finfo = sc->info_file;
1493 _mmstreamrec_dbg_err("");
1495 /* remove blocking part */
1496 MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
1498 ret = _mmstreamrecorder_destroy_recorder_pipeline(handle);
1499 if (ret != MM_ERROR_NONE)
1500 _mmstreamrec_dbg_warn("_mmstreamrecorder_destroy_recorder_pipeline failed. error[%x]", ret);
1502 /* Send recording report to application */
1503 msg.id = MM_MESSAGE_STREAMRECORDER_VIDEO_CAPTURED;
1504 report = (MMStreamRecordingReport *) g_malloc(sizeof(MMStreamRecordingReport));
1506 _mmstreamrec_dbg_err("Recording report fail(%s). Out of memory.", finfo->filename);
1508 report->recording_filename = g_strdup(finfo->filename);
1509 msg.param.data = report;
1511 _mmstreamrecorder_send_message((MMHandleType) hstreamrecorder, &msg);
1515 sc->pipeline_time = 0;
1517 sc->isMaxsizePausing = FALSE; /*In async function, this variable should set in callback function. */
1518 sc->isMaxtimePausing = FALSE;
1519 sc->error_occurs = FALSE;
1521 info->video_frame_count = 0;
1523 info_audio->audio_frame_count = 0;
1526 g_free(finfo->filename);
1527 finfo->filename = NULL;
1528 info->b_commiting = FALSE;
1530 _mmstreamrec_dbg_err("_mmstreamrecorder_video_handle_eos : end");
1535 int _mmstreamrecorder_push_videostream_buffer(MMHandleType handle, unsigned long long timestamp, GstBuffer *buffer, int size)
1537 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1538 _MMStreamRecorderSubContext *sc = NULL;
1539 /* GstPad *srcpad = NULL; */
1540 GstCaps *srccaps = NULL;
1541 char *err_name = NULL;
1544 int video_width = 0;
1545 int video_height = 0;
1546 int ret = MM_ERROR_NONE;
1547 int video_source_format = 0;
1549 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1551 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1552 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1554 if (buffer == NULL || size == 0) {
1555 _mmstreamrec_dbg_err("video : Buffer is %p , size %d, time stamp is %lld", buffer, size, timestamp);
1556 return MM_ERROR_STREAMRECORDER_RESOURCE_CREATION;
1559 _mmstreamrec_dbg_log("video : Buffer is %p , size %d, time stamp is %lld", buffer, size, timestamp);
1561 /* check element availability */
1562 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);
1564 if (ret != MM_ERROR_NONE) {
1565 _mmstreamrec_dbg_err("Error in mm_streamrecorder_get_attributes (%s:%d)", err_name, ret);
1566 SAFE_FREE(err_name);
1570 if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst) {
1572 /*_mmstreamrec_dbg_log("Buffer Push start , time stamp %ld",timestamp);*/
1573 /* srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "src"); */
1574 /* srccaps = gst_pad_get_current_caps(srcpad); */
1575 srccaps = gst_set_videosrcpad_caps_sw(video_src, video_width, video_height, video_fps, 1);
1577 gst_app_src_set_caps((GstAppSrc *) sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, srccaps);
1578 gst_caps_unref(srccaps);
1582 /*_mmstreamrec_dbg_err("newbuf streamrecorder(%p) ",newbuf);*/
1583 ret = gst_app_src_push_buffer((GstAppSrc *) sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, buffer);
1586 _mmstreamrec_dbg_err("video gst_app_src_push_buffer %d", ret);
1587 ret = MM_ERROR_STREAMRECORDER_VIDEOBUFFER_PUSH;
1590 /* g_signal_emit_by_name(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "push-buffer", newbuf, &ret); */
1596 int _mmstreamrecorder_push_audiostream_buffer(MMHandleType handle, unsigned long long timestamp, GstBuffer *buffer, int size)
1598 mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle);
1599 _MMStreamRecorderSubContext *sc = NULL;
1600 _MMStreamRecorderAudioInfo *info = NULL;
1601 GstFlowReturn err = GST_FLOW_OK;
1602 GstPad *srcpad = NULL;
1603 GstCaps *srccaps = NULL;
1608 mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1610 sc = MMF_STREAMRECORDER_SUBCONTEXT(handle);
1611 mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1613 info = (_MMStreamRecorderAudioInfo *) sc->info_audio;
1614 mmf_return_val_if_fail(info, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED);
1616 rate = info->iSamplingRate;
1617 depth = info->audio_encode_depth;
1618 channel = info->iChannels;
1620 /*_mmstreamrec_dbg_log("Audio Buffer Push start , time stamp %ld",timestamp); */
1622 if (sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst) {
1624 srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, "src");
1625 /* TODO : CHANNEL , WIDTH, DATATYPE */
1626 srccaps = gst_pad_get_current_caps(srcpad);
1627 srccaps = gst_set_audiosrcpad_caps(rate, channel, depth, 16, 1);
1628 gst_base_src_set_caps(GST_BASE_SRC(srcpad), srccaps);
1630 err = gst_app_src_push_buffer((GstAppSrc *) sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, buffer);
1633 _mmstreamrec_dbg_err("Audio gst_app_src_push_buffer %d", err);
1634 return MM_ERROR_STREAMRECORDER_AUDIOBUFFER_PUSH;
1638 return MM_ERROR_NONE;