From: Sangchul Lee Date: Thu, 16 Jul 2020 05:28:58 +0000 (+0900) Subject: Improve zerocopy format selection logic X-Git-Tag: accepted/tizen/unified/20200723.161243~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b37b9a4a471ca2b169833a74d2aeaa2668a480fb;p=platform%2Fcore%2Fapi%2Fmediastreamer.git Improve zerocopy format selection logic Previously, it always converted zerocopy format if it meets the predefined format in hard-coded array. Because it did not care the node type and zerocopy format, there happened a case that invalid converting format from I420 to S420 with videotestsrc and capsfilter. This patch adds to look into the supported zerocopy node names and formats in ini file. For example of one target, the zerocopy feature can be defined in mmfw_media_streamer.ini as below. use zerocopy = yes zerocopy node names = video_decoder,video_encoder,capsfilter zerocopy formats = SN12 [Version] 0.1.97 [Issue Type] Improvement Change-Id: Ie74703f8a88de11193748dc8b452de21485408c3 Signed-off-by: Sangchul Lee --- diff --git a/include/media_streamer_gst.h b/include/media_streamer_gst.h index 849153b..128ce54 100644 --- a/include/media_streamer_gst.h +++ b/include/media_streamer_gst.h @@ -149,14 +149,9 @@ int ms_element_pad_names(GstElement *element, GstPadDirection pad_type, char *** int ms_element_get_pad_fmt(GstElement *element, const char *pad_name, media_format_h *fmt); /** - * @brief Sets mediaformat to the GstElement's pad. - */ -int ms_element_set_fmt(GstElement *element, const char *pad_name, media_format_h fmt); - -/** * @brief Creates GstCap's from mediaformat. */ -GstCaps *ms_create_caps_from_fmt(media_format_h fmt); +GstCaps *ms_create_caps_from_fmt(media_format_h fmt, const char *node_name); /** * @brief Seeks GstElement to according time value. diff --git a/include/media_streamer_priv.h b/include/media_streamer_priv.h index 4e03beb..887c249 100644 --- a/include/media_streamer_priv.h +++ b/include/media_streamer_priv.h @@ -67,8 +67,8 @@ typedef struct { * @brief Media Streamer node_info type handle. */ typedef struct { - char *klass_name; - char *default_name; + const char *klass_name; + const char *default_name; } node_info_s; /** diff --git a/include/media_streamer_util.h b/include/media_streamer_util.h index a1362b3..97a0ee4 100644 --- a/include/media_streamer_util.h +++ b/include/media_streamer_util.h @@ -287,7 +287,7 @@ const gchar *ms_convert_audio_mime_to_string_format(media_format_mimetype_e mime /** * @brief Converts Media Format mime type into Caps media format string for video. */ -const gchar *ms_convert_video_mime_to_string_format(media_format_mimetype_e mime); +const gchar *ms_convert_video_mime_to_string_format(media_format_mimetype_e mime, const char *node_name); /** * @brief Converts Media Format mime type into Caps media format string for container. diff --git a/packaging/capi-media-streamer.spec b/packaging/capi-media-streamer.spec index 5ad3e19..8fc4bd5 100644 --- a/packaging/capi-media-streamer.spec +++ b/packaging/capi-media-streamer.spec @@ -1,6 +1,6 @@ Name: capi-media-streamer Summary: A Media Streamer API -Version: 0.1.96 +Version: 0.1.97 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/media_streamer_gst.c b/src/media_streamer_gst.c index 7d13a3a..56a9a97 100644 --- a/src/media_streamer_gst.c +++ b/src/media_streamer_gst.c @@ -2461,7 +2461,7 @@ gboolean ms_pipeline_is_get_state_with_no_preroll(media_streamer_s *ms_streamer) return FALSE; } -GstCaps *ms_create_caps_from_fmt(media_format_h fmt) +GstCaps *ms_create_caps_from_fmt(media_format_h fmt, const char *node_name) { GstCaps *caps = NULL; gchar *caps_name = NULL; @@ -2487,9 +2487,10 @@ GstCaps *ms_create_caps_from_fmt(media_format_h fmt) } else if (!media_format_get_video_info(fmt, &mime, &width, &height, &avg_bps, &max_bps)) { if (MEDIA_FORMAT_RAW == (mime & MEDIA_FORMAT_RAW)) caps = gst_caps_new_simple("video/x-raw", "framerate", GST_TYPE_FRACTION, max_bps, - avg_bps, "format", G_TYPE_STRING, ms_convert_video_mime_to_string_format(mime), "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); + avg_bps, "format", G_TYPE_STRING, ms_convert_video_mime_to_string_format(mime, node_name), + "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); else if (MEDIA_FORMAT_ENCODED == (mime & MEDIA_FORMAT_ENCODED)) - caps = gst_caps_new_simple(ms_convert_video_mime_to_string_format(mime), "framerate", GST_TYPE_FRACTION, max_bps, + caps = gst_caps_new_simple(ms_convert_video_mime_to_string_format(mime, node_name), "framerate", GST_TYPE_FRACTION, max_bps, avg_bps, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); caps_name = gst_caps_to_string(caps); ms_info("Creating Video Caps from media format [%s]", caps_name); @@ -2670,47 +2671,6 @@ int ms_element_get_pad_fmt(GstElement *gst_element, const char *pad_name, media_ return ret; } -int ms_element_set_fmt(GstElement *element, const char *pad_name, media_format_h fmt) -{ - gboolean can_accept = FALSE; - GstCaps *fmt_caps = NULL; - GstElementFactory *factory = NULL; - GstPad *node_pad = NULL; - - ms_debug_fenter(); - - ms_retvm_if(!element || !pad_name || !fmt, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL"); - - fmt_caps = ms_create_caps_from_fmt(fmt); - ms_retvm_if(!fmt_caps, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Can't convert fmt into Caps"); - - factory = gst_element_get_factory(element); - node_pad = gst_element_get_static_pad(element, pad_name); - - if (node_pad && GST_PAD_IS_SRC(node_pad)) - can_accept = gst_element_factory_can_src_any_caps(factory, fmt_caps); - else if (node_pad && GST_PAD_IS_SINK(node_pad)) - can_accept = gst_element_factory_can_sink_any_caps(factory, fmt_caps); - else - ms_error("[%s] doesn`t have valid pad [%s]", GST_ELEMENT_NAME(element), pad_name); - - if (!can_accept) { - if (fmt_caps) - gst_caps_unref(fmt_caps); - ms_error("[%s]'s pad [%s] can`t be set with the given format", GST_ELEMENT_NAME(element), pad_name); - return MEDIA_STREAMER_ERROR_INVALID_OPERATION; - } else { - MS_SET_INT_CAPS_PARAM(element, pad_name, fmt_caps); - ms_info("[%s]'s pad [%s] was set with given format", GST_ELEMENT_NAME(element), pad_name); - } - - MS_SAFE_UNREF(node_pad); - - ms_debug_fleave(); - - return MEDIA_STREAMER_ERROR_NONE; -} - gboolean ms_gst_seek(GstElement *element, gint64 g_time, GstSeekFlags seek_flag) { gboolean result = FALSE; diff --git a/src/media_streamer_node.c b/src/media_streamer_node.c index 22dd7d3..d536448 100644 --- a/src/media_streamer_node.c +++ b/src/media_streamer_node.c @@ -530,8 +530,8 @@ int ms_node_create(media_streamer_node_s *node, media_format_h in_fmt, media_for return ret; } - sink_caps = in_fmt ? ms_create_caps_from_fmt(in_fmt) : NULL; - src_caps = out_fmt ? ms_create_caps_from_fmt(out_fmt) : NULL; + sink_caps = in_fmt ? ms_create_caps_from_fmt(in_fmt, nodes_info[node->type].default_name) : NULL; + src_caps = out_fmt ? ms_create_caps_from_fmt(out_fmt, nodes_info[node->type].default_name) : NULL; node_plug_s plug_info = {&(nodes_info[node->type]), src_caps, sink_caps, NULL}; @@ -2078,6 +2078,55 @@ static int __ms_webrtc_node_set_pad_format(media_streamer_node_s *node, const ch return ret; } +static int __ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt) +{ + gboolean can_accept = FALSE; + GstElement *element = NULL; + GstCaps *fmt_caps = NULL; + GstElementFactory *factory = NULL; + GstPad *node_pad = NULL; + + ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL"); + ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL"); + ms_retvm_if(!pad_name, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL"); + ms_retvm_if(!fmt, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL"); + + element = node->gst_element; + + fmt_caps = ms_create_caps_from_fmt(fmt, nodes_info[node->type].default_name); + ms_retvm_if(!fmt_caps, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Can't convert fmt into Caps"); + + factory = gst_element_get_factory(element); + node_pad = gst_element_get_static_pad(element, pad_name); + if (!node_pad) { + gst_caps_unref(fmt_caps); + ms_error("Failed to gst_element_get_static_pad(), pad_name[%s]", pad_name); + return MEDIA_STREAMER_ERROR_INVALID_OPERATION; + } + + if (GST_PAD_IS_SRC(node_pad)) + can_accept = gst_element_factory_can_src_any_caps(factory, fmt_caps); + else if (GST_PAD_IS_SINK(node_pad)) + can_accept = gst_element_factory_can_sink_any_caps(factory, fmt_caps); + else + ms_error("[%s] doesn`t have valid pad [%s]", GST_ELEMENT_NAME(element), pad_name); + + MS_SAFE_UNREF(node_pad); + + if (!can_accept) { + gst_caps_unref(fmt_caps); + ms_error("[%s]'s pad [%s] can`t be set with the given format", GST_ELEMENT_NAME(element), pad_name); + return MEDIA_STREAMER_ERROR_INVALID_OPERATION; + } + + MS_SET_INT_CAPS_PARAM(element, pad_name, fmt_caps); + gst_caps_unref(fmt_caps); + + ms_info("[%s]'s pad [%s] was set with given format", GST_ELEMENT_NAME(element), pad_name); + + return MEDIA_STREAMER_ERROR_NONE; +} + int ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt) { int ret = MEDIA_STREAMER_ERROR_NONE; @@ -2094,7 +2143,7 @@ int ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, me else if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC) ret = __ms_webrtc_node_set_pad_format(node, pad_name, fmt); else - ret = ms_element_set_fmt(node->gst_element, pad_name, fmt); + ret = __ms_node_set_pad_format(node, pad_name, fmt); ms_debug_fleave(); diff --git a/src/media_streamer_util.c b/src/media_streamer_util.c index 91955ea..7cd5b2f 100644 --- a/src/media_streamer_util.c +++ b/src/media_streamer_util.c @@ -243,30 +243,61 @@ const gchar *ms_convert_audio_mime_to_string_format(media_format_mimetype_e mime return format_name; } -const gchar *ms_convert_video_mime_to_string_format(media_format_mimetype_e mime) +const gchar *ms_convert_video_mime_to_string_format(media_format_mimetype_e mime, const char *node_name) { gchar *format_name = NULL; - int it_format; + int index; gboolean use_zerocopy_fmt = DEFAULT_USE_ZEROCOPY; + gboolean need_to_check_zerocopy_format = FALSE; - ms_debug_fenter(); + ms_retvm_if(node_name == NULL, NULL, "node_name is null"); use_zerocopy_fmt = ms_ini_get_boolean("general:use zerocopy", DEFAULT_USE_ZEROCOPY); + if (use_zerocopy_fmt) { + gchar **zerocopy_node_names = NULL; + ms_ini_read_list("general:zerocopy node names", &zerocopy_node_names); - for (it_format = 0; video_format_table[it_format].format != MEDIA_FORMAT_MAX; it_format++) { - if (mime == video_format_table[it_format].format) { - format_name = video_format_table[it_format].format_name; - break; + for (index = 0; zerocopy_node_names && zerocopy_node_names[index]; index++) { + if (!strcmp(node_name, zerocopy_node_names[index])) { + need_to_check_zerocopy_format = TRUE; + ms_debug("node_name[%s] can use zerocopy format", node_name); + break; + } } + g_strfreev(zerocopy_node_names); } - if (use_zerocopy_fmt) { - for (it_format = 0; zerocopy_video_format_table[it_format].format != MEDIA_FORMAT_MAX; it_format++) { - if (mime == zerocopy_video_format_table[it_format].format) { - format_name = zerocopy_video_format_table[it_format].format_name; + if (need_to_check_zerocopy_format) { + for (index = 0; zerocopy_video_format_table[index].format != MEDIA_FORMAT_MAX; index++) { + if (mime == zerocopy_video_format_table[index].format) { + format_name = zerocopy_video_format_table[index].format_name; + ms_debug("mime[0x%x] -> zerocopy format[%s]", mime, format_name); break; } } + if (format_name) { + gchar **zerocopy_formats = NULL; + ms_ini_read_list("general:zerocopy formats", &zerocopy_formats); + + for (index = 0; zerocopy_formats && zerocopy_formats[index]; index++) { + if (!strcmp(format_name, zerocopy_formats[index])) { + ms_info("zerocopy format[%s]", format_name); + g_strfreev(zerocopy_formats); + return format_name; + } + } + g_strfreev(zerocopy_formats); + ms_debug("[%s] is not supported in this target", format_name); + } else { + ms_debug("Not supported this mimetype[0x%x] for zerocopy", mime); + } + } + + for (index = 0; video_format_table[index].format != MEDIA_FORMAT_MAX; index++) { + if (mime == video_format_table[index].format) { + format_name = video_format_table[index].format_name; + break; + } } if (!format_name)