RELEASE: GStreamer FFmpeg Plug-ins 0.10.12 "A year in hell"
Edward Hervey
bilboed at gmail.com
Thu Aug 11 02:30:57 PDT 2011
Hi,
On Thu, 2011-08-11 at 10:02 +0100, Tvrtko Ursulin wrote:
> On Wednesday 20 Jul 2011 12:02:00 Edward Hervey wrote:
[...]
> I see that multi-threaded decoding is disabled by default in gstffmpegdec. Is this
> because of known issues and how serious are they?
The support for it was only dropped a month before release. The reason
why I set the default back to only using one thread was:
* Lots of warnings from the libav side on some formats
* Reports of segfaulting in some situations
* Critical basic MT-safety patches landing the day I was going to do
the release.
That being said, the multi-threading support in gst-ffmpeg hasn't been
removed/disabled. It's just that I've re-setted the default number of
threads to 1 (instead of 0 which is automatic numbers).
So you can still force the number of threads you want manually.
Hopefully everything will be more stable soon and we'll be able to do
a new gst-ffmpeg release with the default multi-threading enabled within
a couple of months.
>
> 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. :)
>
Put that patch in a new bug report on bugzilla.gnome.org . It'll be
handled there like all patches. I have no objections per-se.
Edward
> 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