Improve zerocopy format selection logic 36/238736/8
authorSangchul Lee <sc11.lee@samsung.com>
Thu, 16 Jul 2020 05:28:58 +0000 (14:28 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Fri, 17 Jul 2020 06:03:07 +0000 (15:03 +0900)
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 <sc11.lee@samsung.com>
include/media_streamer_gst.h
include/media_streamer_priv.h
include/media_streamer_util.h
packaging/capi-media-streamer.spec
src/media_streamer_gst.c
src/media_streamer_node.c
src/media_streamer_util.c

index 849153b537b980a3a94c5cbb9e56eafc23cfe2d2..128ce54842b62b2518368108a8bace37288c6d09 100644 (file)
@@ -148,15 +148,10 @@ 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.
index 4e03bebdc96dc4e8cfecb61693f3b94583823716..887c249cab6d67b5613cf58e7e33af72acb9407e 100644 (file)
@@ -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;
 
 /**
index a1362b31ccaa983c0b80e67220032480ce7a0343..97a0ee4fc7841a2097744af35f32d82cc551d922 100644 (file)
@@ -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.
index 5ad3e190b1f21d2a6bae0e71541c449bf217cc53..8fc4bd561ae384cddab0f7c9de9ee3c5a9bcb06f 100644 (file)
@@ -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
index 7d13a3acfe6a37cbfdb801b4f4086f9dd3a36a4e..56a9a97aa7bb3ad9c5876b19ce532db1ec2f579f 100644 (file)
@@ -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;
index 22dd7d35825db4db419d506984761fe905c3e85c..d5364482dc160b5c481ae1e591d030f93c6cf35b 100644 (file)
@@ -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();
 
index 91955ea86a4f0e63b078eea96e1d23c469752ac7..7cd5b2fd7bb4a07d5384d52a06352d85976f2fb3 100644 (file)
@@ -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)