From: Sangchul Lee Date: Fri, 7 Oct 2022 00:56:10 +0000 (+0900) Subject: webrtc_ini: Add new item for video h/w encoder caps extension X-Git-Tag: accepted/tizen/unified/20221107.173038~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a743dbe431212077bd5db47ae535776038f83672;p=platform%2Fcore%2Fapi%2Fwebrtc.git webrtc_ini: Add new item for video h/w encoder caps extension e.g.) [source camera] video hw encoder element = v4l2h264enc ; comma separated list of 'field-name=value' that will be set to the capsfilter video hw encoder caps ext = profile=constrained-baseline,level=3 Some video hardware encoder could require specific fields for its caps. For example, level, profile, and so on. A capsfilter for encoder is added. [Version] 0.3.258 [Issue Type] Improvement Change-Id: I2433db5f11b33712e2b720956a57f7bf340fc0b1 Signed-off-by: Sangchul Lee --- diff --git a/include/webrtc_private.h b/include/webrtc_private.h index 187b74df..6d3abae8 100644 --- a/include/webrtc_private.h +++ b/include/webrtc_private.h @@ -349,6 +349,7 @@ typedef struct _ini_item_media_source_s { int v_framerate; GStrv v_codecs; const char *v_hw_encoder_element; + GStrv v_hw_encoder_caps_ext; bool v_drc_support; bool v_encoded_fmt_support; /* audio source pipeline */ @@ -660,6 +661,7 @@ const char *_get_raw_format_from_ini(webrtc_ini_s *ini, int src_type, media_type const char *_get_first_codec_from_ini(webrtc_ini_s *ini, int src_type, media_type_e media_type); const char *_get_hw_encoder_from_ini(webrtc_ini_s *ini, int src_type, media_type_e media_type); GStrv _get_supported_codecs_from_ini(webrtc_ini_s *ini, int src_type, media_type_e media_type); +GStrv _get_v_hw_encoder_caps_ext_fields_from_ini(webrtc_ini_s *ini, int src_type); /* transceiver */ void _webrtcbin_on_new_transceiver_cb(GstElement *webrtcbin, GstWebRTCRTPTransceiver *transceiver, gpointer user_data); diff --git a/include/webrtc_source_private.h b/include/webrtc_source_private.h index cceafd88..4df96935 100644 --- a/include/webrtc_source_private.h +++ b/include/webrtc_source_private.h @@ -45,6 +45,7 @@ #define ELEMENT_NAME_FIRST_CAPSFILTER "firstCapsfilter" #define ELEMENT_NAME_RTP_CAPSFILTER "rtpCapsfilter" +#define ELEMENT_NAME_ENCODER_CAPSFILTER "encoderCapsfilter" #define ELEMENT_NAME_VIDEO_SRC "videoSrc" #define ELEMENT_NAME_VIDEO_SWITCH "videoSwitch" #define ELEMENT_NAME_VIDEO_MUTE_SRC "videoMuteSrc" @@ -95,5 +96,6 @@ GstCaps *_make_video_raw_caps_with_resolution(webrtc_gst_slot_s *source, webrtc_ void _release_request_pad(webrtc_gst_slot_s *source); bool _set_default_video_info(webrtc_gst_slot_s *source, const ini_item_media_source_s *ini_source); void _gst_set_element_properties(GstElement *element, GStrv key_value_pairs); +GstCaps *_gst_set_caps_additional_fields(GstCaps *caps, GStrv key_value_pairs); #endif /* __TIZEN_MEDIA_WEBRTC_SOURCE_COMMON_H__ */ diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index bb8fa901..8cf669a4 100644 --- a/packaging/capi-media-webrtc.spec +++ b/packaging/capi-media-webrtc.spec @@ -1,6 +1,6 @@ Name: capi-media-webrtc Summary: A WebRTC library in Tizen Native API -Version: 0.3.257 +Version: 0.3.258 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/webrtc_ini.c b/src/webrtc_ini.c index 28181520..ad38011b 100644 --- a/src/webrtc_ini.c +++ b/src/webrtc_ini.c @@ -72,6 +72,7 @@ #define INI_ITEM_VIDEO_ENCODED_FMT_SUPPORT "video encoded format support" /* source element supports encoded format */ #define INI_ITEM_VIDEO_CODECS "video codecs" #define INI_ITEM_VIDEO_HW_ENCODER_ELEMENT "video hw encoder element" +#define INI_ITEM_VIDEO_HW_ENCODER_CAPS_EXT "video hw encoder caps ext" #define INI_ITEM_AUDIO_RAW_FORMAT "audio raw format" #define INI_ITEM_AUDIO_SAMPLERATE "audio samplerate" #define INI_ITEM_AUDIO_CHANNELS "audio channels" @@ -203,6 +204,7 @@ static void __dump_items_of_source(ini_item_media_source_s *source) __dump_item(INI_ITEM_VIDEO_ENCODED_FMT_SUPPORT, INI_ITEM_TYPE_BOOL, &source->v_encoded_fmt_support); __dump_item(INI_ITEM_VIDEO_CODECS, INI_ITEM_TYPE_STRINGS, (void *)source->v_codecs); __dump_item(INI_ITEM_VIDEO_HW_ENCODER_ELEMENT, INI_ITEM_TYPE_STRING, (void *)source->v_hw_encoder_element); + __dump_item(INI_ITEM_VIDEO_HW_ENCODER_CAPS_EXT, INI_ITEM_TYPE_STRINGS, (void *)source->v_hw_encoder_caps_ext); __dump_item(INI_ITEM_AUDIO_RAW_FORMAT, INI_ITEM_TYPE_STRING, (void *)source->a_raw_format); __dump_item(INI_ITEM_AUDIO_SAMPLERATE, INI_ITEM_TYPE_INT, &source->a_samplerate); __dump_item(INI_ITEM_AUDIO_CHANNELS, INI_ITEM_TYPE_INT, &source->a_channels); @@ -389,6 +391,11 @@ static void __ini_source_destroy_cb(gpointer data) source->source_element_properties = NULL; } + if (source->v_hw_encoder_caps_ext) { + g_strfreev(source->v_hw_encoder_caps_ext); + source->v_hw_encoder_caps_ext = NULL; + } + g_free(source); } @@ -425,6 +432,7 @@ static void __apply_media_source_setting(webrtc_ini_s *ini, ini_item_media_sourc if (!is_default) { source->source_element = __ini_get_string(ini->dict, category, INI_ITEM_SOURCE_ELEMENT, NULL); __ini_read_list(ini->dict, category, INI_ITEM_SOURCE_ELEMENT_PROPERTIES, &source->source_element_properties, NULL); + __ini_read_list(ini->dict, category, INI_ITEM_VIDEO_HW_ENCODER_CAPS_EXT, &source->v_hw_encoder_caps_ext, NULL); } source->v_raw_format = __ini_get_string(ini->dict, category, INI_ITEM_VIDEO_RAW_FORMAT, @@ -740,6 +748,21 @@ GStrv _get_supported_codecs_from_ini(webrtc_ini_s *ini, int src_type, media_type else return ini_source->v_codecs; } + +//LCOV_EXCL_START +GStrv _get_v_hw_encoder_caps_ext_fields_from_ini(webrtc_ini_s *ini, int src_type) +{ + const ini_item_media_source_s *ini_source; + + RET_VAL_IF(ini == NULL, NULL, "ini is NULL"); + + if (!(ini_source = _ini_get_source_by_type(ini, src_type))) + return NULL; + + return ini_source->v_hw_encoder_caps_ext; +} +//LCOV_EXCL_STOP + void _unload_ini(webrtc_s *webrtc) { RET_IF(webrtc == NULL, "webrtc is NULL"); diff --git a/src/webrtc_source_private.c b/src/webrtc_source_private.c index f4e1a469..b4b0a680 100644 --- a/src/webrtc_source_private.c +++ b/src/webrtc_source_private.c @@ -470,6 +470,8 @@ static GstCaps *__make_default_encoded_caps(webrtc_gst_slot_s *source, webrtc_in _media_type = _get_video_media_type(source->av[AV_IDX_VIDEO].codec); RET_VAL_IF(_media_type == NULL, NULL, "_media_type is NULL"); caps = _get_caps_from_encoded_video_media_type(_media_type, source->video_info.width, source->video_info.height); + if (source->zerocopy_enabled) + caps = _gst_set_caps_additional_fields(caps, _get_v_hw_encoder_caps_ext_fields_from_ini(ini, source->type)); break; case WEBRTC_MEDIA_SOURCE_TYPE_AUDIOTEST: @@ -515,6 +517,8 @@ static GstCaps *__make_default_encoded_caps(webrtc_gst_slot_s *source, webrtc_in if (media_type) *media_type = g_strdup(_media_type); + PRINT_CAPS(caps, "default encoded"); + return caps; } @@ -801,7 +805,8 @@ int _create_rest_of_elements(webrtc_s *webrtc, webrtc_gst_slot_s *source, bool n GstElement *encoder = NULL; GstElement *payloader; GstElement *queue; - GstElement *capsfilter2; + GstElement *encoder_capsfilter = NULL; + GstElement *rtp_capsfilter; GstElement *videocrop; GstCaps *sink_caps; element_info_s elem_info; @@ -809,6 +814,7 @@ int _create_rest_of_elements(webrtc_s *webrtc, webrtc_gst_slot_s *source, bool n int idx; GstPad *pad_for_render = NULL; GstCaps *caps_for_render = NULL; + GstCaps *caps_for_encoder = NULL; RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL"); @@ -860,13 +866,21 @@ int _create_rest_of_elements(webrtc_s *webrtc, webrtc_gst_slot_s *source, bool n if (!(encoder = __prepare_encoder(webrtc, source, is_audio))) goto error; - APPEND_ELEMENT(*element_list, encoder); _set_need_decoding_for_loopback(source, idx, false); + + if (!(encoder_capsfilter = _create_element(DEFAULT_ELEMENT_CAPSFILTER, ELEMENT_NAME_ENCODER_CAPSFILTER))) + goto error; + APPEND_ELEMENT(*element_list, encoder_capsfilter); + skip_encoder: + caps_for_encoder = __make_default_encoded_caps(source, &webrtc->ini, &media_type); + if (encoder_capsfilter) + g_object_set(G_OBJECT(encoder_capsfilter), "caps", caps_for_encoder, NULL); + CREATE_ELEMENT_FROM_REGISTRY(elem_info, GST_KLASS_NAME_PAYLOADER_RTP, - __make_default_encoded_caps(source, &webrtc->ini, &media_type), + caps_for_encoder, NULL, NULL, payloader); @@ -878,15 +892,15 @@ skip_encoder: goto error; APPEND_ELEMENT(*element_list, queue); - if (!(capsfilter2 = _create_element(DEFAULT_ELEMENT_CAPSFILTER, ELEMENT_NAME_RTP_CAPSFILTER))) + if (!(rtp_capsfilter = _create_element(DEFAULT_ELEMENT_CAPSFILTER, ELEMENT_NAME_RTP_CAPSFILTER))) goto error; - APPEND_ELEMENT(*element_list, capsfilter2); + APPEND_ELEMENT(*element_list, rtp_capsfilter); if (_set_payload_type(webrtc, source, idx, media_type) != WEBRTC_ERROR_NONE) goto error; if ((sink_caps = _make_rtp_caps(media_type, source->av[idx].pt, source, encoder))) { - g_object_set(G_OBJECT(capsfilter2), "caps", sink_caps, NULL); + g_object_set(G_OBJECT(rtp_capsfilter), "caps", sink_caps, NULL); gst_caps_unref(sink_caps); } @@ -1003,6 +1017,7 @@ bool _set_default_video_info(webrtc_gst_slot_s *source, const ini_item_media_sou return true; } +//LCOV_EXCL_START static void __parse_type_and_set_value(GType type, GstElement *element, GStrv key_value_pair) { RET_IF(element == NULL, "element is NULL"); @@ -1073,4 +1088,36 @@ void _gst_set_element_properties(GstElement *element, GStrv key_value_pairs) g_strfreev(key_value_pair); } -} \ No newline at end of file +} + +GstCaps *_gst_set_caps_additional_fields(GstCaps *caps, GStrv key_value_pairs) +{ + GStrv key_value_pair; + + if (!caps) + return NULL; + + if (!key_value_pairs) + return NULL; + + while (key_value_pairs && *key_value_pairs) { + key_value_pair = g_strsplit(*key_value_pairs++, "=", 2); + + if (!g_strcmp0(key_value_pair[0], "") || !g_strcmp0(key_value_pair[1], "")) { + LOG_ERROR("invalid key_value_pair, key[%s], value[%s]", key_value_pair[0], key_value_pair[1]); + g_strfreev(key_value_pair); + continue; + } + + gst_caps_set_simple(caps, + key_value_pair[0], G_TYPE_STRING, key_value_pair[1], + NULL); + + LOG_DEBUG("field[%s] value[%s]", key_value_pair[0], key_value_pair[1]); + + g_strfreev(key_value_pair); + } + + return caps; +} +//LCOV_EXCL_STOP \ No newline at end of file