encodebin: Add flags to disable conversion elements
authorRobert Swain <robert.swain@collabora.co.uk>
Wed, 29 Jun 2011 11:12:49 +0000 (13:12 +0200)
committerRobert Swain <robert.swain@collabora.co.uk>
Wed, 29 Jun 2011 22:59:18 +0000 (00:59 +0200)
Add a flags property and two flags to allow one to disable the
conversion elements within encodebin. Doing so insists that the
uncompressed input to encodebin for the appropriate stream type is
sufficient to meet the caps requirements of the encoders, muxers and
encodebin target.

This is mostly beneficial to bypass slow caps negotiations in the
conversion elements.

gst/encoding/gstencodebin.c

index d90e74597dbc972ca3aa9e3780e822faa2bcd781..446f93b3c066cefc71ae409411cd674f2f2af5b4 100644 (file)
 #define fast_pad_link(a,b) gst_pad_link_full((a),(b),GST_PAD_LINK_CHECK_NOTHING)
 #define fast_element_link(a,b) gst_element_link_pads_full((a),"src",(b),"sink",GST_PAD_LINK_CHECK_NOTHING)
 
+typedef enum
+{
+  GST_ENC_FLAG_NATIVE_AUDIO = (1 << 0),
+  GST_ENC_FLAG_NATIVE_VIDEO = (1 << 1)
+} GstEncFlags;
+
+#define GST_TYPE_ENC_FLAGS (gst_enc_flags_get_type())
+GType gst_enc_flags_get_type (void);
+
 /* generic templates */
 static GstStaticPadTemplate muxer_src_template =
 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
@@ -180,6 +189,8 @@ struct _GstEncodeBin
 
   guint64 tolerance;
   gboolean avoid_reencoding;
+
+  GstEncFlags flags;
 };
 
 struct _GstEncodeBinClass
@@ -216,6 +227,7 @@ struct _StreamGroup
 #define DEFAULT_QUEUE_TIME_MAX     GST_SECOND
 #define DEFAULT_AUDIO_JITTER_TOLERANCE 20 * GST_MSECOND
 #define DEFAULT_AVOID_REENCODING   FALSE
+#define DEFAULT_FLAGS              0
 
 #define DEFAULT_RAW_CAPS                       \
   "video/x-raw-yuv; "                          \
@@ -238,6 +250,7 @@ enum
   PROP_QUEUE_TIME_MAX,
   PROP_AUDIO_JITTER_TOLERANCE,
   PROP_AVOID_REENCODING,
+  PROP_FLAGS,
   PROP_LAST
 };
 
@@ -248,6 +261,31 @@ enum
   LAST_SIGNAL
 };
 
+#define C_FLAGS(v) ((guint) v)
+
+GType
+gst_enc_flags_get_type (void)
+{
+  static const GFlagsValue values[] = {
+    {C_FLAGS (GST_ENC_FLAG_NATIVE_AUDIO), "Only use native audio formats",
+        "native-audio"},
+    {C_FLAGS (GST_ENC_FLAG_NATIVE_VIDEO), "Only use native video formats",
+        "native-video"},
+    {0, NULL, NULL}
+  };
+  static volatile GType id = 0;
+
+  if (g_once_init_enter ((gsize *) & id)) {
+    GType _id;
+
+    _id = g_flags_register_static ("GstEncFlags", values);
+
+    g_once_init_leave ((gsize *) & id, _id);
+  }
+
+  return id;
+}
+
 static guint gst_encode_bin_signals[LAST_SIGNAL] = { 0 };
 
 static GstStaticCaps default_raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS);
@@ -339,6 +377,16 @@ gst_encode_bin_class_init (GstEncodeBinClass * klass)
           DEFAULT_AVOID_REENCODING,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  /**
+   * GstEncodeBin:flags
+   *
+   * Control the behaviour of encodebin.
+   */
+  g_object_class_install_property (gobject_klass, PROP_FLAGS,
+      g_param_spec_flags ("flags", "Flags", "Flags to control behaviour",
+          GST_TYPE_ENC_FLAGS, DEFAULT_FLAGS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   /* Signals */
   /**
    * GstEncodeBin::request-pad
@@ -447,6 +495,7 @@ gst_encode_bin_init (GstEncodeBin * encode_bin)
   encode_bin->queue_time_max = DEFAULT_QUEUE_TIME_MAX;
   encode_bin->tolerance = DEFAULT_AUDIO_JITTER_TOLERANCE;
   encode_bin->avoid_reencoding = DEFAULT_AVOID_REENCODING;
+  encode_bin->flags = DEFAULT_FLAGS;
 
   tmpl = gst_static_pad_template_get (&muxer_src_template);
   encode_bin->srcpad = gst_ghost_pad_new_no_target_from_template ("src", tmpl);
@@ -480,6 +529,9 @@ gst_encode_bin_set_property (GObject * object, guint prop_id,
     case PROP_AVOID_REENCODING:
       ebin->avoid_reencoding = g_value_get_boolean (value);
       break;
+    case PROP_FLAGS:
+      ebin->flags = g_value_get_flags (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -511,6 +563,9 @@ gst_encode_bin_get_property (GObject * object, guint prop_id,
     case PROP_AVOID_REENCODING:
       g_value_set_boolean (value, ebin->avoid_reencoding);
       break;
+    case PROP_FLAGS:
+      g_value_set_flags (value, ebin->flags);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1206,37 +1261,40 @@ _create_stream_group (GstEncodeBin * ebin, GstEncodingProfile * sprof,
   /* 3.2. restriction elements */
   /* FIXME : Once we have properties for specific converters, use those */
   if (GST_IS_ENCODING_VIDEO_PROFILE (sprof)) {
+    const gboolean native_video = ! !(ebin->flags & GST_ENC_FLAG_NATIVE_VIDEO);
     GstElement *cspace, *scale, *vrate, *cspace2;
 
     GST_LOG ("Adding conversion elements for video stream");
 
-    cspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
-    scale = gst_element_factory_make ("videoscale", NULL);
-    if (!scale) {
-      missing_element_name = "videoscale";
-      goto missing_element;
-    }
-    /* 4-tap scaling and black borders */
-    g_object_set (scale, "method", 2, "add-borders", TRUE, NULL);
-    cspace2 = gst_element_factory_make ("ffmpegcolorspace", NULL);
+    if (!native_video) {
+      cspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
+      scale = gst_element_factory_make ("videoscale", NULL);
+      if (!scale) {
+        missing_element_name = "videoscale";
+        goto missing_element;
+      }
+      /* 4-tap scaling and black borders */
+      g_object_set (scale, "method", 2, "add-borders", TRUE, NULL);
+      cspace2 = gst_element_factory_make ("ffmpegcolorspace", NULL);
 
-    if (!cspace || !cspace2) {
-      missing_element_name = "ffmpegcolorspace";
-      goto missing_element;
-    }
+      if (!cspace || !cspace2) {
+        missing_element_name = "ffmpegcolorspace";
+        goto missing_element;
+      }
 
-    gst_bin_add_many ((GstBin *) ebin, cspace, scale, cspace2, NULL);
-    tosync = g_list_append (tosync, cspace);
-    tosync = g_list_append (tosync, scale);
-    tosync = g_list_append (tosync, cspace2);
+      gst_bin_add_many ((GstBin *) ebin, cspace, scale, cspace2, NULL);
+      tosync = g_list_append (tosync, cspace);
+      tosync = g_list_append (tosync, scale);
+      tosync = g_list_append (tosync, cspace2);
 
-    sgroup->converters = g_list_prepend (sgroup->converters, cspace);
-    sgroup->converters = g_list_prepend (sgroup->converters, scale);
-    sgroup->converters = g_list_prepend (sgroup->converters, cspace2);
+      sgroup->converters = g_list_prepend (sgroup->converters, cspace);
+      sgroup->converters = g_list_prepend (sgroup->converters, scale);
+      sgroup->converters = g_list_prepend (sgroup->converters, cspace2);
 
-    if (!fast_element_link (cspace, scale) ||
-        !fast_element_link (scale, cspace2))
-      goto converter_link_failure;
+      if (!fast_element_link (cspace, scale) ||
+          !fast_element_link (scale, cspace2))
+        goto converter_link_failure;
+    }
 
     if (!gst_encoding_video_profile_get_variableframerate
         (GST_ENCODING_VIDEO_PROFILE (sprof))) {
@@ -1249,15 +1307,23 @@ _create_stream_group (GstEncodeBin * ebin, GstEncodingProfile * sprof,
       gst_bin_add ((GstBin *) ebin, vrate);
       tosync = g_list_prepend (tosync, vrate);
       sgroup->converters = g_list_prepend (sgroup->converters, vrate);
-      if (!fast_element_link (cspace2, vrate) ||
-          !fast_element_link (vrate, last))
+
+      if ((!native_video && !fast_element_link (cspace2, vrate))
+          || !fast_element_link (vrate, last))
         goto converter_link_failure;
-    } else if (!fast_element_link (cspace2, last))
-      goto converter_link_failure;
 
-    last = cspace;
+      if (!native_video)
+        last = cspace;
+      else
+        last = vrate;
+    } else if (!native_video) {
+      if (!fast_element_link (cspace2, last))
+        goto converter_link_failure;
+      last = cspace;
+    }
 
-  } else if (GST_IS_ENCODING_AUDIO_PROFILE (sprof)) {
+  } else if (GST_IS_ENCODING_AUDIO_PROFILE (sprof)
+      && !(ebin->flags & GST_ENC_FLAG_NATIVE_AUDIO)) {
     GstElement *aconv, *ares, *arate, *aconv2;
 
     GST_LOG ("Adding conversion elements for audio stream");