From 4ec81ff7fa97e6747ecbb195d12596f58a241917 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Fri, 20 Jan 2006 14:17:16 +0000 Subject: [PATCH] ext/ffmpeg/: ffdeinterlace port to 0.10. Original commit message from CVS: reviewed by: Edward Hervey * ext/ffmpeg/Makefile.am: * ext/ffmpeg/gstffmpeg.c: (plugin_init): * ext/ffmpeg/gstffmpegdeinterlace.c: (gst_ffmpegdeinterlace_base_init), (gst_ffmpegdeinterlace_class_init), (gst_ffmpegdeinterlace_sink_setcaps), (gst_ffmpegdeinterlace_init), (gst_ffmpegdeinterlace_chain), (gst_ffmpegdeinterlace_register): ffdeinterlace port to 0.10. Could be made a subclass of GstBaseTransform later on... --- ChangeLog | 14 ++ ext/ffmpeg/Makefile.am | 6 +- ext/ffmpeg/gstffmpeg.c | 2 +- ext/ffmpeg/gstffmpegdeinterlace.c | 375 ++++++++---------------------- 4 files changed, 121 insertions(+), 276 deletions(-) diff --git a/ChangeLog b/ChangeLog index 21847a1e73..a9fd532534 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2006-01-20 Martin Zlomek from Itonis (michael.benes@xeris.cz) + + reviewed by: Edward Hervey + + * ext/ffmpeg/Makefile.am: + * ext/ffmpeg/gstffmpeg.c: (plugin_init): + * ext/ffmpeg/gstffmpegdeinterlace.c: + (gst_ffmpegdeinterlace_base_init), + (gst_ffmpegdeinterlace_class_init), + (gst_ffmpegdeinterlace_sink_setcaps), (gst_ffmpegdeinterlace_init), + (gst_ffmpegdeinterlace_chain), (gst_ffmpegdeinterlace_register): + ffdeinterlace port to 0.10. + Could be made a subclass of GstBaseTransform later on... + 2006-01-20 Michal Benes Reviewed by : Edward Hervey diff --git a/ext/ffmpeg/Makefile.am b/ext/ffmpeg/Makefile.am index 3490e352b0..a5b53aaa7d 100644 --- a/ext/ffmpeg/Makefile.am +++ b/ext/ffmpeg/Makefile.am @@ -3,12 +3,12 @@ plugin_LTLIBRARIES = libgstffmpeg.la libgstffmpeg_la_SOURCES = gstffmpeg.c \ gstffmpegcodecmap.c \ gstffmpegdec.c \ - gstffmpegenc.c + gstffmpegenc.c \ + gstffmpegdeinterlace.c # gstffmpegdemux.c \ # gstffmpegmux.c \ # gstffmpegprotocol.c \ -# gstffmpegscale.c \ -# gstffmpegdeinterlace.c +# gstffmpegscale.c libgstffmpeg_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ -I $(top_srcdir)/gst-libs/ext/ffmpeg/libavformat \ diff --git a/ext/ffmpeg/gstffmpeg.c b/ext/ffmpeg/gstffmpeg.c index bb2ec7c31e..66bfea8d1f 100644 --- a/ext/ffmpeg/gstffmpeg.c +++ b/ext/ffmpeg/gstffmpeg.c @@ -109,12 +109,12 @@ plugin_init (GstPlugin * plugin) gst_ffmpegenc_register (plugin); gst_ffmpegdec_register (plugin); + gst_ffmpegdeinterlace_register (plugin); #if 0 gst_ffmpegdemux_register (plugin); gst_ffmpegmux_register (plugin); gst_ffmpegcsp_register (plugin); gst_ffmpegscale_register (plugin); - gst_ffmpegdeinterlace_register (plugin); register_protocol (&gstreamer_protocol); #endif diff --git a/ext/ffmpeg/gstffmpegdeinterlace.c b/ext/ffmpeg/gstffmpegdeinterlace.c index ce90e5f770..b33a839604 100644 --- a/ext/ffmpeg/gstffmpegdeinterlace.c +++ b/ext/ffmpeg/gstffmpegdeinterlace.c @@ -2,6 +2,7 @@ * Copyright (C) <1999> Erik Walthinsen * This file: * Copyright (C) 2005 Luca Ognibene + * Copyright (C) 2006 Martin Zlomek * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -20,20 +21,39 @@ */ #ifdef HAVE_CONFIG_H -#include "config.h" +# include "config.h" +#endif + +#ifdef HAVE_FFMPEG_UNINSTALLED +# include +#else +# include #endif #include -#ifdef HAVE_FFMPEG_UNINSTALLED -#include -#else -#include -#endif - #include + #include "gstffmpeg.h" #include "gstffmpegcodecmap.h" +typedef struct _GstFFMpegDeinterlace +{ + GstElement element; + + GstPad *sinkpad, *srcpad; + + gint width, height; + gint to_size; + + enum PixelFormat pixfmt; + AVPicture from_frame, to_frame; +} GstFFMpegDeinterlace; + +typedef struct _GstFFMpegDeinterlaceClass +{ + GstElementClass parent_class; +} GstFFMpegDeinterlaceClass; + #define GST_TYPE_FFMPEGDEINTERLACE \ (gst_ffmpegdeinterlace_get_type()) #define GST_FFMPEGDEINTERLACE(obj) \ @@ -45,323 +65,134 @@ #define GST_IS_FFMPEGDEINTERLACE_CLASS(obj) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGDEINTERLACE)) -typedef struct _GstFFMpegDeinterlace GstFFMpegDeinterlace; -typedef struct _GstFFMpegDeinterlaceClass GstFFMpegDeinterlaceClass; - -struct _GstFFMpegDeinterlace -{ - GstElement element; - - GstPad *sinkpad, *srcpad; - - gint width, height; - - enum PixelFormat pixfmt; - AVPicture from_frame, to_frame; - GstCaps *sinkcaps; - - guint to_size; - -}; - -struct _GstFFMpegDeinterlaceClass -{ - GstElementClass parent_class; -}; - -/* elementfactory information */ -static GstElementDetails ffmpegdeinterlace_details = { - "FFMPEG Deinterlace element", - "Filter/Converter/Video", - "Deinterlace video", - "Luca Ognibene ", -}; - -/* Signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - ARG_0, -}; - -static GstStaticPadTemplate gst_ffmpegdeinterlace_src_template = -GST_STATIC_PAD_TEMPLATE ("src", +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")) ); -static GstStaticPadTemplate gst_ffmpegdeinterlace_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")) ); +GST_BOILERPLATE (GstFFMpegDeinterlace, gst_ffmpegdeinterlace, GstElement, + GST_TYPE_ELEMENT); -static GType gst_ffmpegdeinterlace_get_type (void); - -static void gst_ffmpegdeinterlace_base_init (GstFFMpegDeinterlaceClass * klass); -static void gst_ffmpegdeinterlace_class_init (GstFFMpegDeinterlaceClass * klass); -static void gst_ffmpegdeinterlace_init (GstFFMpegDeinterlace * space); - -static void gst_ffmpegdeinterlace_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_ffmpegdeinterlace_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); - -static GstPadLinkReturn -gst_ffmpegdeinterlace_pad_link (GstPad * pad, const GstCaps * caps); - -static void gst_ffmpegdeinterlace_chain (GstPad * pad, GstData * data); -static GstStateChangeReturn gst_ffmpegdeinterlace_change_state (GstElement * element, - GstStateChange transition); - -static GstElementClass *parent_class = NULL; - -/*static guint gst_ffmpegdeinterlace_signals[LAST_SIGNAL] = { 0 }; */ - -static GstCaps * -gst_ffmpegdeinterlace_getcaps (GstPad * pad) -{ - GstFFMpegDeinterlace *filter; - GstPad *otherpad; - - filter = GST_FFMPEGDEINTERLACE (gst_pad_get_parent (pad)); - - otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad; - - otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad; - - return gst_pad_get_allowed_caps (otherpad); -} - -static GstPadLinkReturn -gst_ffmpegdeinterlace_pad_link (GstPad * pad, const GstCaps * caps) -{ - GstStructure *structure; - AVCodecContext *ctx; - GstFFMpegDeinterlace *deinterlace; - GstPad *otherpad; - GstPadLinkReturn ret; - int height, width; - - deinterlace = GST_FFMPEGDEINTERLACE (gst_pad_get_parent (pad)); - - otherpad = (pad == deinterlace->srcpad) ? deinterlace->sinkpad : - deinterlace->srcpad; - - structure = gst_caps_get_structure (caps, 0); - ret = gst_structure_get_int (structure, "width", &width); - ret &= gst_structure_get_int (structure, "height", &height); - - ctx = avcodec_alloc_context (); - ctx->width = width; - ctx->height = height; - ctx->pix_fmt = PIX_FMT_NB; - gst_ffmpeg_caps_with_codectype (CODEC_TYPE_VIDEO, caps, ctx); - if (ctx->pix_fmt == PIX_FMT_NB) { - av_free (ctx); - - /* we disable ourself here */ - return GST_PAD_LINK_REFUSED; - } - - deinterlace->pixfmt = ctx->pix_fmt; - av_free (ctx); - - ret = gst_pad_try_set_caps (otherpad, caps); - if (GST_PAD_LINK_FAILED (ret)) { - return ret; - } - - deinterlace->width = width; - deinterlace->height = height; - deinterlace->to_size = avpicture_get_size (deinterlace->pixfmt, - deinterlace->width, deinterlace->height); - return GST_PAD_LINK_OK; -} - -static GType -gst_ffmpegdeinterlace_get_type (void) -{ - static GType ffmpegdeinterlace_type = 0; - - if (!ffmpegdeinterlace_type) { - static const GTypeInfo ffmpegdeinterlace_info = { - sizeof (GstFFMpegDeinterlaceClass), - (GBaseInitFunc) gst_ffmpegdeinterlace_base_init, - NULL, - (GClassInitFunc) gst_ffmpegdeinterlace_class_init, - NULL, - NULL, - sizeof (GstFFMpegDeinterlace), - 0, - (GInstanceInitFunc) gst_ffmpegdeinterlace_init, - }; - - ffmpegdeinterlace_type = g_type_register_static (GST_TYPE_ELEMENT, - "GstFFMpegDeinterlace", &ffmpegdeinterlace_info, 0); - } - - return ffmpegdeinterlace_type; -} +static GstFlowReturn gst_ffmpegdeinterlace_chain (GstPad * pad, + GstBuffer * inbuf); static void -gst_ffmpegdeinterlace_base_init (GstFFMpegDeinterlaceClass * klass) +gst_ffmpegdeinterlace_base_init (gpointer g_class) { - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_set_details (element_class, &ffmpegdeinterlace_details); + static GstElementDetails plugin_details = { + "FFMPEG Deinterlace element", + "Filter/Converter/Video", + "Deinterlace video", + "Luca Ognibene ", + }; + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_ffmpegdeinterlace_src_template)); + gst_static_pad_template_get (&src_factory)); gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_ffmpegdeinterlace_sink_template)); + gst_static_pad_template_get (&sink_factory)); + gst_element_class_set_details (element_class, &plugin_details); } static void gst_ffmpegdeinterlace_class_init (GstFFMpegDeinterlaceClass * klass) { - GObjectClass *gobject_class; - GstElementClass *gstelement_class; +} - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; +static gboolean +gst_ffmpegdeinterlace_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstFFMpegDeinterlace *deinterlace = + GST_FFMPEGDEINTERLACE (gst_pad_get_parent (pad)); + GstStructure *structure = gst_caps_get_structure (caps, 0); + AVCodecContext *ctx; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + if (!gst_structure_get_int (structure, "width", &deinterlace->width)) + return FALSE; + if (!gst_structure_get_int (structure, "height", &deinterlace->height)) + return FALSE; - gobject_class->set_property = gst_ffmpegdeinterlace_set_property; - gobject_class->get_property = gst_ffmpegdeinterlace_get_property; + ctx = avcodec_alloc_context (); + ctx->width = deinterlace->width; + ctx->height = deinterlace->height; + ctx->pix_fmt = PIX_FMT_NB; + gst_ffmpeg_caps_with_codectype (CODEC_TYPE_VIDEO, caps, ctx); + if (ctx->pix_fmt == PIX_FMT_NB) { + av_free (ctx); + return FALSE; + } - gstelement_class->change_state = gst_ffmpegdeinterlace_change_state; + deinterlace->pixfmt = ctx->pix_fmt; + + av_free (ctx); + + deinterlace->to_size = + avpicture_get_size (deinterlace->pixfmt, deinterlace->width, + deinterlace->height); + + return gst_pad_set_caps (deinterlace->srcpad, caps); } static void -gst_ffmpegdeinterlace_init (GstFFMpegDeinterlace * deinterlace) +gst_ffmpegdeinterlace_init (GstFFMpegDeinterlace * deinterlace, + GstFFMpegDeinterlaceClass * klass) { - deinterlace->sinkpad = gst_pad_new_from_template (gst_static_pad_template_get - (&gst_ffmpegdeinterlace_sink_template), - "sink"); - gst_pad_set_link_function (deinterlace->sinkpad, gst_ffmpegdeinterlace_pad_link); - gst_pad_set_getcaps_function (deinterlace->sinkpad, gst_ffmpegdeinterlace_getcaps); - gst_pad_set_chain_function (deinterlace->sinkpad, gst_ffmpegdeinterlace_chain); + deinterlace->sinkpad = + gst_pad_new_from_static_template (&sink_factory, "sink"); + gst_pad_set_setcaps_function (deinterlace->sinkpad, + gst_ffmpegdeinterlace_sink_setcaps); + gst_pad_set_chain_function (deinterlace->sinkpad, + gst_ffmpegdeinterlace_chain); gst_element_add_pad (GST_ELEMENT (deinterlace), deinterlace->sinkpad); - deinterlace->srcpad = gst_pad_new_from_template (gst_static_pad_template_get - (&gst_ffmpegdeinterlace_src_template), - "src"); + deinterlace->srcpad = gst_pad_new_from_static_template (&src_factory, "src"); gst_element_add_pad (GST_ELEMENT (deinterlace), deinterlace->srcpad); - gst_pad_set_link_function (deinterlace->srcpad, gst_ffmpegdeinterlace_pad_link); - gst_pad_set_getcaps_function (deinterlace->srcpad, gst_ffmpegdeinterlace_getcaps); deinterlace->pixfmt = PIX_FMT_NB; } -static void -gst_ffmpegdeinterlace_chain (GstPad * pad, GstData * data) +static GstFlowReturn +gst_ffmpegdeinterlace_chain (GstPad * pad, GstBuffer * inbuf) { - GstBuffer *inbuf = GST_BUFFER (data); - GstFFMpegDeinterlace *deinterlace; + GstFFMpegDeinterlace *deinterlace = + GST_FFMPEGDEINTERLACE (gst_pad_get_parent (pad)); GstBuffer *outbuf = NULL; + GstFlowReturn result; - g_return_if_fail (pad != NULL); - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (inbuf != NULL); + result = + gst_pad_alloc_buffer (deinterlace->srcpad, GST_BUFFER_OFFSET_NONE, + deinterlace->to_size, GST_PAD_CAPS (deinterlace->srcpad), &outbuf); + if (result == GST_FLOW_OK) { + gst_ffmpeg_avpicture_fill (&deinterlace->from_frame, + GST_BUFFER_DATA (inbuf), deinterlace->pixfmt, deinterlace->width, + deinterlace->height); - deinterlace = GST_FFMPEGDEINTERLACE (gst_pad_get_parent (pad)); + gst_ffmpeg_avpicture_fill (&deinterlace->to_frame, GST_BUFFER_DATA (outbuf), + deinterlace->pixfmt, deinterlace->width, deinterlace->height); - g_return_if_fail (deinterlace != NULL); - g_return_if_fail (GST_IS_FFMPEGDEINTERLACE (deinterlace)); + avpicture_deinterlace (&deinterlace->to_frame, &deinterlace->from_frame, + deinterlace->pixfmt, deinterlace->width, deinterlace->height); - if (!GST_PAD_IS_USABLE (deinterlace->srcpad)) { - gst_buffer_unref (inbuf); - return; + gst_buffer_stamp (outbuf, inbuf); + + result = gst_pad_push (deinterlace->srcpad, outbuf); } - outbuf = gst_pad_alloc_buffer_and_set_caps (deinterlace->srcpad, - GST_BUFFER_OFFSET_NONE, deinterlace->to_size); - - gst_ffmpeg_avpicture_fill (&deinterlace->from_frame, - GST_BUFFER_DATA (inbuf), - deinterlace->pixfmt, - deinterlace->width, deinterlace->height); - - gst_ffmpeg_avpicture_fill (&deinterlace->to_frame, - GST_BUFFER_DATA (outbuf), - deinterlace->pixfmt, - deinterlace->width, deinterlace->height); - - avpicture_deinterlace (&deinterlace->to_frame, &deinterlace->from_frame, - deinterlace->pixfmt, deinterlace->width, deinterlace->height); - - gst_buffer_stamp (outbuf, (const GstBuffer *) inbuf); - gst_buffer_unref (inbuf); - gst_pad_push (deinterlace->srcpad, GST_DATA (outbuf)); - -} -static GstStateChangeReturn -gst_ffmpegdeinterlace_change_state (GstElement * element, GstStateChange transition) -{ - GstFFMpegDeinterlace *deinterlace; - - deinterlace = GST_FFMPEGDEINTERLACE (element); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_NULL: - break; - } - - if (parent_class->change_state) - return parent_class->change_state (element, transition); - - return GST_STATE_CHANGE_SUCCESS; -} - -static void -gst_ffmpegdeinterlace_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec) -{ - GstFFMpegDeinterlace *deinterlace; - - /* it's not null if we got it, but it might not be ours */ - g_return_if_fail (GST_IS_FFMPEGDEINTERLACE (object)); - deinterlace = GST_FFMPEGDEINTERLACE (object); - - switch (prop_id) { - default: - break; - } -} - -static void -gst_ffmpegdeinterlace_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec) -{ - GstFFMpegDeinterlace *deinterlace; - - /* it's not null if we got it, but it might not be ours */ - g_return_if_fail (GST_IS_FFMPEGDEINTERLACE (object)); - deinterlace = GST_FFMPEGDEINTERLACE (object); - - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + return result; } gboolean gst_ffmpegdeinterlace_register (GstPlugin * plugin) { - return gst_element_register (plugin, "ffdeinterlace", GST_RANK_NONE, GST_TYPE_FFMPEGDEINTERLACE); }