RELEASE: GStreamer FFmpeg Plug-ins 0.10.12 "A year in hell"

Tvrtko Ursulin tvrtko.ursulin at onelan.co.uk
Thu Aug 11 02:02:47 PDT 2011


On Wednesday 20 Jul 2011 12:02:00 Edward Hervey wrote:
> This mail announces the release of GStreamer FFmpeg Plug-ins 0.10.12 "A
> year in hell"
> 
> GStreamer FFmpeg plug-in contains  elements using the FFmpeg library
> code. It contains most popular decoders and encoders.
> 
> Highlights of this release:
>       * Bump to LibAV 0.7
>       * Timestamp tracking fixes
>       * New codecs
>       * Multi-threaded decoding

I see that multi-threaded decoding is disabled by default in gstffmpegdec. Is this
because of known issues and how serious are they?

With regards to ffdeinterlace - I did a pretty mechanical (not understading GStreamer
internals and code base that well) patch  porting the mode property from good plugins
deinterlace because having this control and automatic mode is quite convenient for us.

Would something like this be acceptable for merging upstream? At least in principle, I realize patch might have issues. :)

Thanks,

Tvrtko


diff -uprN a/gst-ffmpeg-0.10.12/ext/ffmpeg/gstffmpegdeinterlace.c b/gst-ffmpeg-0.10.12/ext/ffmpeg/gstffmpegdeinterlace.c
--- a/gst-ffmpeg-0.10.12/ext/ffmpeg/gstffmpegdeinterlace.c	2011-07-13 10:07:28.000000000 +0100
+++ b/gst-ffmpeg-0.10.12/ext/ffmpeg/gstffmpegdeinterlace.c	2011-08-04 11:11:30.542756021 +0100
@@ -37,6 +37,44 @@
 #include "gstffmpegcodecmap.h"
 #include "gstffmpegutils.h"
 
+
+/* Properties */
+
+#define DEFAULT_MODE            GST_FFMPEGDEINTERLACE_MODE_AUTO
+
+enum
+{
+  PROP_0,
+  PROP_MODE,
+  PROP_LAST
+};
+
+typedef enum {
+  GST_FFMPEGDEINTERLACE_MODE_AUTO,
+  GST_FFMPEGDEINTERLACE_MODE_INTERLACED,
+  GST_FFMPEGDEINTERLACE_MODE_DISABLED
+} GstFFMpegDeinterlaceMode;
+
+#define GST_TYPE_FFMPEGDEINTERLACE_MODES (gst_ffmpegdeinterlace_modes_get_type ())
+static GType
+gst_ffmpegdeinterlace_modes_get_type (void)
+{
+  static GType deinterlace_modes_type = 0;
+
+  static const GEnumValue modes_types[] = {
+    {GST_FFMPEGDEINTERLACE_MODE_AUTO, "Auto detection", "auto"},
+    {GST_FFMPEGDEINTERLACE_MODE_INTERLACED, "Force deinterlacing", "interlaced"},
+    {GST_FFMPEGDEINTERLACE_MODE_DISABLED, "Run in passthrough mode", "disabled"},
+    {0, NULL, NULL},
+  };
+
+  if (!deinterlace_modes_type) {
+    deinterlace_modes_type =
+        g_enum_register_static ("GstFFMpegDeinterlaceModes", modes_types);
+  }
+  return deinterlace_modes_type;
+}
+
 typedef struct _GstFFMpegDeinterlace
 {
   GstElement element;
@@ -46,6 +84,14 @@ typedef struct _GstFFMpegDeinterlace
   gint width, height;
   gint to_size;
 
+  GstFFMpegDeinterlaceMode mode;
+  
+  gboolean interlaced; /* is input interlaced? */
+  gboolean passthrough;
+  
+  gboolean reconfigure;
+  GstFFMpegDeinterlaceMode new_mode;
+  
   enum PixelFormat pixfmt;
   AVPicture from_frame, to_frame;
 } GstFFMpegDeinterlace;
@@ -68,6 +114,11 @@ typedef struct _GstFFMpegDeinterlaceClas
 
 GType gst_ffmpegdeinterlace_get_type (void);
 
+static void gst_ffmpegdeinterlace_set_property (GObject * self, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_ffmpegdeinterlace_get_property (GObject * self, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
@@ -103,6 +154,34 @@ gst_ffmpegdeinterlace_base_init (gpointe
 static void
 gst_ffmpegdeinterlace_class_init (GstFFMpegDeinterlaceClass * klass)
 {
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+
+  gobject_class->set_property = gst_ffmpegdeinterlace_set_property;
+  gobject_class->get_property = gst_ffmpegdeinterlace_get_property;
+
+  /**
+   * GstDeinterlace:mode
+   * 
+   * This selects whether the deinterlacing methods should
+   * always be applied or if they should only be applied
+   * on content that has the "interlaced" flag on the caps.
+   *
+   */
+  g_object_class_install_property (gobject_class, PROP_MODE,
+      g_param_spec_enum ("mode",
+          "Mode",
+          "Deinterlace Mode",
+          GST_TYPE_FFMPEGDEINTERLACE_MODES,
+          DEFAULT_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
+      );
+}
+
+static void
+gst_ffmpegdeinterlace_update_passthrough (GstFFMpegDeinterlace * deinterlace)
+{
+  deinterlace->passthrough = (deinterlace->mode == GST_FFMPEGDEINTERLACE_MODE_DISABLED
+      || (!deinterlace->interlaced && deinterlace->mode != GST_FFMPEGDEINTERLACE_MODE_INTERLACED));
+  GST_DEBUG_OBJECT (deinterlace, "Passthrough: %d", deinterlace->passthrough);
 }
 
 static gboolean
@@ -120,6 +199,10 @@ gst_ffmpegdeinterlace_sink_setcaps (GstP
   if (!gst_structure_get_int (structure, "height", &deinterlace->height))
     return FALSE;
 
+  deinterlace->interlaced = FALSE;
+  gst_structure_get_boolean (structure, "interlaced", &deinterlace->interlaced);
+  gst_ffmpegdeinterlace_update_passthrough (deinterlace);
+
   ctx = avcodec_alloc_context ();
   ctx->width = deinterlace->width;
   ctx->height = deinterlace->height;
@@ -138,10 +221,10 @@ gst_ffmpegdeinterlace_sink_setcaps (GstP
       avpicture_get_size (deinterlace->pixfmt, deinterlace->width,
       deinterlace->height);
 
-  src_caps = gst_caps_copy (caps);
-  gst_caps_set_simple (src_caps, "interlaced", G_TYPE_BOOLEAN, FALSE, NULL);
-  ret = gst_pad_set_caps (deinterlace->srcpad, src_caps);
-  gst_caps_unref (src_caps);
+  src_caps = gst_caps_copy (caps);
+  gst_caps_set_simple (src_caps, "interlaced", G_TYPE_BOOLEAN, deinterlace->interlaced, NULL);
+  ret = gst_pad_set_caps (deinterlace->srcpad, src_caps);
+  gst_caps_unref (src_caps);
 
   return ret;
 }
@@ -162,6 +245,12 @@ gst_ffmpegdeinterlace_init (GstFFMpegDei
   gst_element_add_pad (GST_ELEMENT (deinterlace), deinterlace->srcpad);
 
   deinterlace->pixfmt = PIX_FMT_NB;
+
+  deinterlace->interlaced = FALSE;
+  deinterlace->passthrough = FALSE;
+  deinterlace->reconfigure = FALSE;
+  deinterlace->mode = DEFAULT_MODE;
+  deinterlace->new_mode = -1;
 }
 
 static GstFlowReturn
@@ -172,6 +261,23 @@ gst_ffmpegdeinterlace_chain (GstPad * pa
   GstBuffer *outbuf = NULL;
   GstFlowReturn result;
 
+  GST_OBJECT_LOCK (deinterlace);
+  if (deinterlace->reconfigure) {
+    if (deinterlace->new_mode != -1)
+      deinterlace->mode = deinterlace->new_mode;
+    deinterlace->new_mode = -1;
+
+    deinterlace->reconfigure = FALSE;
+    GST_OBJECT_UNLOCK (deinterlace);
+    if (GST_PAD_CAPS (deinterlace->srcpad))
+      gst_ffmpegdeinterlace_sink_setcaps (deinterlace->sinkpad, GST_PAD_CAPS (deinterlace->sinkpad));
+  } else {
+    GST_OBJECT_UNLOCK (deinterlace);
+  }
+  
+  if (deinterlace->passthrough)
+      return gst_pad_push (deinterlace->srcpad, inbuf);
+
   result =
       gst_pad_alloc_buffer (deinterlace->srcpad, GST_BUFFER_OFFSET_NONE,
       deinterlace->to_size, GST_PAD_CAPS (deinterlace->srcpad), &outbuf);
@@ -202,3 +308,53 @@ gst_ffmpegdeinterlace_register (GstPlugi
   return gst_element_register (plugin, "ffdeinterlace",
       GST_RANK_NONE, GST_TYPE_FFMPEGDEINTERLACE);
 }
+
+static void
+gst_ffmpegdeinterlace_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstFFMpegDeinterlace *self;
+
+  g_return_if_fail (GST_IS_FFMPEGDEINTERLACE (object));
+  self = GST_FFMPEGDEINTERLACE (object);
+
+  switch (prop_id) {
+    case PROP_MODE:{
+      gint new_mode;
+
+      GST_OBJECT_LOCK (self);
+      new_mode = g_value_get_enum (value);
+      if (self->mode != new_mode && GST_PAD_CAPS (self->srcpad)) {
+        self->reconfigure = TRUE;
+        self->new_mode = new_mode;
+      } else {
+        self->mode = new_mode;
+        gst_ffmpegdeinterlace_update_passthrough (self);
+      }
+      GST_OBJECT_UNLOCK (self);
+      break;
+    }
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
+  }
+
+}
+
+static void
+gst_ffmpegdeinterlace_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstFFMpegDeinterlace *self;
+
+  g_return_if_fail (GST_IS_FFMPEGDEINTERLACE (object));
+  self = GST_FFMPEGDEINTERLACE (object);
+
+  switch (prop_id) {
+    case PROP_MODE:
+      g_value_set_enum (value, self->mode);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
+  }
+}
+


More information about the gstreamer-devel mailing list