From 4b03527ed8f401eb5e7c1734178a00261a430832 Mon Sep 17 00:00:00 2001 From: Hyunsoo Park Date: Mon, 25 Nov 2019 16:03:36 +0900 Subject: [PATCH] Merge branch 'tizen' into tizen_5.5 It is merge of patch 'Adds changes for mode of stream recoder'. 'https://review.tizen.org/gerrit/#/c/platform/core/multimedia/libmm-streamrecorder/+/218536/' Change-Id: Iee498d750b0bf1c56a7117aa08656a7a2395afb4 Signed-off-by: Hyunsoo Park --- packaging/libmm-streamrecorder.spec | 2 +- src/include/mm_streamrecorder.h | 16 +- src/include/mm_streamrecorder_gstcommon.h | 3 +- src/include/mm_streamrecorder_ini.h | 4 + src/include/mm_streamrecorder_internal.h | 28 +- src/include/mm_streamrecorder_recorder.h | 4 +- src/mm_streamrecorder.c | 4 +- src/mm_streamrecorder_attribute.c | 2 +- src/mm_streamrecorder_gstcommon.c | 38 ++- src/mm_streamrecorder_ini.c | 6 + src/mm_streamrecorder_internal.c | 6 +- src/mm_streamrecorder_recorder.c | 497 +++++++++++++++++++++--------- 12 files changed, 437 insertions(+), 173 deletions(-) diff --git a/packaging/libmm-streamrecorder.spec b/packaging/libmm-streamrecorder.spec index 49a0505..f2be44c 100644 --- a/packaging/libmm-streamrecorder.spec +++ b/packaging/libmm-streamrecorder.spec @@ -1,6 +1,6 @@ Name: libmm-streamrecorder Summary: Media Stream Recorder library -Version: 0.0.26 +Version: 0.0.27 Release: 0 Group: Multimedia/Other License: Apache-2.0 diff --git a/src/include/mm_streamrecorder.h b/src/include/mm_streamrecorder.h index b32ba7d..6043828 100644 --- a/src/include/mm_streamrecorder.h +++ b/src/include/mm_streamrecorder.h @@ -130,13 +130,13 @@ typedef enum { */ typedef enum { - MM_STREAMRECORDER_MODE_MEDIABUFFER = 0, /**< Recording with mediabuffer */ - MM_STREAMRECORDER_MODE_SCREENRECORD, /**< Recording with screenrecord */ + MM_STREAMRECORDER_MODE_STREAM_BUFFER = 0, /**< Recording with mediabuffer */ + MM_STREAMRECORDER_MODE_DEVICE_LOOPBACK /**< Recording with device's own screen(display) and audio */ } MMStreamRecorderModeType; typedef enum { MM_STREAMRECORDER_VIDEO_TYPE_TBM_BO, /**< TBM BO type */ - MM_STREAMRECORDER_VIDEO_TYPE_NORMAL_BUFFER, /**< Normal Raw data buffer */ + MM_STREAMRECORDER_VIDEO_TYPE_NORMAL_BUFFER /**< Normal Raw data buffer */ } MMStreamRecorderVideoBufType; typedef enum { @@ -144,9 +144,7 @@ typedef enum { MM_STREAMRECORDER_INPUT_FORMAT_NV12, /**< NV12 pixel format */ MM_STREAMRECORDER_INPUT_FORMAT_NV21, /**< NV21 pixel format */ MM_STREAMRECORDER_INPUT_FORMAT_I420, /**< I420 pixel format */ - MM_STREAMRECORDER_INPUT_FORMAT_UYVY, /**< UYVY pixel format */ - MM_STREAMRECORDER_INPUT_FORMAT_YUYV, /**< YUYV pixel format */ - MM_STREAMRECORDER_INPUT_FORMAT_BGRA8888, /**< BGRA8888 pixel format */ + MM_STREAMRECORDER_INPUT_FORMAT_BGRA, /**< BGRA pixel format */ MM_STREAMRECORDER_INPUT_FORMAT_NUM /**< Number of the pixel format */ } MMStreamRecorderVideoSourceFormat; @@ -176,7 +174,7 @@ typedef enum { * An enumeration for attribute validation type. */ typedef enum { - MM_STR_REC_ATTRS_VALID_TYPE_INVALID = -1, /**< Invalid validation type */ + MM_STR_REC_ATTRS_VALID_TYPE_INVALID = -1, /**< Invalid validation type */ MM_STR_REC_ATTRS_VALID_TYPE_NONE, /**< Do not check validity */ MM_STR_REC_ATTRS_VALID_TYPE_INT_ARRAY, /**< validity checking type of integer array */ MM_STR_REC_ATTRS_VALID_TYPE_INT_RANGE, /**< validity checking type of integer range */ @@ -443,9 +441,9 @@ int mm_streamrecorder_commit(MMHandleType streamrecorder); int mm_streamrecorder_cancel(MMHandleType streamrecorder); -int mm_streamrecorder_push_video_packet(MMHandleType streamrecorder, media_packet_h packet, unsigned long timestamp, void *buffer); +int mm_streamrecorder_push_video_packet(MMHandleType streamrecorder, media_packet_h packet, unsigned long long timestamp, void *buffer); -int mm_streamrecorder_push_stream_buffer(MMHandleType streamrecorder, MMStreamRecorderStreamType streamtype, unsigned long timestamp, void *buffer, int size); +int mm_streamrecorder_push_stream_buffer(MMHandleType streamrecorder, MMStreamRecorderStreamType streamtype, unsigned long long timestamp, void *buffer, int size); /** * mm_streamrecorder_commit:\n diff --git a/src/include/mm_streamrecorder_gstcommon.h b/src/include/mm_streamrecorder_gstcommon.h index 4da1a79..1689f66 100644 --- a/src/include/mm_streamrecorder_gstcommon.h +++ b/src/include/mm_streamrecorder_gstcommon.h @@ -246,7 +246,8 @@ gboolean _mmstreamrecorder_link_elements(GList *element_list); * */ int _mmstreamrecorder_gst_set_state(MMHandleType handle, GstElement *pipeline, GstState target_state); -GstCaps *gst_set_videosrcpad_caps(gint srcfmt, gint width, gint height, gint rate, gint scale); +GstCaps *gst_set_videosrcpad_caps_sw(gint srcfmt, gint width, gint height, gint rate, gint scale); +GstCaps *gst_set_videosrcpad_caps_hw(gchar* srcfmt, gint width, gint height, gint rate, gint scale); GstCaps *gst_set_audiosrcpad_caps(gint samplerate, gint channel, gint depth, gint width, gint datatype); #ifdef __cplusplus diff --git a/src/include/mm_streamrecorder_ini.h b/src/include/mm_streamrecorder_ini.h index e9b39f5..74df497 100644 --- a/src/include/mm_streamrecorder_ini.h +++ b/src/include/mm_streamrecorder_ini.h @@ -53,6 +53,8 @@ typedef struct __mm_streamrecorder_ini { guint convert_output_buffer_num; guint reset_pause_time; guint screen_record; + gboolean hw_encoder_supported; + gchar video_codec_element_hw[STREAMRECORDER_INI_MAX_STRLEN]; /*encodebin */ guint encsink_bin_profile; @@ -98,6 +100,8 @@ typedef struct __mm_streamrecorder_ini { #define DEFAULT_CONVERT_OUTPUT_BUFFER_NUM 6 #define DEFAULT_RESET_PAUSE_TIME 0 #define DEFAULT_SCREEN_RECORD 1 +#define DEFAULT_HW_ENCODER_SUPPORTED 0 +#define DEFAULT_VIDEO_CODEC_ELEMENT_HW "" /*encodebin*/ #define DEFAULT_ENCSINK_BIN_PROFILE 0 diff --git a/src/include/mm_streamrecorder_internal.h b/src/include/mm_streamrecorder_internal.h index 5bd3d2c..c529dfb 100644 --- a/src/include/mm_streamrecorder_internal.h +++ b/src/include/mm_streamrecorder_internal.h @@ -136,6 +136,9 @@ typedef enum { _MMSTREAMRECORDER_AUDIOSRC_BIN, _MMSTREAMRECORDER_AUDIOSRC_SRC, /* appsrc */ _MMSTREAMRECORDER_AUDIOSRC_FILT, + _MMSTREAMRECORDER_AUDIOSRC_CONV, + _MMSTREAMRECORDER_AUDIOSRC_ENC, + _MMSTREAMRECORDER_AUDIOSRC_QUE, /* Pipeline element of Encodebin */ _MMSTREAMRECORDER_ENCSINK_BIN, @@ -163,6 +166,27 @@ typedef enum { _MMSTREAMRECORDER_ENCODE_PIPELINE_ELEMENT_NUM, } _MMSTREAMRECORDER_ENCODE_PIPELINE_ELELMENT; +typedef enum { + /* Pipeline element of Audio input */ + _MMSTREAMRECORDER_AUDIO_SRC = 0x01, + _MMSTREAMRECORDER_AUDIO_CONV, + _MMSTREAMRECORDER_AUDIO_ENC, + _MMSTREAMRECORDER_AUDIO_QUE, + + /* Pipeline element of Video input */ + _MMSTREAMRECORDER_VIDEO_SRC, + _MMSTREAMRECORDER_VIDEO_CAPS, + _MMSTREAMRECORDER_VIDEO_CONV, + _MMSTREAMRECORDER_VIDEO_ENC, + _MMSTREAMRECORDER_VIDEO_QUE, + + /* Pipeline element of Common */ + _MMSTREAMRECORDER_MUX, + _MMSTREAMRECORDER_SINK, + + _MMSTREAMRECORDER_ELELMENT_NUM, +} _MMSTREAMRECORDER_ELELMENT; + /** * Command type for streamrecorder. */ @@ -359,9 +383,9 @@ int _mmstreamrecorder_unrealize(MMHandleType hstreamrecorder); */ int _mmstreamrecorder_record(MMHandleType hstreamrecorder); -int _mmstreamrecorder_push_video_packet(MMHandleType handle, media_packet_h packet, unsigned long timestamp, void *buffer); +int _mmstreamrecorder_push_video_packet(MMHandleType handle, media_packet_h packet, unsigned long long timestamp, void *buffer); -int _mmstreamrecorder_push_stream_buffer(MMHandleType handle, MMStreamRecorderStreamType streamtype, unsigned long timestamp, void *buffer, int size); +int _mmstreamrecorder_push_stream_buffer(MMHandleType handle, MMStreamRecorderStreamType streamtype, unsigned long long timestamp, void *buffer, int size); /** * This function is to pause video and audio recording diff --git a/src/include/mm_streamrecorder_recorder.h b/src/include/mm_streamrecorder_recorder.h index 8b8c4ce..edd4773 100644 --- a/src/include/mm_streamrecorder_recorder.h +++ b/src/include/mm_streamrecorder_recorder.h @@ -140,8 +140,8 @@ int _mmstreamrecorder_destroy_recorder_pipeline(MMHandleType handle); // COMMAND int _mmstreamrecorder_video_command(MMHandleType handle, int command); -int _mmstreamrecorder_push_videostream_buffer(MMHandleType handle, unsigned long timestamp, GstBuffer *buffer, int size); -int _mmstreamrecorder_push_audiostream_buffer(MMHandleType handle, unsigned long timestamp, GstBuffer *buffer, int size); +int _mmstreamrecorder_push_videostream_buffer(MMHandleType handle, unsigned long long timestamp, GstBuffer *buffer, int size); +int _mmstreamrecorder_push_audiostream_buffer(MMHandleType handle, unsigned long long timestamp, GstBuffer *buffer, int size); #ifdef __cplusplus } diff --git a/src/mm_streamrecorder.c b/src/mm_streamrecorder.c index b4c639b..1002c12 100644 --- a/src/mm_streamrecorder.c +++ b/src/mm_streamrecorder.c @@ -145,7 +145,7 @@ int mm_streamrecorder_record(MMHandleType streamrecorder) return error; } -int mm_streamrecorder_push_stream_buffer(MMHandleType streamrecorder, MMStreamRecorderStreamType streamtype, unsigned long timestamp, void *buffer, int size) +int mm_streamrecorder_push_stream_buffer(MMHandleType streamrecorder, MMStreamRecorderStreamType streamtype, unsigned long long timestamp, void *buffer, int size) { int error = MM_ERROR_NONE; @@ -160,7 +160,7 @@ int mm_streamrecorder_push_stream_buffer(MMHandleType streamrecorder, MMStreamRe return error; } -int mm_streamrecorder_push_video_packet(MMHandleType streamrecorder, media_packet_h packet, unsigned long timestamp, void *buffer) +int mm_streamrecorder_push_video_packet(MMHandleType streamrecorder, media_packet_h packet, unsigned long long timestamp, void *buffer) { int error = MM_ERROR_NONE; diff --git a/src/mm_streamrecorder_attribute.c b/src/mm_streamrecorder_attribute.c index 02e45b0..4555485 100644 --- a/src/mm_streamrecorder_attribute.c +++ b/src/mm_streamrecorder_attribute.c @@ -237,7 +237,7 @@ mm_streamrecorder_attr_construct_info stream_attrs_const_info[] = { (char *)"recorder-mode", MM_ATTRS_TYPE_INT, MM_ATTRS_FLAG_RW, - {(void *)MM_STREAMRECORDER_MODE_MEDIABUFFER}, + {(void *)MM_STREAMRECORDER_MODE_STREAM_BUFFER}, MM_ATTRS_VALID_TYPE_NONE, {0}, {_MMSTREAMRECORDER_MAX_INT}, diff --git a/src/mm_streamrecorder_gstcommon.c b/src/mm_streamrecorder_gstcommon.c index 1a437fa..64d4d5e 100644 --- a/src/mm_streamrecorder_gstcommon.c +++ b/src/mm_streamrecorder_gstcommon.c @@ -323,22 +323,28 @@ int _mmstreamrecorder_gst_set_state(MMHandleType handle, GstElement *pipeline, G return MM_ERROR_STREAMRECORDER_RESPONSE_TIMEOUT; } -GstCaps *gst_set_videosrcpad_caps(gint srcfmt, gint width, gint height, gint rate, gint scale) +GstCaps *gst_set_videosrcpad_caps_sw(gint srcfmt, gint width, gint height, gint rate, gint scale) { GstCaps *caps = NULL; - if (srcfmt == MM_STREAMRECORDER_INPUT_FORMAT_NV12) + switch (srcfmt) { + case MM_STREAMRECORDER_INPUT_FORMAT_NV12 : caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "NV12", "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, rate, scale, NULL); - else if (srcfmt == MM_STREAMRECORDER_INPUT_FORMAT_I420) + break; + case MM_STREAMRECORDER_INPUT_FORMAT_I420 : caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "I420", "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, rate, scale, NULL); - else - caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "BGRA8888", "bpp", G_TYPE_INT, 32, "depth", G_TYPE_INT, 24, "endianness", G_TYPE_INT, 4321, "red_mask", G_TYPE_INT, 65280, "green_mask", G_TYPE_INT, 16711680, "blue_mask", G_TYPE_INT, -16777216, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, rate, scale, NULL); + break; + case MM_STREAMRECORDER_INPUT_FORMAT_BGRA : + caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "BGRA", "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, rate, scale, NULL); + break; + default : + caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "BGRA", "bpp", G_TYPE_INT, 32, "depth", G_TYPE_INT, 24, "endianness", G_TYPE_INT, 4321, "red_mask", G_TYPE_INT, 65280, "green_mask", G_TYPE_INT, 16711680, "blue_mask", G_TYPE_INT, -16777216, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, rate, scale, NULL); + break; + } - if (!caps) { + if (!caps) _mmstreamrec_dbg_err("failed to alloc caps"); - return NULL; - } /* gchar *type = gst_caps_to_string(caps); */ @@ -349,6 +355,22 @@ GstCaps *gst_set_videosrcpad_caps(gint srcfmt, gint width, gint height, gint rat return caps; } +GstCaps *gst_set_videosrcpad_caps_hw(gchar* elem, gint width, gint height, gint rate, gint scale) +{ + + GstCaps *caps = NULL; + _mmstreamrec_dbg_err("Hardware Codec Element [%s]", elem); + + + if (!g_strcmp0(elem, "sprd")) + caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "SN12", "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, rate, scale, NULL); + + if (!caps) + _mmstreamrec_dbg_err("failed to alloc caps"); + + return caps; +} + GstCaps *gst_set_audiosrcpad_caps(gint samplerate, gint channel, gint depth, gint width, gint datatype) { diff --git a/src/mm_streamrecorder_ini.c b/src/mm_streamrecorder_ini.c index 787c0c3..9f6cce3 100644 --- a/src/mm_streamrecorder_ini.c +++ b/src/mm_streamrecorder_ini.c @@ -96,6 +96,8 @@ int _mm_streamrecorder_ini_load(mm_streamrecorder_ini_t *ini) ini->convert_output_buffer_num = iniparser_getint(dict, "general:convert output buffer num", DEFAULT_CONVERT_OUTPUT_BUFFER_NUM); ini->reset_pause_time = iniparser_getint(dict, "general:reset pause time", DEFAULT_RESET_PAUSE_TIME); ini->screen_record = iniparser_getint(dict, "general:screen record", DEFAULT_SCREEN_RECORD); + ini->hw_encoder_supported = iniparser_getboolean(dict, "general:hw encoder supported", DEFAULT_HW_ENCODER_SUPPORTED); + MM_STREAMRECORDER_INI_GET_STRING(dict, ini->video_codec_element_hw, (const char *)"general:video codec element hw", (char *)DEFAULT_VIDEO_SOURCE); /*encodebin */ ini->encsink_bin_profile = iniparser_getint(dict, "encodebin:encsink bin profile", DEFAULT_ENCSINK_BIN_PROFILE); @@ -140,6 +142,8 @@ int _mm_streamrecorder_ini_load(mm_streamrecorder_ini_t *ini) ini->convert_output_buffer_num = DEFAULT_CONVERT_OUTPUT_BUFFER_NUM; ini->reset_pause_time = DEFAULT_RESET_PAUSE_TIME; ini->screen_record = DEFAULT_SCREEN_RECORD; + ini->hw_encoder_supported = DEFAULT_HW_ENCODER_SUPPORTED; + strncpy(ini->video_codec_element_hw, DEFAULT_VIDEO_CODEC_ELEMENT_HW, STREAMRECORDER_INI_MAX_STRLEN - 1); /*encodebin */ ini->encsink_bin_profile = DEFAULT_ENCSINK_BIN_PROFILE; @@ -190,6 +194,8 @@ int _mm_streamrecorder_ini_load(mm_streamrecorder_ini_t *ini) _mmstreamrec_dbg_log("convert_output_buffer_num : %d", ini->convert_output_buffer_num); _mmstreamrec_dbg_log("reset_pause_time : %d", ini->reset_pause_time); _mmstreamrec_dbg_log("screen_record : %d", ini->screen_record); + _mmstreamrec_dbg_log("hw_encoder_supported : %d", ini->hw_encoder_supported); + _mmstreamrec_dbg_log("video_codec_element_hw : %s", ini->video_codec_element_hw); /*encodebin */ _mmstreamrec_dbg_log("encode bin profile : %d", ini->encsink_bin_profile); diff --git a/src/mm_streamrecorder_internal.c b/src/mm_streamrecorder_internal.c index 1846328..b446eed 100644 --- a/src/mm_streamrecorder_internal.c +++ b/src/mm_streamrecorder_internal.c @@ -389,7 +389,7 @@ int _mmstreamrecorder_record(MMHandleType handle) return ret; } -int _mmstreamrecorder_push_video_packet(MMHandleType handle, media_packet_h media_packet, unsigned long timestamp, void *buffer) +int _mmstreamrecorder_push_video_packet(MMHandleType handle, media_packet_h media_packet, unsigned long long timestamp, void *buffer) { int ret = MM_ERROR_NONE; unsigned int ind = 0; @@ -458,7 +458,7 @@ int _mmstreamrecorder_push_video_packet(MMHandleType handle, media_packet_h medi return ret; } -int _mmstreamrecorder_push_stream_buffer(MMHandleType handle, MMStreamRecorderStreamType streamtype, unsigned long timestamp, void *buffer, int size) +int _mmstreamrecorder_push_stream_buffer(MMHandleType handle, MMStreamRecorderStreamType streamtype, unsigned long long timestamp, void *buffer, int size) { int ret = MM_ERROR_NONE; @@ -506,7 +506,7 @@ int _mmstreamrecorder_push_stream_buffer(MMHandleType handle, MMStreamRecorderSt gst_buffer_append_memory(stream_buffer->buffer, gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, video_buf, sizeof(MMVideoBuffer), 0, sizeof(MMVideoBuffer), stream_buffer, _mmstreamrecorder_buffer_destroy)); } else { - gst_buffer_append_memory(stream_buffer->buffer, gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, + gst_buffer_append_memory(stream_buffer->buffer, gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, buffer, size, 0, size, stream_buffer, _mmstreamrecorder_buffer_destroy)); } ret = _mmstreamrecorder_push_videostream_buffer(handle, timestamp, stream_buffer->buffer, size); diff --git a/src/mm_streamrecorder_recorder.c b/src/mm_streamrecorder_recorder.c index d9eaeb0..eb72cdb 100644 --- a/src/mm_streamrecorder_recorder.c +++ b/src/mm_streamrecorder_recorder.c @@ -158,15 +158,23 @@ int _mmstreamrecorder_create_recorder_pipeline(MMHandleType handle) { int i = 0; int err = MM_ERROR_NONE; - int audio_enable = FALSE; + int rec_mode = 0; + int width = 0; + int height = 0; + int video_src_format = 0; + int frame_rate = 0; + int filename_size = 0; + gboolean audio_enable = FALSE; GstBus *bus = NULL; GstPad *srcpad = NULL; GstPad *sinkpad = NULL; - + GstCaps *caps = NULL; + GList *element_list = NULL; + GstStructure* pulse_property = NULL; unsigned int video_codec = MM_VIDEO_CODEC_INVALID; unsigned int file_format = MM_FILE_FORMAT_INVALID; char *err_name = NULL; - + char *filename = NULL; mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle); _MMStreamRecorderSubContext *sc = NULL; @@ -177,96 +185,278 @@ int _mmstreamrecorder_create_recorder_pipeline(MMHandleType handle) _mmstreamrec_dbg_warn("start"); - err = mm_streamrecorder_get_attributes(handle, &err_name, MMSTR_VIDEO_ENCODER, &video_codec, MMSTR_FILE_FORMAT, &file_format, NULL); + err = mm_streamrecorder_get_attributes(handle, &err_name, MMSTR_VIDEO_ENCODER, &video_codec, MMSTR_FILE_FORMAT, &file_format, MMSTR_RECORDER_MODE, &rec_mode, NULL); if (err != MM_ERROR_NONE) { _mmstreamrec_dbg_warn("Get attrs fail. (%s:%x)", err_name, err); SAFE_FREE(err_name); return err; } - err = _mmstreamrecorder_check_videocodec_fileformat_compatibility(video_codec, file_format); - if (err != MM_ERROR_NONE) - return err; + if (rec_mode == MM_STREAMRECORDER_MODE_STREAM_BUFFER) { + _mmstreamrec_dbg_log("Recording Mode [%d]", MM_STREAMRECORDER_MODE_STREAM_BUFFER); + err = _mmstreamrecorder_check_videocodec_fileformat_compatibility(video_codec, file_format); + if (err != MM_ERROR_NONE) + return err; - /* Main pipeline */ - _MMSTREAMRECORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCODE_MAIN_PIPE, "recorder_pipeline", err); + /* Main pipeline */ + _MMSTREAMRECORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCODE_MAIN_PIPE, "recorder_pipeline", err); - /* get audio disable */ - mm_streamrecorder_get_attributes(handle, NULL, MMSTR_AUDIO_ENABLE, &audio_enable, NULL); - sc->audio_enable = audio_enable; + /* get audio disable */ + mm_streamrecorder_get_attributes(handle, NULL, MMSTR_AUDIO_ENABLE, &audio_enable, NULL); + sc->audio_enable = audio_enable; - _mmstreamrec_dbg_log("AUDIO DISABLE : %d", sc->audio_enable); + _mmstreamrec_dbg_log("AUDIO DISABLE : %d", sc->audio_enable); - if (sc->audio_enable == TRUE) { - /* create audiosrc bin */ - err = _mmstreamrecorder_create_audiosrc_bin((MMHandleType) hstreamrecorder); + if (sc->audio_enable == TRUE) { + /* create audiosrc bin */ + err = _mmstreamrecorder_create_audiosrc_bin((MMHandleType) hstreamrecorder); + if (err != MM_ERROR_NONE) + return err; + } + + err = _mmstreamrecorder_create_encodesink_bin((MMHandleType) hstreamrecorder, MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO); if (err != MM_ERROR_NONE) return err; - } - - err = _mmstreamrecorder_create_encodesink_bin((MMHandleType) hstreamrecorder, MM_STREAMRECORDER_ENCBIN_PROFILE_VIDEO); - if (err != MM_ERROR_NONE) - return err; - - if (sc->audio_enable == TRUE) - gst_bin_add(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst); - /* add element and encodesink bin to encode main pipeline */ - 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); + if (sc->audio_enable == TRUE) + gst_bin_add(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst); - /* Link each element : appsrc - capsfilter - encodesink bin */ - srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "src"); - sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, "sink"); - _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error); + /* add element and encodesink bin to encode main pipeline */ + 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); - srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, "src"); - sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, "video_sink0"); - _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error); + /* Link each element : appsrc - capsfilter - encodesink bin */ + srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "src"); + sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, "sink"); + _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error); - if (sc->audio_enable == TRUE) { - srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, "src"); - sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, "audio_sink0"); + srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, "src"); + sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, "video_sink0"); _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error); - } - if (sc->audio_enable == TRUE) { - sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "sink"); - MMSTREAMRECORDER_ADD_BUFFER_PROBE(sinkpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_audioque_dataprobe, hstreamrecorder); - gst_object_unref(sinkpad); - sinkpad = NULL; + if (sc->audio_enable == TRUE) { + srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_BIN].gst, "src"); + sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_BIN].gst, "audio_sink0"); + _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error); + } - if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC_QUE].gst) { - srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC_QUE].gst, "src"); + if (sc->audio_enable == TRUE) { + sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "sink"); + MMSTREAMRECORDER_ADD_BUFFER_PROBE(sinkpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_audioque_dataprobe, hstreamrecorder); + gst_object_unref(sinkpad); + sinkpad = NULL; + + if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC_QUE].gst) { + srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC_QUE].gst, "src"); + MMSTREAMRECORDER_ADD_EVENT_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_eventprobe_monitor, hstreamrecorder); + gst_object_unref(srcpad); + srcpad = NULL; + } + } + + if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC_QUE].gst) { + srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC_QUE].gst, "src"); MMSTREAMRECORDER_ADD_EVENT_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_eventprobe_monitor, hstreamrecorder); gst_object_unref(srcpad); srcpad = NULL; } - } - if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC_QUE].gst) { - srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC_QUE].gst, "src"); - MMSTREAMRECORDER_ADD_EVENT_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_eventprobe_monitor, hstreamrecorder); + if (sc->audio_enable == FALSE) { + sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "sink"); + MMSTREAMRECORDER_ADD_BUFFER_PROBE(sinkpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_video_dataprobe_audio_disable, hstreamrecorder); + gst_object_unref(sinkpad); + sinkpad = NULL; + } + + srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "src"); + MMSTREAMRECORDER_ADD_BUFFER_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_video_dataprobe_record, hstreamrecorder); gst_object_unref(srcpad); srcpad = NULL; - } - if (sc->audio_enable == FALSE) { - sinkpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "sink"); - MMSTREAMRECORDER_ADD_BUFFER_PROBE(sinkpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_video_dataprobe_audio_disable, hstreamrecorder); - gst_object_unref(sinkpad); - sinkpad = NULL; - } + if (sc->audio_enable == TRUE) { + srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "src"); + MMSTREAMRECORDER_ADD_BUFFER_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_audio_dataprobe_check, hstreamrecorder); + gst_object_unref(srcpad); + srcpad = NULL; + } + } else if (rec_mode == MM_STREAMRECORDER_MODE_DEVICE_LOOPBACK) { + _mmstreamrec_dbg_log("Recording Mode [%d]", MM_STREAMRECORDER_MODE_DEVICE_LOOPBACK); + 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); + _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); - srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "src"); - MMSTREAMRECORDER_ADD_BUFFER_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_video_dataprobe_record, hstreamrecorder); - gst_object_unref(srcpad); - srcpad = NULL; + _MMSTREAMRECORDER_PIPELINE_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCODE_MAIN_PIPE, "recorder_pipeline", err); - if (sc->audio_enable == TRUE) { - srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "src"); - MMSTREAMRECORDER_ADD_BUFFER_PROBE(srcpad, _MMSTREAMRECORDER_HANDLER_VIDEOREC, __mmstreamrecorder_audio_dataprobe_check, hstreamrecorder); - gst_object_unref(srcpad); - srcpad = NULL; + if (!hstreamrecorder->ini.hw_encoder_supported) { + _mmstreamrec_dbg_log("Screen is recorded with SW encoder."); + if (audio_enable) { + _mmstreamrec_dbg_log("Audio is enabled!"); + + /* Audio pipeline */ + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_SRC, "pulsesrc", "audio_source", element_list, err); + + pulse_property = gst_structure_new_from_string("props,media.role=loopback-mirroring"); + MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst, "stream-properties", pulse_property); + MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst, "do-timestamp", true); + MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst, "provide-clock", false); + + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_CONV, "audioconvert", "audio_converter", element_list, err); + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_ENC, "avenc_aac", "audio_encoder", element_list, err); + MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_ENC].gst, "compliance", -2); + + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_QUE, "queue", "audio_queue", element_list, err); + + gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), + sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst, + sc->encode_element[_MMSTREAMRECORDER_AUDIO_CONV].gst, + sc->encode_element[_MMSTREAMRECORDER_AUDIO_ENC].gst, + sc->encode_element[_MMSTREAMRECORDER_AUDIO_QUE].gst, NULL); + } + + /* Video pipeline */ + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_SRC, "waylandsrc", "video_source", element_list, err); + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_CAPS, "capsfilter", "video_capsfilter", element_list, err); + + caps = gst_set_videosrcpad_caps_sw(MM_STREAMRECORDER_INPUT_FORMAT_BGRA, width, height, frame_rate, 1); + MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_VIDEO_CAPS].gst, "caps", caps); + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_CONV, "videoconvert", "video_conveter", element_list, err); + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_ENC, "avenc_mpeg4", "video_encoder", element_list, err); + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_QUE, "queue", "video_queue", element_list, err); + + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_MUX, "avmux_mp4", "av_muxer", element_list, err); + + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_SINK, "filesink", "av_sink", element_list, err); + MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_SINK].gst, "location", filename); + + + gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), + sc->encode_element[_MMSTREAMRECORDER_VIDEO_SRC].gst, + sc->encode_element[_MMSTREAMRECORDER_VIDEO_CAPS].gst, + sc->encode_element[_MMSTREAMRECORDER_VIDEO_CONV].gst, + sc->encode_element[_MMSTREAMRECORDER_VIDEO_ENC].gst, + sc->encode_element[_MMSTREAMRECORDER_VIDEO_QUE].gst, NULL); + + gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), + sc->encode_element[_MMSTREAMRECORDER_MUX].gst, + sc->encode_element[_MMSTREAMRECORDER_SINK].gst, NULL); + if (audio_enable) { + if (!_MM_GST_ELEMENT_LINK_MANY(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_CONV].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_ENC].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_QUE].gst), NULL)) { + _mmstreamrec_dbg_log("AUDIO PIPELINE LINK MANY FAILED"); + } + + if (!_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_QUE].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_MUX].gst))) { + _mmstreamrec_dbg_log("LINK BETWEEN AUDIO QUE AND MUX FAILED"); + } + } + + if (!_MM_GST_ELEMENT_LINK_MANY(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_SRC].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_CAPS].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_CONV].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_ENC].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_QUE].gst), NULL)) { + _mmstreamrec_dbg_log("VIDEO PIPELINE LINK MANY FAILED"); + } + + if (!_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_QUE].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_MUX].gst))) { + _mmstreamrec_dbg_log("LINK BETWEEN VIDEO QUE AND MUX FAILED"); + } + + if (!_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_MUX].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_SINK].gst))) { + _mmstreamrec_dbg_log("LINK BETWEEN MUX AND SINK FAILED"); + } + } else { + _mmstreamrec_dbg_log("Screen is recorded with HW encoder."); + if (audio_enable) { + _mmstreamrec_dbg_log("Audio is enabled!"); + + /* Audio pipeline */ + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_SRC, "pulsesrc", "audio_source", element_list, err); + + pulse_property = gst_structure_new_from_string("props,media.role=loopback-mirroring"); + MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst, "stream-properties", pulse_property); + MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst, "do-timestamp", true); + MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst, "provide-clock", false); + + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_CONV, "audioconvert", "audio_converter", element_list, err); + + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_ENC, "avenc_aac", "audio_encoder", element_list, err); + MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_AUDIO_ENC].gst, "compliance", -2); + + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_AUDIO_QUE, "queue", "audio_queue", element_list, err); + + gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), + sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst, + sc->encode_element[_MMSTREAMRECORDER_AUDIO_CONV].gst, + sc->encode_element[_MMSTREAMRECORDER_AUDIO_ENC].gst, + sc->encode_element[_MMSTREAMRECORDER_AUDIO_QUE].gst, + sc->encode_element[_MMSTREAMRECORDER_VIDEO_SRC].gst, NULL); + } + /* Video pipeline */ + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_SRC, "waylandsrc", "video_source", element_list, err); + + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_CAPS, "capsfilter", "video_capsfilter", element_list, err); + + caps = gst_set_videosrcpad_caps_hw(hstreamrecorder->ini.video_codec_element_hw, width, height, frame_rate, 1); + MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_VIDEO_CAPS].gst, "caps", caps); + + if (!g_strcmp0(hstreamrecorder->ini.video_codec_element_hw, "sprd")){ + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_ENC, "sprdenc_h264", "video_encoder", element_list, err); + } else { + _mmstreamrec_dbg_warn("no matched hw codec element found."); + goto pipeline_creation_error; + } + + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_VIDEO_QUE, "queue", "video_queue", element_list, err); + + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_MUX, "avmux_mp4", "av_muxer", element_list, err); + + _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_SINK, "filesink", "av_sink", element_list, err); + MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_SINK].gst, "location", filename); + + gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), + sc->encode_element[_MMSTREAMRECORDER_VIDEO_SRC].gst, + sc->encode_element[_MMSTREAMRECORDER_VIDEO_CAPS].gst, + sc->encode_element[_MMSTREAMRECORDER_VIDEO_ENC].gst, + sc->encode_element[_MMSTREAMRECORDER_VIDEO_QUE].gst, NULL); + + gst_bin_add_many(GST_BIN(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst), + sc->encode_element[_MMSTREAMRECORDER_MUX].gst, + sc->encode_element[_MMSTREAMRECORDER_SINK].gst, NULL); + if (audio_enable) { + if (!_MM_GST_ELEMENT_LINK_MANY(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_SRC].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_CONV].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_ENC].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_QUE].gst), NULL)) { + _mmstreamrec_dbg_log("AUDIO PIPELINE LINK MANY FAILED"); + } + + if (!_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_AUDIO_QUE].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_MUX].gst))) { + _mmstreamrec_dbg_log("LINK BETWEEN AUDIO QUE AND MUX FAILED"); + } + } + + if (!_MM_GST_ELEMENT_LINK_MANY(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_SRC].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_CAPS].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_ENC].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_QUE].gst), NULL)) { + _mmstreamrec_dbg_log("VIDEO PIPELINE LINK MANY FAILED"); + } + + if (!_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_VIDEO_QUE].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_MUX].gst))) { + _mmstreamrec_dbg_log("LINK BETWEEN VIDEO QUE AND MUX FAILED"); + } + + if (!_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_MUX].gst), + GST_ELEMENT(sc->encode_element[_MMSTREAMRECORDER_SINK].gst))) { + _mmstreamrec_dbg_log("LINK BETWEEN MUX AND SINK FAILED"); + } + } } bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst)); @@ -276,7 +466,6 @@ int _mmstreamrecorder_create_recorder_pipeline(MMHandleType handle) gst_object_unref(bus); bus = NULL; - return MM_ERROR_NONE; pipeline_creation_error: @@ -434,14 +623,14 @@ int _mmstreamrecorder_create_encodesink_bin(MMHandleType handle, MMStreamRecorde _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SRC, hstreamrecorder->ini.name_of_encsink_src, "encodesink_src", element_list, err); _MMSTREAMRECORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMSTREAMRECORDER_ENCSINK_FILT, "capsfilter", "encodesink_filter", element_list, err); - caps = gst_set_videosrcpad_caps(video_src_format, video_width, video_height, video_fps, 1); + caps = gst_set_videosrcpad_caps_sw(video_src_format, video_width, video_height, video_fps, 1); MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "caps", caps); if (caps) { gst_caps_unref(caps); caps = NULL; } - caps = gst_set_videosrcpad_caps(video_src_format, video_width, video_height, video_fps, 1); + caps = gst_set_videosrcpad_caps_sw(video_src_format, video_width, video_height, video_fps, 1); MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_FILT].gst, "caps", caps); if (caps) { gst_caps_unref(caps); @@ -454,7 +643,7 @@ int _mmstreamrecorder_create_encodesink_bin(MMHandleType handle, MMStreamRecorde g_list_free(element_list); element_list = NULL; } - if (rec_mode == MM_STREAMRECORDER_MODE_MEDIABUFFER) { + if (rec_mode == MM_STREAMRECORDER_MODE_STREAM_BUFFER) { /* set appsrc as live source */ MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "is-live", hstreamrecorder->ini.encsink_src_islive); } @@ -480,7 +669,7 @@ int _mmstreamrecorder_create_encodesink_bin(MMHandleType handle, MMStreamRecorde /* TODO : check the last value ( set ) */ MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "profile", hstreamrecorder->ini.encsink_bin_profile); - if (rec_mode == MM_STREAMRECORDER_MODE_MEDIABUFFER) + if (rec_mode == MM_STREAMRECORDER_MODE_STREAM_BUFFER) MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", hstreamrecorder->ini.encsink_bin_auto_audio_convert); MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "auto-audio-resample", hstreamrecorder->ini.encsink_bin_auto_audio_resample); @@ -514,7 +703,7 @@ int _mmstreamrecorder_create_encodesink_bin(MMHandleType handle, MMStreamRecorde if (video_src_format == MM_STREAMRECORDER_INPUT_FORMAT_NV12) video_src_format = MM_STREAMRECORDER_INPUT_FORMAT_I420; - caps = gst_set_videosrcpad_caps(video_src_format, video_width, video_height, video_fps, 1); + caps = gst_set_videosrcpad_caps_sw(video_src_format, video_width, video_height, video_fps, 1); MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_ENCBIN].gst, "vcaps", caps); if (video_src_format != MM_STREAMRECORDER_INPUT_FORMAT_NV12) MMSTREAMRECORDER_G_OBJECT_SET(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VCONV].gst, "dst-buffer-num", hstreamrecorder->ini.convert_output_buffer_num); @@ -767,7 +956,7 @@ int _mmstreamrecorder_create_encodesink_bin(MMHandleType handle, MMStreamRecorde return MM_ERROR_NONE; - pipeline_creation_error: +pipeline_creation_error: _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_ENCBIN); _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_SRC); _MMSTREAMRECORDER_ELEMENT_REMOVE(sc->encode_element, _MMSTREAMRECORDER_ENCSINK_FILT); @@ -902,7 +1091,7 @@ int _mmstreamrecorder_create_audiosrc_bin(MMHandleType handle) } if (caps) { - if (rec_mode == MM_STREAMRECORDER_MODE_MEDIABUFFER) + if (rec_mode == MM_STREAMRECORDER_MODE_STREAM_BUFFER) MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "caps", caps); MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_FILT].gst), "caps", caps); @@ -919,7 +1108,7 @@ int _mmstreamrecorder_create_audiosrc_bin(MMHandleType handle) goto pipeline_creation_error; } - if (rec_mode == MM_STREAMRECORDER_MODE_SCREENRECORD) { + if (rec_mode == MM_STREAMRECORDER_MODE_DEVICE_LOOPBACK) { #if 1 /* mic mode */ MMSTREAMRECORDER_G_OBJECT_SET((sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst), "do-timestamp", TRUE); #else /* speaker mode with alsasrc */ @@ -1019,6 +1208,9 @@ int _mmstreamrecorder_video_command(MMHandleType handle, int command) GstElement *pipeline = NULL; GstPad *pad = NULL; guint count = 0; + gboolean audio_enable = FALSE; + int rec_mode = 0; + char *err_name = NULL; mmf_return_val_if_fail(hstreamrecorder, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED); @@ -1031,6 +1223,14 @@ int _mmstreamrecorder_video_command(MMHandleType handle, int command) mmf_return_val_if_fail(sc->info_file, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED); + ret = mm_streamrecorder_get_attributes(handle, &err_name, MMSTR_RECORDER_MODE, &rec_mode, MMSTR_AUDIO_ENABLE, &audio_enable, NULL); + + if (ret != MM_ERROR_NONE) { + _mmstreamrec_dbg_err("Get attrs fail. (%s:%x)", err_name, ret); + SAFE_FREE(err_name); + return ret; + } + info = sc->info_video; if (sc->audio_enable == TRUE) info_audio = sc->info_audio; @@ -1059,7 +1259,7 @@ int _mmstreamrecorder_video_command(MMHandleType handle, int command) sc->ferror_count = 0; sc->error_occurs = FALSE; sc->bget_eos = FALSE; - + ret = _mmstreamrecorder_gst_set_state(handle, sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PAUSED); ret = _mmstreamrecorder_gst_set_state(handle, sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PLAYING); if (ret != MM_ERROR_NONE) { /* Remove recorder pipeline and recording file which size maybe zero */ @@ -1150,88 +1350,96 @@ int _mmstreamrecorder_video_command(MMHandleType handle, int command) case _MM_STREAMRECORDER_CMD_COMMIT: /* video recording command */ { - - if (info->b_commiting) { - _mmstreamrec_dbg_err("now on commiting previous file!!(command : %d)", command); - return MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING; - } else { - _mmstreamrec_dbg_log("_MM_STREAMRECORDER_CMD_COMMIT : start"); - info->b_commiting = TRUE; - } - - for (count = 0; count <= hstreamrecorder->ini.retrial_count; count++) { - if (sc->audio_enable == FALSE) { - /* check only video frame */ - if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame) { - break; - } else if (count == hstreamrecorder->ini.retrial_count) { - _mmstreamrec_dbg_err("Commit fail, frame count is %" G_GUINT64_FORMAT "", info->video_frame_count); - info->b_commiting = FALSE; - return MM_ERROR_STREAMRECORDER_INVALID_CONDITION; - } else { - _mmstreamrec_dbg_warn("Waiting for enough video frame, retrial [%d], frame %" G_GUINT64_FORMAT "", count, info->video_frame_count); + if(rec_mode == MM_STREAMRECORDER_MODE_DEVICE_LOOPBACK) { + if (sc->encode_element[_MMSTREAMRECORDER_ENCODE_MAIN_PIPE].gst != NULL) {\ + if (audio_enable) { + 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()); } + 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()); + } + } else { - usleep(hstreamrecorder->ini.video_frame_wait_time); + if (info->b_commiting) { + _mmstreamrec_dbg_err("now on commiting previous file!!(command : %d)", command); + return MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING; } else { - /* check both of video and audio frame */ - if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame && info_audio->audio_frame_count) { - break; - } else if (count == hstreamrecorder->ini.retrial_count) { - _mmstreamrec_dbg_err("Commit fail, VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]", info->video_frame_count, info_audio->audio_frame_count); + _mmstreamrec_dbg_log("_MM_STREAMRECORDER_CMD_COMMIT : start"); + info->b_commiting = TRUE; + } - info->b_commiting = FALSE; - return MM_ERROR_STREAMRECORDER_INVALID_CONDITION; + for (count = 0; count <= hstreamrecorder->ini.retrial_count; count++) { + if (sc->audio_enable == FALSE) { + /* check only video frame */ + if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame) { + break; + } else if (count == hstreamrecorder->ini.retrial_count) { + _mmstreamrec_dbg_err("Commit fail, frame count is %" G_GUINT64_FORMAT "", info->video_frame_count); + info->b_commiting = FALSE; + return MM_ERROR_STREAMRECORDER_INVALID_CONDITION; + } else { + _mmstreamrec_dbg_warn("Waiting for enough video frame, retrial [%d], frame %" G_GUINT64_FORMAT "", count, info->video_frame_count); + } + + usleep(hstreamrecorder->ini.video_frame_wait_time); } else { - _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); + /* check both of video and audio frame */ + if (info->video_frame_count >= hstreamrecorder->ini.minimum_frame && info_audio->audio_frame_count) { + break; + } else if (count == hstreamrecorder->ini.retrial_count) { + _mmstreamrec_dbg_err("Commit fail, VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]", info->video_frame_count, info_audio->audio_frame_count); + + info->b_commiting = FALSE; + return MM_ERROR_STREAMRECORDER_INVALID_CONDITION; + } else { + _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); + } + + usleep(hstreamrecorder->ini.video_frame_wait_time); } - - usleep(hstreamrecorder->ini.video_frame_wait_time); } - } - if (sc->error_occurs) { - GstPad *video = NULL; - GstPad *audio = NULL; + if (sc->error_occurs) { + GstPad *video = NULL; + GstPad *audio = NULL; - _mmstreamrec_dbg_err("Committing Error case"); + _mmstreamrec_dbg_err("Committing Error case"); #if 0 - video = gst_element_get_static_pad(sc->element[_MMSTREAMRECORDER_VIDEOSINK_SINK].gst, "sink"); - ret = gst_pad_send_event(video, gst_event_new_eos()); - _mmstreamrec_dbg_err("Sending EOS video sink : %d", ret); - gst_object_unref(video); + video = gst_element_get_static_pad(sc->element[_MMSTREAMRECORDER_VIDEOSINK_SINK].gst, "sink"); + ret = gst_pad_send_event(video, gst_event_new_eos()); + _mmstreamrec_dbg_err("Sending EOS video sink : %d", ret); + gst_object_unref(video); #endif - video = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "src"); - gst_pad_push_event(video, gst_event_new_flush_start()); - gst_pad_push_event(video, gst_event_new_flush_stop(TRUE)); - ret = gst_pad_push_event(video, gst_event_new_eos()); - _mmstreamrec_dbg_err("Sending EOS video encoder src pad : %d", ret); - gst_object_unref(video); - - if (sc->audio_enable == TRUE) { - audio = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "src"); - gst_pad_push_event(audio, gst_event_new_flush_start()); - gst_pad_push_event(audio, gst_event_new_flush_stop(TRUE)); - ret = gst_element_send_event(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, gst_event_new_eos()); - _mmstreamrec_dbg_err("Sending EOS audio encoder src pad : %d", ret); - gst_object_unref(audio); - } - } else { - if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst != NULL) { + video = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_VENC].gst, "src"); + gst_pad_push_event(video, gst_event_new_flush_start()); + gst_pad_push_event(video, gst_event_new_flush_stop(TRUE)); + ret = gst_pad_push_event(video, gst_event_new_eos()); + _mmstreamrec_dbg_err("Sending EOS video encoder src pad : %d", ret); + gst_object_unref(video); + + if (sc->audio_enable == TRUE) { + audio = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_AENC].gst, "src"); + gst_pad_push_event(audio, gst_event_new_flush_start()); + gst_pad_push_event(audio, gst_event_new_flush_stop(TRUE)); + ret = gst_element_send_event(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, gst_event_new_eos()); + _mmstreamrec_dbg_err("Sending EOS audio encoder src pad : %d", ret); + gst_object_unref(audio); + } + } else { + if (sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst != NULL) { ret = gst_element_send_event(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, gst_event_new_eos()); _mmstreamrec_dbg_warn("send eos to appsrc result : %d", ret); - } + } - if (sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst != NULL) { - pad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, "src"); - ret = gst_element_send_event(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, gst_event_new_eos()); - gst_object_unref(pad); - pad = NULL; + if (sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst != NULL) { + pad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, "src"); + ret = gst_element_send_event(sc->encode_element[_MMSTREAMRECORDER_AUDIOSRC_SRC].gst, gst_event_new_eos()); + gst_object_unref(pad); + pad = NULL; - _mmstreamrec_dbg_warn("send eos to audiosrc result : %d", ret); + _mmstreamrec_dbg_warn("send eos to audiosrc result : %d", ret); + } } } - /* Wait EOS */ _mmstreamrec_dbg_log("Start to wait EOS"); ret = _mmstreamrecorder_get_eos_message(handle); @@ -1324,7 +1532,7 @@ int _mmstreamrecorder_video_handle_eos(MMHandleType handle) return TRUE; } -int _mmstreamrecorder_push_videostream_buffer(MMHandleType handle, unsigned long timestamp, GstBuffer *buffer, int size) +int _mmstreamrecorder_push_videostream_buffer(MMHandleType handle, unsigned long long timestamp, GstBuffer *buffer, int size) { mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle); _MMStreamRecorderSubContext *sc = NULL; @@ -1344,11 +1552,11 @@ int _mmstreamrecorder_push_videostream_buffer(MMHandleType handle, unsigned long mmf_return_val_if_fail(sc, MM_ERROR_STREAMRECORDER_NOT_INITIALIZED); if (buffer == NULL || size == 0) { - _mmstreamrec_dbg_err("video : Buffer is %p , size %d, time stamp is %ld", buffer, size, timestamp); + _mmstreamrec_dbg_err("video : Buffer is %p , size %d, time stamp is %lld", buffer, size, timestamp); return MM_ERROR_STREAMRECORDER_RESOURCE_CREATION; } - _mmstreamrec_dbg_log("video : Buffer is %p , size %d, time stamp is %ld", buffer, size, timestamp); + _mmstreamrec_dbg_log("video : Buffer is %p , size %d, time stamp is %lld", buffer, size, timestamp); /* check element availability */ 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); @@ -1364,7 +1572,7 @@ int _mmstreamrecorder_push_videostream_buffer(MMHandleType handle, unsigned long /*_mmstreamrec_dbg_log("Buffer Push start , time stamp %ld",timestamp);*/ /* srcpad = gst_element_get_static_pad(sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, "src"); */ /* srccaps = gst_pad_get_current_caps(srcpad); */ - srccaps = gst_set_videosrcpad_caps(video_src, video_width, video_height, video_fps, 1); + srccaps = gst_set_videosrcpad_caps_sw(video_src, video_width, video_height, video_fps, 1); if (srccaps) { gst_app_src_set_caps((GstAppSrc *) sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, srccaps); gst_caps_unref(srccaps); @@ -1373,6 +1581,7 @@ int _mmstreamrecorder_push_videostream_buffer(MMHandleType handle, unsigned long /*_mmstreamrec_dbg_err("newbuf streamrecorder(%p) ",newbuf);*/ ret = gst_app_src_push_buffer((GstAppSrc *) sc->encode_element[_MMSTREAMRECORDER_ENCSINK_SRC].gst, buffer); + if (ret) { _mmstreamrec_dbg_err("video gst_app_src_push_buffer %d", ret); ret = MM_ERROR_STREAMRECORDER_VIDEOBUFFER_PUSH; @@ -1384,7 +1593,7 @@ int _mmstreamrecorder_push_videostream_buffer(MMHandleType handle, unsigned long return ret; } -int _mmstreamrecorder_push_audiostream_buffer(MMHandleType handle, unsigned long timestamp, GstBuffer *buffer, int size) +int _mmstreamrecorder_push_audiostream_buffer(MMHandleType handle, unsigned long long timestamp, GstBuffer *buffer, int size) { mmf_streamrecorder_t *hstreamrecorder = MMF_STREAMRECORDER(handle); _MMStreamRecorderSubContext *sc = NULL; -- 2.7.4