webrtc_ini: Add new item for video h/w encoder caps extension 29/283529/1
authorSangchul Lee <sc11.lee@samsung.com>
Fri, 7 Oct 2022 00:56:10 +0000 (09:56 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Fri, 28 Oct 2022 05:33:07 +0000 (14:33 +0900)
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 <sc11.lee@samsung.com>
include/webrtc_private.h
include/webrtc_source_private.h
packaging/capi-media-webrtc.spec
src/webrtc_ini.c
src/webrtc_source_private.c

index 187b74df77633d9756ff052dadbbd30604ded646..6d3abae8f91214fac9b7d17a45f2a293c15c985c 100644 (file)
@@ -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);
index cceafd881bae53b479624a26ce56ce6829de9a31..4df9693589c6facfaa7590de4bea42a27015173c 100644 (file)
@@ -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__ */
index bb8fa901a6388d9d20f47374ae7222a9afd571eb..8cf669a44f6727237313e84feff05eedc33139b3 100644 (file)
@@ -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
index 281815208181a92761a8143ba74e81825f001379..ad38011bec3b76ecc6e8bf8f177e276096a394e1 100644 (file)
@@ -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");
index f4e1a4691e0b7c2006095e6a50b1b68c895d4604..b4b0a6809f1ee60db61244fa3be09beff1e7ed36 100644 (file)
@@ -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