diff options
author | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2012-01-25 13:22:43 +0100 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2012-01-25 13:22:43 +0100 |
commit | a2a430024136fd947637ff56a4fea6a2689ca59d (patch) | |
tree | 8cab3177242814f02b1e49a51d81b5f2f1660621 /ext | |
parent | 071c6e8f15f2afff7ca4ce5934c3bae1d76aea95 (diff) | |
parent | 8fb0beaf00aeae2ef6081d08f0d74d6e655a53da (diff) |
Merge branch 'master' into 0.11
Conflicts:
configure.ac
ext/kate/gstkateenc.c
gst/colorspace/colorspace.c
gst/mpegvideoparse/mpegvideoparse.c
Diffstat (limited to 'ext')
-rw-r--r-- | ext/Makefile.am | 8 | ||||
-rw-r--r-- | ext/chromaprint/Makefile.am | 14 | ||||
-rw-r--r-- | ext/chromaprint/gstchromaprint.c | 317 | ||||
-rw-r--r-- | ext/chromaprint/gstchromaprint.h | 77 | ||||
-rw-r--r-- | ext/cog/gstcogmse.c | 8 | ||||
-rw-r--r-- | ext/gme/gstgme.c | 2 | ||||
-rw-r--r-- | ext/gsm/gstgsmdec.c | 257 | ||||
-rw-r--r-- | ext/gsm/gstgsmdec.h | 20 | ||||
-rw-r--r-- | ext/gsm/gstgsmenc.c | 147 | ||||
-rw-r--r-- | ext/gsm/gstgsmenc.h | 12 | ||||
-rw-r--r-- | ext/kate/gstkateenc.c | 41 | ||||
-rw-r--r-- | ext/opencv/gsttemplatematch.c | 2 | ||||
-rw-r--r-- | ext/resindvd/resindvdbin.c | 23 | ||||
-rw-r--r-- | ext/resindvd/resindvdsrc.c | 1 | ||||
-rw-r--r-- | ext/resindvd/rsnaudiomunge.c | 2 | ||||
-rw-r--r-- | ext/resindvd/rsndec.c | 34 | ||||
-rw-r--r-- | ext/rsvg/gstrsvgoverlay.c | 13 | ||||
-rw-r--r-- | ext/schroedinger/gstschrodec.c | 27 | ||||
-rw-r--r-- | ext/schroedinger/gstschroenc.c | 27 | ||||
-rw-r--r-- | ext/schroedinger/gstschroutils.c | 23 | ||||
-rw-r--r-- | ext/schroedinger/gstschroutils.h | 6 | ||||
-rw-r--r-- | ext/spc/gstspc.c | 2 | ||||
-rw-r--r-- | ext/vp8/gstvp8enc.c | 3 |
23 files changed, 730 insertions, 336 deletions
diff --git a/ext/Makefile.am b/ext/Makefile.am index dc62386ca..a1636f690 100644 --- a/ext/Makefile.am +++ b/ext/Makefile.am @@ -58,6 +58,12 @@ else CELT_DIR= endif +if USE_CHROMAPRINT +CHROMAPRINT_DIR=chromaprint +else +CHROMAPRINT_DIR= +endif + if USE_COG COG_DIR=cog else @@ -397,6 +403,7 @@ SUBDIRS=\ $(BZ2_DIR) \ $(CDAUDIO_DIR) \ $(CELT_DIR) \ + $(CHROMAPRINT_DIR) \ $(COG_DIR) \ $(CURL_DIR) \ $(DC1394_DIR) \ @@ -456,6 +463,7 @@ DIST_SUBDIRS = \ bz2 \ cdaudio \ celt \ + chromaprint \ cog \ curl \ dc1394 \ diff --git a/ext/chromaprint/Makefile.am b/ext/chromaprint/Makefile.am new file mode 100644 index 000000000..115d8c298 --- /dev/null +++ b/ext/chromaprint/Makefile.am @@ -0,0 +1,14 @@ +plugin_LTLIBRARIES = libgstchromaprint.la + +libgstchromaprint_la_SOURCES = gstchromaprint.c gstchromaprint.h + +libgstchromaprint_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \ + $(CHROMAPRINT_CFLAGS) +libgstchromaprint_la_LIBADD = \ + $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(GST_LIBS) \ + $(CHROMAPRINT_LIBS) +libgstchromaprint_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstchromaprint_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = gstchromaprint.h diff --git a/ext/chromaprint/gstchromaprint.c b/ext/chromaprint/gstchromaprint.c new file mode 100644 index 000000000..c0a129301 --- /dev/null +++ b/ext/chromaprint/gstchromaprint.c @@ -0,0 +1,317 @@ +/* GStreamer chromaprint audio fingerprinting element + * Copyright (C) 2006 M. Derezynski + * Copyright (C) 2008 Eric Buehl + * Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.org> + * Copyright (C) 2011 Lukáš Lalinský <lalinsky@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-chromaprint + * + * The chromaprint element calculates an acoustic fingerprint for an + * audio stream which can be used to identify a song and look up + * further metadata from the <ulink url="http://acoustid.org/">Acoustid</ulink> + * and Musicbrainz databases. + * + * <refsect2> + * <title>Example launch line</title> + * |[ + * gst-launch -m uridecodebin uri=file:///path/to/song.ogg ! audioconvert ! chromaprint ! fakesink + * ]| + * </refsect2> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "gstchromaprint.h" + +#define DEFAULT_MAX_DURATION 120 + +#define PAD_CAPS \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, 2 ], " \ + "endianness = (int) { BYTE_ORDER }, " \ + "width = (int) { 16 }, " \ + "depth = (int) { 16 }, " \ + "signed = (boolean) true" + +GST_DEBUG_CATEGORY_STATIC (gst_chromaprint_debug); +#define GST_CAT_DEFAULT gst_chromaprint_debug + +enum +{ + PROP_0, + PROP_FINGERPRINT, + PROP_MAX_DURATION +}; + + +GST_BOILERPLATE (GstChromaprint, gst_chromaprint, GstElement, + GST_TYPE_AUDIO_FILTER); + +static void gst_chromaprint_finalize (GObject * object); +static void gst_chromaprint_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_chromaprint_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static GstFlowReturn gst_chromaprint_transform_ip (GstBaseTransform * trans, + GstBuffer * buf); +static gboolean gst_chromaprint_event (GstBaseTransform * trans, + GstEvent * event); + +static void +gst_chromaprint_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + GstAudioFilterClass *audio_filter_class = (GstAudioFilterClass *) g_class; + GstCaps *caps; + + gst_element_class_set_details_simple (element_class, + "Chromaprint fingerprinting element", + "Filter/Analyzer/Audio", + "Find an audio fingerprint using the Chromaprint library", + "Lukáš Lalinský <lalinsky@gmail.com>"); + + caps = gst_caps_from_string (PAD_CAPS); + gst_audio_filter_class_add_pad_templates (audio_filter_class, caps); + gst_caps_unref (caps); +} + +static void +gst_chromaprint_class_init (GstChromaprintClass * klass) +{ + GObjectClass *gobject_class; + GstBaseTransformClass *gstbasetrans_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass); + + gobject_class->set_property = gst_chromaprint_set_property; + gobject_class->get_property = gst_chromaprint_get_property; + + /* FIXME: do we need this in addition to the tag message ? */ + g_object_class_install_property (gobject_class, PROP_FINGERPRINT, + g_param_spec_string ("fingerprint", "Resulting fingerprint", + "Resulting fingerprint", NULL, G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, PROP_MAX_DURATION, + g_param_spec_uint ("duration", "Duration limit", + "Number of seconds of audio to use for fingerprinting", + 0, G_MAXUINT, DEFAULT_MAX_DURATION, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_chromaprint_finalize); + + gstbasetrans_class->transform_ip = + GST_DEBUG_FUNCPTR (gst_chromaprint_transform_ip); + gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_chromaprint_event); + gstbasetrans_class->passthrough_on_same_caps = TRUE; +} + +static void +gst_chromaprint_reset (GstChromaprint * chromaprint) +{ + if (chromaprint->fingerprint) { + chromaprint_dealloc (chromaprint->fingerprint); + chromaprint->fingerprint = NULL; + } + + chromaprint->nsamples = 0; + chromaprint->duration = 0; + chromaprint->record = TRUE; +} + +static void +gst_chromaprint_create_fingerprint (GstChromaprint * chromaprint) +{ + GstTagList *tags; + + if (chromaprint->duration <= 3) + return; + + GST_DEBUG_OBJECT (chromaprint, + "Generating fingerprint based on %d seconds of audio", + chromaprint->duration); + + chromaprint_finish (chromaprint->context); + chromaprint_get_fingerprint (chromaprint->context, &chromaprint->fingerprint); + chromaprint->record = FALSE; + + tags = gst_tag_list_new_full (GST_TAG_CHROMAPRINT_FINGERPRINT, + chromaprint->fingerprint, NULL); + + gst_element_found_tags (GST_ELEMENT (chromaprint), tags); +} + +static void +gst_chromaprint_init (GstChromaprint * chromaprint, + GstChromaprintClass * gclass) +{ + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (chromaprint), TRUE); + + chromaprint->context = chromaprint_new (CHROMAPRINT_ALGORITHM_DEFAULT); + chromaprint->fingerprint = NULL; + chromaprint->max_duration = DEFAULT_MAX_DURATION; + gst_chromaprint_reset (chromaprint); +} + +static void +gst_chromaprint_finalize (GObject * object) +{ + GstChromaprint *chromaprint = GST_CHROMAPRINT (object); + + chromaprint->record = FALSE; + + if (chromaprint->context) { + chromaprint_free (chromaprint->context); + chromaprint->context = NULL; + } + + if (chromaprint->fingerprint) { + chromaprint_dealloc (chromaprint->fingerprint); + chromaprint->fingerprint = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static GstFlowReturn +gst_chromaprint_transform_ip (GstBaseTransform * trans, GstBuffer * buf) +{ + GstChromaprint *chromaprint = GST_CHROMAPRINT (trans); + gint rate = GST_AUDIO_FILTER (chromaprint)->format.rate; + gint channels = GST_AUDIO_FILTER (chromaprint)->format.channels; + guint nsamples; + + if (G_UNLIKELY (rate <= 0 || channels <= 0)) + return GST_FLOW_NOT_NEGOTIATED; + + if (!chromaprint->record) + return GST_FLOW_OK; + + nsamples = GST_BUFFER_SIZE (buf) / (channels * 2); + + if (nsamples == 0) + return GST_FLOW_OK; + + if (chromaprint->nsamples == 0) { + chromaprint_start (chromaprint->context, rate, channels); + } + chromaprint->nsamples += nsamples; + chromaprint->duration = chromaprint->nsamples / rate; + + chromaprint_feed (chromaprint->context, GST_BUFFER_DATA (buf), + GST_BUFFER_SIZE (buf) / 2); + + if (chromaprint->duration >= chromaprint->max_duration + && !chromaprint->fingerprint) { + gst_chromaprint_create_fingerprint (chromaprint); + } + + return GST_FLOW_OK; +} + +static gboolean +gst_chromaprint_event (GstBaseTransform * trans, GstEvent * event) +{ + GstChromaprint *chromaprint = GST_CHROMAPRINT (trans); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + case GST_EVENT_NEWSEGMENT: + GST_DEBUG_OBJECT (trans, "Got %s event, clearing buffer", + GST_EVENT_TYPE_NAME (event)); + gst_chromaprint_reset (chromaprint); + break; + case GST_EVENT_EOS: + if (!chromaprint->fingerprint) { + gst_chromaprint_create_fingerprint (chromaprint); + } + break; + default: + break; + } + + return TRUE; +} + +static void +gst_chromaprint_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstChromaprint *chromaprint = GST_CHROMAPRINT (object); + + switch (prop_id) { + case PROP_MAX_DURATION: + chromaprint->max_duration = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_chromaprint_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstChromaprint *chromaprint = GST_CHROMAPRINT (object); + + switch (prop_id) { + case PROP_FINGERPRINT: + g_value_set_string (value, chromaprint->fingerprint); + break; + case PROP_MAX_DURATION: + g_value_set_uint (value, chromaprint->max_duration); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gboolean ret; + + GST_DEBUG_CATEGORY_INIT (gst_chromaprint_debug, "chromaprint", + 0, "chromaprint element"); + + GST_INFO ("libchromaprint %s", chromaprint_get_version ()); + + ret = gst_element_register (plugin, "chromaprint", GST_RANK_NONE, + GST_TYPE_CHROMAPRINT); + + if (ret) { + gst_tag_register (GST_TAG_CHROMAPRINT_FINGERPRINT, GST_TAG_FLAG_META, + G_TYPE_STRING, "chromaprint fingerprint", "Chromaprint fingerprint", + NULL); + } + + return ret; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "chromaprint", + "Calculate Chromaprint fingerprint from audio files", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/chromaprint/gstchromaprint.h b/ext/chromaprint/gstchromaprint.h new file mode 100644 index 000000000..12bad8a13 --- /dev/null +++ b/ext/chromaprint/gstchromaprint.h @@ -0,0 +1,77 @@ +/* GStreamer chromaprint audio fingerprinting element + * Copyright (C) 2006 M. Derezynski + * Copyright (C) 2008 Eric Buehl + * Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.org> + * Copyright (C) 2011 Lukáš Lalinský <<user@hostname.org>> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_CHROMAPRINT_H__ +#define __GST_CHROMAPRINT_H__ + +#include <gst/gst.h> +#include <gst/base/gstadapter.h> +#include <gst/audio/gstaudiofilter.h> +#include <gst/audio/audio.h> +#include <chromaprint.h> + +G_BEGIN_DECLS + +#define GST_TYPE_CHROMAPRINT \ + (gst_chromaprint_get_type()) +#define GST_CHROMAPRINT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CHROMAPRINT,GstChromaprint)) +#define GST_CHROMAPRINT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CHROMAPRINT,GstChromaprintClass)) +#define GST_IS_CHROMAPRINT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CHROMAPRINT)) +#define GST_IS_CHROMAPRINT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CHROMAPRINT)) + +#define GST_TAG_CHROMAPRINT_FINGERPRINT "chromaprint-fingerprint" + +typedef struct _GstChromaprint GstChromaprint; +typedef struct _GstChromaprintClass GstChromaprintClass; + +/** + * GstChromaprint: + * + * Opaque #GstChromaprint element structure + */ +struct _GstChromaprint +{ + GstAudioFilter element; + + /*< private >*/ + ChromaprintContext * context; + char * fingerprint; + gboolean record; + guint64 nsamples; + guint duration; + guint max_duration; +}; + +struct _GstChromaprintClass +{ + GstAudioFilterClass parent_class; +}; + +GType gst_chromaprint_get_type (void); + +G_END_DECLS + +#endif /* __GST_CHROMAPRINT_H__ */ diff --git a/ext/cog/gstcogmse.c b/ext/cog/gstcogmse.c index 3ce16a37b..ad38d8dfb 100644 --- a/ext/cog/gstcogmse.c +++ b/ext/cog/gstcogmse.c @@ -208,6 +208,9 @@ gst_mse_finalize (GObject * object) gst_object_unref (fs->sinkpad_test); g_mutex_free (fs->lock); g_cond_free (fs->cond); + gst_buffer_replace (&fs->buffer_ref, NULL); + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); } static GstCaps * @@ -243,7 +246,7 @@ gst_mse_getcaps (GstPad * pad) } if (pad != fs->sinkpad_test) { - peercaps = gst_pad_peer_get_caps (fs->sinkpad_ref); + peercaps = gst_pad_peer_get_caps (fs->sinkpad_test); if (peercaps) { icaps = gst_caps_intersect (caps, peercaps); gst_caps_unref (caps); @@ -310,6 +313,7 @@ gst_mse_reset (GstMSE * fs) fs->luma_mse_sum = 0; fs->chroma_mse_sum = 0; fs->n_frames = 0; + fs->cancel = FALSE; if (fs->buffer_ref) { gst_buffer_unref (fs->buffer_ref); @@ -435,9 +439,11 @@ gst_mse_sink_event (GstPad * pad, GstEvent * event) break; case GST_EVENT_FLUSH_START: GST_DEBUG ("flush start"); + fs->cancel = TRUE; break; case GST_EVENT_FLUSH_STOP: GST_DEBUG ("flush stop"); + fs->cancel = FALSE; break; default: break; diff --git a/ext/gme/gstgme.c b/ext/gme/gstgme.c index 7a70c7a3c..75d9ff423 100644 --- a/ext/gme/gstgme.c +++ b/ext/gme/gstgme.c @@ -161,6 +161,8 @@ gst_gme_dec_dispose (GObject * object) g_object_unref (gme->adapter); gme->adapter = NULL; } + + GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); } static GstFlowReturn diff --git a/ext/gsm/gstgsmdec.c b/ext/gsm/gstgsmdec.c index 3318bdc77..2bf475f26 100644 --- a/ext/gsm/gstgsmdec.c +++ b/ext/gsm/gstgsmdec.c @@ -43,43 +43,16 @@ enum ARG_0 }; -static void gst_gsmdec_base_init (gpointer g_class); -static void gst_gsmdec_class_init (GstGSMDec * klass); -static void gst_gsmdec_init (GstGSMDec * gsmdec); -static void gst_gsmdec_finalize (GObject * object); - -static gboolean gst_gsmdec_sink_setcaps (GstPad * pad, GstCaps * caps); -static gboolean gst_gsmdec_sink_event (GstPad * pad, GstEvent * event); -static GstFlowReturn gst_gsmdec_chain (GstPad * pad, GstBuffer * buf); - -static GstElementClass *parent_class = NULL; +static gboolean gst_gsmdec_start (GstAudioDecoder * dec); +static gboolean gst_gsmdec_stop (GstAudioDecoder * dec); +static gboolean gst_gsmdec_set_format (GstAudioDecoder * dec, GstCaps * caps); +static GstFlowReturn gst_gsmdec_parse (GstAudioDecoder * dec, + GstAdapter * adapter, gint * offset, gint * length); +static GstFlowReturn gst_gsmdec_handle_frame (GstAudioDecoder * dec, + GstBuffer * in_buf); /*static guint gst_gsmdec_signals[LAST_SIGNAL] = { 0 }; */ -GType -gst_gsmdec_get_type (void) -{ - static GType gsmdec_type = 0; - - if (!gsmdec_type) { - static const GTypeInfo gsmdec_info = { - sizeof (GstGSMDecClass), - gst_gsmdec_base_init, - NULL, - (GClassInitFunc) gst_gsmdec_class_init, - NULL, - NULL, - sizeof (GstGSMDec), - 0, - (GInstanceInitFunc) gst_gsmdec_init, - }; - - gsmdec_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstGSMDec", &gsmdec_info, 0); - } - return gsmdec_type; -} - #define ENCODED_SAMPLES 160 static GstStaticPadTemplate gsmdec_sink_template = @@ -101,6 +74,9 @@ GST_STATIC_PAD_TEMPLATE ("src", "depth = (int) 16, " "rate = (int) [1, MAX], " "channels = (int) 1") ); +GST_BOILERPLATE (GstGSMDec, gst_gsmdec, GstAudioDecoder, + GST_TYPE_AUDIO_DECODER); + static void gst_gsmdec_base_init (gpointer g_class) { @@ -116,63 +92,60 @@ gst_gsmdec_base_init (gpointer g_class) } static void -gst_gsmdec_class_init (GstGSMDec * klass) +gst_gsmdec_class_init (GstGSMDecClass * klass) { - GObjectClass *gobject_class; + GstAudioDecoderClass *base_class; - gobject_class = (GObjectClass *) klass; + base_class = (GstAudioDecoderClass *) klass; - parent_class = g_type_class_peek_parent (klass); - - gobject_class->finalize = gst_gsmdec_finalize; + base_class->start = GST_DEBUG_FUNCPTR (gst_gsmdec_start); + base_class->stop = GST_DEBUG_FUNCPTR (gst_gsmdec_stop); + base_class->set_format = GST_DEBUG_FUNCPTR (gst_gsmdec_set_format); + base_class->parse = GST_DEBUG_FUNCPTR (gst_gsmdec_parse); + base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_gsmdec_handle_frame); GST_DEBUG_CATEGORY_INIT (gsmdec_debug, "gsmdec", 0, "GSM Decoder"); } static void -gst_gsmdec_init (GstGSMDec * gsmdec) +gst_gsmdec_init (GstGSMDec * gsmdec, GstGSMDecClass * klass) { - /* create the sink and src pads */ - gsmdec->sinkpad = - gst_pad_new_from_static_template (&gsmdec_sink_template, "sink"); - gst_pad_set_setcaps_function (gsmdec->sinkpad, gst_gsmdec_sink_setcaps); - gst_pad_set_event_function (gsmdec->sinkpad, gst_gsmdec_sink_event); - gst_pad_set_chain_function (gsmdec->sinkpad, gst_gsmdec_chain); - gst_element_add_pad (GST_ELEMENT (gsmdec), gsmdec->sinkpad); - - gsmdec->srcpad = - gst_pad_new_from_static_template (&gsmdec_src_template, "src"); - gst_element_add_pad (GST_ELEMENT (gsmdec), gsmdec->srcpad); +} + +static gboolean +gst_gsmdec_start (GstAudioDecoder * dec) +{ + GstGSMDec *gsmdec = GST_GSMDEC (dec); + + GST_DEBUG_OBJECT (dec, "start"); gsmdec->state = gsm_create (); - gsmdec->adapter = gst_adapter_new (); - gsmdec->next_of = 0; - gsmdec->next_ts = 0; + return TRUE; } -static void -gst_gsmdec_finalize (GObject * object) +static gboolean +gst_gsmdec_stop (GstAudioDecoder * dec) { - GstGSMDec *gsmdec; + GstGSMDec *gsmdec = GST_GSMDEC (dec); - gsmdec = GST_GSMDEC (object); + GST_DEBUG_OBJECT (dec, "stop"); - g_object_unref (gsmdec->adapter); gsm_destroy (gsmdec->state); - G_OBJECT_CLASS (parent_class)->finalize (object); + return TRUE; } static gboolean -gst_gsmdec_sink_setcaps (GstPad * pad, GstCaps * caps) +gst_gsmdec_set_format (GstAudioDecoder * dec, GstCaps * caps) { GstGSMDec *gsmdec; GstCaps *srccaps; GstStructure *s; gboolean ret = FALSE; + gint rate; - gsmdec = GST_GSMDEC (gst_pad_get_parent (pad)); + gsmdec = GST_GSMDEC (dec); s = gst_caps_get_structure (caps, 0); if (s == NULL) @@ -186,7 +159,9 @@ gst_gsmdec_sink_setcaps (GstPad * pad, GstCaps * caps) else goto wrong_caps; - if (!gst_structure_get_int (s, "rate", &gsmdec->rate)) { + gsmdec->needed = 33; + + if (!gst_structure_get_int (s, "rate", &rate)) { GST_WARNING_OBJECT (gsmdec, "missing sample rate parameter from sink caps"); goto beach; } @@ -194,21 +169,16 @@ gst_gsmdec_sink_setcaps (GstPad * pad, GstCaps * caps) /* MSGSM needs different framing */ gsm_option (gsmdec->state, GSM_OPT_WAV49, &gsmdec->use_wav49); - gsmdec->duration = gst_util_uint64_scale (ENCODED_SAMPLES, - GST_SECOND, gsmdec->rate); - /* Setting up src caps based on the input sample rate. */ srccaps = gst_caps_new_simple ("audio/x-raw-int", "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, - "rate", G_TYPE_INT, gsmdec->rate, "channels", G_TYPE_INT, 1, NULL); - - ret = gst_pad_set_caps (gsmdec->srcpad, srccaps); + "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, 1, NULL); + ret = gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec), srccaps); gst_caps_unref (srccaps); - gst_object_unref (gsmdec); return ret; @@ -218,127 +188,66 @@ wrong_caps: GST_ERROR_OBJECT (gsmdec, "invalid caps received"); beach: - gst_object_unref (gsmdec); return ret; } -static gboolean -gst_gsmdec_sink_event (GstPad * pad, GstEvent * event) +static GstFlowReturn +gst_gsmdec_parse (GstAudioDecoder * dec, GstAdapter * adapter, + gint * offset, gint * length) { - gboolean res; - GstGSMDec *gsmdec; + GstGSMDec *gsmdec = GST_GSMDEC (dec); + guint size; + + size = gst_adapter_available (adapter); + g_return_val_if_fail (size > 0, GST_FLOW_ERROR); - gsmdec = GST_GSMDEC (gst_pad_get_parent (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_START: - res = gst_pad_push_event (gsmdec->srcpad, event); - break; - case GST_EVENT_FLUSH_STOP: - gst_segment_init (&gsmdec->segment, GST_FORMAT_UNDEFINED); - res = gst_pad_push_event (gsmdec->srcpad, event); - break; - case GST_EVENT_NEWSEGMENT: - { - gboolean update; - GstFormat format; - gdouble rate, arate; - gint64 start, stop, time; - - gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, - &start, &stop, &time); - - /* now configure the values */ - gst_segment_set_newsegment_full (&gsmdec->segment, update, - rate, arate, format, start, stop, time); - - /* and forward */ - res = gst_pad_push_event (gsmdec->srcpad, event); - break; - } - case GST_EVENT_EOS: - default: - res = gst_pad_push_event (gsmdec->srcpad, event); - break; + /* WAV49 requires alternating 33 and 32 bytes of input */ + if (gsmdec->use_wav49) { + gsmdec->needed = (gsmdec->needed == 33 ? 32 : 33); } - gst_object_unref (gsmdec); + if (size < gsmdec->needed) + return GST_FLOW_UNEXPECTED; - return res; + *offset = 0; + *length = gsmdec->needed; + + return GST_FLOW_OK; } static GstFlowReturn -gst_gsmdec_chain (GstPad * pad, GstBuffer * buf) +gst_gsmdec_handle_frame (GstAudioDecoder * dec, GstBuffer * buffer) { GstGSMDec *gsmdec; gsm_byte *data; GstFlowReturn ret = GST_FLOW_OK; - GstClockTime timestamp; - gint needed; - - gsmdec = GST_GSMDEC (gst_pad_get_parent (pad)); - - timestamp = GST_BUFFER_TIMESTAMP (buf); - - if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) { - gst_adapter_clear (gsmdec->adapter); - gsmdec->next_ts = GST_CLOCK_TIME_NONE; - /* FIXME, do some good offset */ - gsmdec->next_of = 0; - } - gst_adapter_push (gsmdec->adapter, buf); - - needed = 33; - /* do we have enough bytes to read a frame */ - while (gst_adapter_available (gsmdec->adapter) >= needed) { - GstBuffer *outbuf; - - /* always the same amount of output samples */ - outbuf = gst_buffer_new_and_alloc (ENCODED_SAMPLES * sizeof (gsm_signal)); - - /* If we are not given any timestamp, interpolate from last seen - * timestamp (if any). */ - if (timestamp == GST_CLOCK_TIME_NONE) - timestamp = gsmdec->next_ts; - - GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - - /* interpolate in the next run */ - if (timestamp != GST_CLOCK_TIME_NONE) - gsmdec->next_ts = timestamp + gsmdec->duration; - timestamp = GST_CLOCK_TIME_NONE; - - GST_BUFFER_DURATION (outbuf) = gsmdec->duration; - GST_BUFFER_OFFSET (outbuf) = gsmdec->next_of; - if (gsmdec->next_of != -1) - gsmdec->next_of += ENCODED_SAMPLES; - GST_BUFFER_OFFSET_END (outbuf) = gsmdec->next_of; - - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (gsmdec->srcpad)); - - /* now encode frame into the output buffer */ - data = (gsm_byte *) gst_adapter_peek (gsmdec->adapter, needed); - if (gsm_decode (gsmdec->state, data, - (gsm_signal *) GST_BUFFER_DATA (outbuf)) < 0) { - /* invalid frame */ - GST_WARNING_OBJECT (gsmdec, "tried to decode an invalid frame, skipping"); - } - gst_adapter_flush (gsmdec->adapter, needed); - - /* WAV49 requires alternating 33 and 32 bytes of input */ - if (gsmdec->use_wav49) - needed = (needed == 33 ? 32 : 33); - - GST_DEBUG_OBJECT (gsmdec, "Pushing buffer of size %d ts %" GST_TIME_FORMAT, - GST_BUFFER_SIZE (outbuf), - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf))); - - /* push */ - ret = gst_pad_push (gsmdec->srcpad, outbuf); + GstBuffer *outbuf; + + /* no fancy draining */ + if (G_UNLIKELY (!buffer)) + return GST_FLOW_OK; + + gsmdec = GST_GSMDEC (dec); + + /* always the same amount of output samples */ + outbuf = gst_buffer_new_and_alloc (ENCODED_SAMPLES * sizeof (gsm_signal)); + + /* now encode frame into the output buffer */ + data = (gsm_byte *) GST_BUFFER_DATA (buffer); + if (gsm_decode (gsmdec->state, data, + (gsm_signal *) GST_BUFFER_DATA (outbuf)) < 0) { + /* invalid frame */ + GST_AUDIO_DECODER_ERROR (gsmdec, 1, STREAM, DECODE, (NULL), + ("tried to decode an invalid frame"), ret); + if (ret != GST_FLOW_OK) + goto exit; + gst_buffer_unref (outbuf); + outbuf = NULL; } - gst_object_unref (gsmdec); + gst_audio_decoder_finish_frame (dec, outbuf, 1); +exit: return ret; } diff --git a/ext/gsm/gstgsmdec.h b/ext/gsm/gstgsmdec.h index 0013aa47e..d3ddec604 100644 --- a/ext/gsm/gstgsmdec.h +++ b/ext/gsm/gstgsmdec.h @@ -21,7 +21,7 @@ #define __GST_GSMDEC_H__ #include <gst/gst.h> -#include <gst/base/gstadapter.h> +#include <gst/audio/gstaudiodecoder.h> #ifdef GSM_HEADER_IN_SUBDIR #include <gsm/gsm.h> @@ -47,28 +47,16 @@ typedef struct _GstGSMDecClass GstGSMDecClass; struct _GstGSMDec { - GstElement element; - - /* pads */ - GstPad *sinkpad, *srcpad; + GstAudioDecoder element; gsm state; gint use_wav49; - gint64 next_of; - GstClockTime next_ts; - - GstAdapter *adapter; - - GstSegment segment; - - gint rate; - - GstClockTime duration; + gint needed; }; struct _GstGSMDecClass { - GstElementClass parent_class; + GstAudioDecoderClass parent_class; }; GType gst_gsmdec_get_type (void); diff --git a/ext/gsm/gstgsmenc.c b/ext/gsm/gstgsmenc.c index 434c4b1fa..e8c97c1f0 100644 --- a/ext/gsm/gstgsmenc.c +++ b/ext/gsm/gstgsmenc.c @@ -43,39 +43,12 @@ enum ARG_0 }; -static void gst_gsmenc_base_init (gpointer g_class); -static void gst_gsmenc_class_init (GstGSMEnc * klass); -static void gst_gsmenc_init (GstGSMEnc * gsmenc); -static void gst_gsmenc_finalize (GObject * object); - -static gboolean gst_gsmenc_setcaps (GstPad * pad, GstCaps * caps); -static GstFlowReturn gst_gsmenc_chain (GstPad * pad, GstBuffer * buf); - -static GstElementClass *parent_class = NULL; - -GType -gst_gsmenc_get_type (void) -{ - static GType gsmenc_type = 0; - - if (!gsmenc_type) { - static const GTypeInfo gsmenc_info = { - sizeof (GstGSMEncClass), - gst_gsmenc_base_init, - NULL, - (GClassInitFunc) gst_gsmenc_class_init, - NULL, - NULL, - sizeof (GstGSMEnc), - 0, - (GInstanceInitFunc) gst_gsmenc_init, - }; - - gsmenc_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstGSMEnc", &gsmenc_info, 0); - } - return gsmenc_type; -} +static gboolean gst_gsmenc_start (GstAudioEncoder * enc); +static gboolean gst_gsmenc_stop (GstAudioEncoder * enc); +static gboolean gst_gsmenc_set_format (GstAudioEncoder * enc, + GstAudioInfo * info); +static GstFlowReturn gst_gsmenc_handle_frame (GstAudioEncoder * enc, + GstBuffer * in_buf); static GstStaticPadTemplate gsmenc_src_template = GST_STATIC_PAD_TEMPLATE ("src", @@ -95,6 +68,9 @@ GST_STATIC_PAD_TEMPLATE ("sink", "depth = (int) 16, " "rate = (int) 8000, " "channels = (int) 1") ); +GST_BOILERPLATE (GstGSMEnc, gst_gsmenc, GstAudioEncoder, + GST_TYPE_AUDIO_ENCODER); + static void gst_gsmenc_base_init (gpointer g_class) { @@ -110,34 +86,32 @@ gst_gsmenc_base_init (gpointer g_class) } static void -gst_gsmenc_class_init (GstGSMEnc * klass) +gst_gsmenc_class_init (GstGSMEncClass * klass) { - GObjectClass *gobject_class; + GstAudioEncoderClass *base_class; - gobject_class = (GObjectClass *) klass; + base_class = (GstAudioEncoderClass *) klass; - parent_class = g_type_class_peek_parent (klass); - - gobject_class->finalize = gst_gsmenc_finalize; + base_class->start = GST_DEBUG_FUNCPTR (gst_gsmenc_start); + base_class->stop = GST_DEBUG_FUNCPTR (gst_gsmenc_stop); + base_class->set_format = GST_DEBUG_FUNCPTR (gst_gsmenc_set_format); + base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_gsmenc_handle_frame); GST_DEBUG_CATEGORY_INIT (gsmenc_debug, "gsmenc", 0, "GSM Encoder"); } static void -gst_gsmenc_init (GstGSMEnc * gsmenc) +gst_gsmenc_init (GstGSMEnc * gsmenc, GstGSMEncClass * klass) { - gint use_wav49; +} - /* create the sink and src pads */ - gsmenc->sinkpad = - gst_pad_new_from_static_template (&gsmenc_sink_template, "sink"); - gst_pad_set_chain_function (gsmenc->sinkpad, gst_gsmenc_chain); - gst_pad_set_setcaps_function (gsmenc->sinkpad, gst_gsmenc_setcaps); - gst_element_add_pad (GST_ELEMENT (gsmenc), gsmenc->sinkpad); +static gboolean +gst_gsmenc_start (GstAudioEncoder * enc) +{ + GstGSMEnc *gsmenc = GST_GSMENC (enc); + gint use_wav49; - gsmenc->srcpad = - gst_pad_new_from_static_template (&gsmenc_src_template, "src"); - gst_element_add_pad (GST_ELEMENT (gsmenc), gsmenc->srcpad); + GST_DEBUG_OBJECT (enc, "start"); gsmenc->state = gsm_create (); @@ -145,78 +119,69 @@ gst_gsmenc_init (GstGSMEnc * gsmenc) use_wav49 = 0; gsm_option (gsmenc->state, GSM_OPT_WAV49, &use_wav49); - gsmenc->adapter = gst_adapter_new (); - gsmenc->next_ts = 0; + return TRUE; } -static void -gst_gsmenc_finalize (GObject * object) +static gboolean +gst_gsmenc_stop (GstAudioEncoder * enc) { - GstGSMEnc *gsmenc; - - gsmenc = GST_GSMENC (object); + GstGSMEnc *gsmenc = GST_GSMENC (enc); - g_object_unref (gsmenc->adapter); + GST_DEBUG_OBJECT (enc, "stop"); gsm_destroy (gsmenc->state); - G_OBJECT_CLASS (parent_class)->finalize (object); + return TRUE; } static gboolean -gst_gsmenc_setcaps (GstPad * pad, GstCaps * caps) +gst_gsmenc_set_format (GstAudioEncoder * benc, GstAudioInfo * info) { - GstGSMEnc *gsmenc; GstCaps *srccaps; - gsmenc = GST_GSMENC (gst_pad_get_parent (pad)); - srccaps = gst_static_pad_template_get_caps (&gsmenc_src_template); + gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (benc), srccaps); - gst_pad_set_caps (gsmenc->srcpad, srccaps); - - gst_object_unref (gsmenc); + /* report needs to base class */ + gst_audio_encoder_set_frame_samples_min (benc, 160); + gst_audio_encoder_set_frame_samples_max (benc, 160); + gst_audio_encoder_set_frame_max (benc, 1); return TRUE; } - static GstFlowReturn -gst_gsmenc_chain (GstPad * pad, GstBuffer * buf) +gst_gsmenc_handle_frame (GstAudioEncoder * benc, GstBuffer * buffer) { GstGSMEnc *gsmenc; gsm_signal *data; GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *outbuf; - gsmenc = GST_GSMENC (gst_pad_get_parent (pad)); + gsmenc = GST_GSMENC (benc); - if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) { - gst_adapter_clear (gsmenc->adapter); + /* we don't deal with squeezing remnants, so simply discard those */ + if (G_UNLIKELY (buffer == NULL)) { + GST_DEBUG_OBJECT (gsmenc, "no data"); + goto done; } - gst_adapter_push (gsmenc->adapter, buf); - - while (gst_adapter_available (gsmenc->adapter) >= 320) { - GstBuffer *outbuf; - - outbuf = gst_buffer_new_and_alloc (33 * sizeof (gsm_byte)); - GST_BUFFER_TIMESTAMP (outbuf) = gsmenc->next_ts; - GST_BUFFER_DURATION (outbuf) = 20 * GST_MSECOND; - gsmenc->next_ts += 20 * GST_MSECOND; - - /* encode 160 16-bit samples into 33 bytes */ - data = (gsm_signal *) gst_adapter_peek (gsmenc->adapter, 320); - gsm_encode (gsmenc->state, data, (gsm_byte *) GST_BUFFER_DATA (outbuf)); - gst_adapter_flush (gsmenc->adapter, 320); + if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 320)) { + GST_DEBUG_OBJECT (gsmenc, "discarding trailing data %d", + GST_BUFFER_SIZE (buffer)); + ret = gst_audio_encoder_finish_frame (benc, NULL, -1); + goto done; + } - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (gsmenc->srcpad)); + outbuf = gst_buffer_new_and_alloc (33 * sizeof (gsm_byte)); - GST_DEBUG_OBJECT (gsmenc, "Pushing buffer of size %d", - GST_BUFFER_SIZE (outbuf)); + /* encode 160 16-bit samples into 33 bytes */ + data = (gsm_signal *) GST_BUFFER_DATA (buffer); + gsm_encode (gsmenc->state, data, (gsm_byte *) GST_BUFFER_DATA (outbuf)); - ret = gst_pad_push (gsmenc->srcpad, outbuf); - } + GST_LOG_OBJECT (gsmenc, "encoded to %d bytes", GST_BUFFER_SIZE (outbuf)); - gst_object_unref (gsmenc); + ret = gst_audio_encoder_finish_frame (benc, outbuf, 160); +done: return ret; } diff --git a/ext/gsm/gstgsmenc.h b/ext/gsm/gstgsmenc.h index ba3b089b7..28b8e2e29 100644 --- a/ext/gsm/gstgsmenc.h +++ b/ext/gsm/gstgsmenc.h @@ -21,7 +21,7 @@ #define __GST_GSMENC_H__ #include <gst/gst.h> -#include <gst/base/gstadapter.h> +#include <gst/audio/gstaudioencoder.h> #ifdef GSM_HEADER_IN_SUBDIR #include <gsm/gsm.h> @@ -47,20 +47,14 @@ typedef struct _GstGSMEncClass GstGSMEncClass; struct _GstGSMEnc { - GstElement element; - - /* pads */ - GstPad *sinkpad, *srcpad; - GstAdapter *adapter; + GstAudioEncoder element; gsm state; - GstClockTime next_ts; - gboolean firstBuf; }; struct _GstGSMEncClass { - GstElementClass parent_class; + GstAudioEncoderClass parent_class; }; GType gst_gsmenc_get_type (void); diff --git a/ext/kate/gstkateenc.c b/ext/kate/gstkateenc.c index 8ee8b69df..450e8e61e 100644 --- a/ext/kate/gstkateenc.c +++ b/ext/kate/gstkateenc.c @@ -924,33 +924,32 @@ gst_kate_enc_chain_text (GstKateEnc * ke, GstBuffer * buf, ("kate_encode_set_markup_type: %d", ret)); rflow = GST_FLOW_ERROR; } else { - char *text; - gsize text_len; + const char *text; + size_t text_len; + gboolean need_unmap = TRUE; + kate_float t0 = start / (double) GST_SECOND; + kate_float t1 = stop / (double) GST_SECOND; text = gst_buffer_map (buf, &text_len, NULL, GST_MAP_READ); - if (text) { - kate_float t0 = start / (double) GST_SECOND; - kate_float t1 = stop / (double) GST_SECOND; - GST_LOG_OBJECT (ke, "Encoding text: %*.*s (%u bytes) from %f to %f", - (int) text_len, (int) text_len, text, text_len, t0, t1); - - ret = kate_encode_text (&ke->k, t0, t1, text, text_len, &kp); + if (text == NULL) { + text = ""; + text_len = 0; + need_unmap = FALSE; + } - if (G_UNLIKELY (ret < 0)) { - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Failed to encode text: %d", ret)); - rflow = GST_FLOW_ERROR; - } else { - rflow = - gst_kate_enc_chain_push_packet (ke, &kp, start, stop - start + 1); - } - } else { - /* FIXME: this should not be an error, we should ignore it and move on */ + GST_LOG_OBJECT (ke, "Encoding text: %*.*s (%u bytes) from %f to %f", + (int) text_len, (int) text_len, GST_BUFFER_DATA (buf), + GST_BUFFER_SIZE (buf), t0, t1); + ret = kate_encode_text (&ke->k, t0, t1, text, text_len, &kp); + if (G_UNLIKELY (ret < 0)) { GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("no text in text packet")); + ("Failed to encode text: %d", ret)); rflow = GST_FLOW_ERROR; + } else { + rflow = gst_kate_enc_chain_push_packet (ke, &kp, start, stop - start + 1); } - gst_buffer_unmap (buf, text, text_len); + if (need_unmap) + gst_buffer_unmap (buf, text, text_len); } return rflow; diff --git a/ext/opencv/gsttemplatematch.c b/ext/opencv/gsttemplatematch.c index 4f26121db..84640ff3b 100644 --- a/ext/opencv/gsttemplatematch.c +++ b/ext/opencv/gsttemplatematch.c @@ -296,6 +296,8 @@ gst_template_match_finalize (GObject * object) if (filter->cvTemplateImage) { cvReleaseImage (&filter->cvTemplateImage); } + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); } /* chain function diff --git a/ext/resindvd/resindvdbin.c b/ext/resindvd/resindvdbin.c index 5885b238a..8c2d94fd6 100644 --- a/ext/resindvd/resindvdbin.c +++ b/ext/resindvd/resindvdbin.c @@ -470,18 +470,16 @@ create_elements (RsnDvdBin * dvdbin) RSN_TYPE_STREAM_SELECTOR, "audioselect", "Audio stream selector")) return FALSE; - if (!try_create_piece (dvdbin, DVD_ELEM_AUDDEC, NULL, - RSN_TYPE_AUDIODEC, "auddec", "audio decoder")) + if (!try_create_piece (dvdbin, DVD_ELEM_AUD_MUNGE, NULL, + RSN_TYPE_AUDIOMUNGE, "audioearlymunge", "Audio output filter")) return FALSE; - /* rsnaudiomunge goes after the audio decoding to regulate the stream */ - if (!try_create_piece (dvdbin, DVD_ELEM_AUD_MUNGE, NULL, - RSN_TYPE_AUDIOMUNGE, "audiomunge", "Audio output filter")) + if (!try_create_piece (dvdbin, DVD_ELEM_AUDDEC, NULL, + RSN_TYPE_AUDIODEC, "auddec", "audio decoder")) return FALSE; - src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "src"); - sink = - gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], "sink"); + src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], "src"); + sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "sink"); if (src == NULL || sink == NULL) goto failed_aud_connect; if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) @@ -491,7 +489,8 @@ create_elements (RsnDvdBin * dvdbin) src = sink = NULL; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_SELECT], "src"); - sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "sink"); + sink = + gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], "sink"); if (src == NULL || sink == NULL) goto failed_aud_connect; if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) @@ -501,7 +500,7 @@ create_elements (RsnDvdBin * dvdbin) src = sink = NULL; /* ghost audio munge output pad onto bin */ - src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], "src"); + src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "src"); if (src == NULL) goto failed_aud_ghost; src_templ = gst_static_pad_template_get (&audio_src_template); @@ -701,7 +700,7 @@ demux_pad_added (GstElement * element, GstPad * pad, RsnDvdBin * dvdbin) gst_element_get_request_pad (dvdbin->pieces[DVD_ELEM_SPU_SELECT], "sink_%u"); skip_mq = TRUE; - } else if (can_sink_caps (dvdbin->pieces[DVD_ELEM_AUDDEC], caps)) { + } else if (can_sink_caps (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], caps)) { GST_LOG_OBJECT (dvdbin, "Found audio pad w/ caps %" GST_PTR_FORMAT, caps); dest_pad = gst_element_get_request_pad (dvdbin->pieces[DVD_ELEM_AUD_SELECT], @@ -720,7 +719,7 @@ demux_pad_added (GstElement * element, GstPad * pad, RsnDvdBin * dvdbin) ("No MPEG video decoder found")); } else { GST_ELEMENT_WARNING (dvdbin, STREAM, CODEC_NOT_FOUND, (NULL), - ("No MPEG video decoder found")); + ("No MPEG audio decoder found")); } } diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index a0059fdaa..e3eba9f91 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -269,6 +269,7 @@ rsn_dvdsrc_finalize (GObject * object) g_mutex_free (src->dvd_lock); g_mutex_free (src->branch_lock); g_cond_free (src->still_cond); + g_free (src->device); gst_buffer_replace (&src->alloc_buf, NULL); gst_buffer_replace (&src->next_buf, NULL); diff --git a/ext/resindvd/rsnaudiomunge.c b/ext/resindvd/rsnaudiomunge.c index 5e6f9cc6f..2b78dfea9 100644 --- a/ext/resindvd/rsnaudiomunge.c +++ b/ext/resindvd/rsnaudiomunge.c @@ -155,9 +155,9 @@ rsn_audiomunge_set_caps (GstPad * pad, GstCaps * caps) g_return_val_if_fail (munge != NULL, FALSE); otherpad = (pad == munge->srcpad) ? munge->sinkpad : munge->srcpad; - gst_object_unref (munge); ret = gst_pad_set_caps (otherpad, caps); + gst_object_unref (munge); return ret; } diff --git a/ext/resindvd/rsndec.c b/ext/resindvd/rsndec.c index 3abc0065c..662e932d5 100644 --- a/ext/resindvd/rsndec.c +++ b/ext/resindvd/rsndec.c @@ -247,18 +247,50 @@ _get_decoder_factories (gpointer arg) GstPadTemplate *templ = gst_element_class_get_pad_template (klass, "sink"); RsnDecFactoryFilterCtx ctx = { NULL, }; + GstCaps *raw; + gboolean raw_audio; ctx.desired_caps = gst_pad_template_get_caps (templ); + + raw = gst_caps_from_string ("audio/x-raw-float"); + raw_audio = gst_caps_can_intersect (raw, ctx.desired_caps); + if (raw_audio) { + GstCaps *sub = gst_caps_subtract (ctx.desired_caps, raw); + ctx.desired_caps = sub; + } else { + gst_caps_ref (ctx.desired_caps); + } + gst_caps_unref (raw); + /* Set decoder caps to empty. Will be filled by the factory_filter */ ctx.decoder_caps = gst_caps_new_empty (); + GST_DEBUG ("Finding factories for caps: %" GST_PTR_FORMAT, ctx.desired_caps); factories = gst_default_registry_feature_filter ( (GstPluginFeatureFilter) rsndec_factory_filter, FALSE, &ctx); + /* If these are audio caps, we add audioconvert, which is not a decoder, + but allows raw audio to go through relatively unmolested - this will + come handy when we have to send placeholder silence to allow preroll + for those DVDs which have titles with no audio track. */ + if (raw_audio) { + GstPluginFeature *feature; + GST_DEBUG ("These are audio caps, adding audioconvert"); + feature = + gst_default_registry_find_feature ("audioconvert", + GST_TYPE_ELEMENT_FACTORY); + if (feature) { + factories = g_list_append (factories, feature); + } else { + GST_WARNING ("Could not find feature audioconvert"); + } + } + factories = g_list_sort (factories, (GCompareFunc) sort_by_ranks); GST_DEBUG ("Available decoder caps %" GST_PTR_FORMAT, ctx.decoder_caps); gst_caps_unref (ctx.decoder_caps); + gst_caps_unref (ctx.desired_caps); return factories; } @@ -343,7 +375,7 @@ static GstStaticPadTemplate audio_sink_template = GST_STATIC_CAPS ("audio/mpeg,mpegversion=(int)1;" "audio/x-private1-lpcm;" "audio/x-private1-ac3;" "audio/ac3;" "audio/x-ac3;" - "audio/x-private1-dts;") + "audio/x-private1-dts; audio/x-raw-float") ); static GstStaticPadTemplate audio_src_template = GST_STATIC_PAD_TEMPLATE ("src", diff --git a/ext/rsvg/gstrsvgoverlay.c b/ext/rsvg/gstrsvgoverlay.c index 1cbd0990c..9d4ce6025 100644 --- a/ext/rsvg/gstrsvgoverlay.c +++ b/ext/rsvg/gstrsvgoverlay.c @@ -123,6 +123,8 @@ static GstStaticPadTemplate data_sink_template = GST_BOILERPLATE (GstRsvgOverlay, gst_rsvg_overlay, GstVideoFilter, GST_TYPE_VIDEO_FILTER); +static void gst_rsvg_overlay_finalize (GObject * object); + static void gst_rsvg_overlay_set_svg_data (GstRsvgOverlay * overlay, const gchar * data, gboolean consider_as_filename) @@ -467,6 +469,7 @@ gst_rsvg_overlay_class_init (GstRsvgOverlayClass * klass) gobject_class->set_property = gst_rsvg_overlay_set_property; gobject_class->get_property = gst_rsvg_overlay_get_property; + gobject_class->finalize = gst_rsvg_overlay_finalize; g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DATA, g_param_spec_string ("data", "data", "SVG data.", "", @@ -542,3 +545,13 @@ gst_rsvg_overlay_init (GstRsvgOverlay * overlay, GstRsvgOverlayClass * klass) GST_DEBUG_FUNCPTR (gst_rsvg_overlay_data_sink_event)); gst_element_add_pad (GST_ELEMENT (overlay), overlay->data_sinkpad); } + +static void +gst_rsvg_overlay_finalize (GObject * object) +{ + GstRsvgOverlay *overlay = GST_RSVG_OVERLAY (object); + + g_object_unref (overlay->adapter); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} diff --git a/ext/schroedinger/gstschrodec.c b/ext/schroedinger/gstschrodec.c index 50bb40480..c8fa8336e 100644 --- a/ext/schroedinger/gstschrodec.c +++ b/ext/schroedinger/gstschrodec.c @@ -102,7 +102,7 @@ static GstStaticPadTemplate gst_schro_dec_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ I420, YUY2, AYUV }")) + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV (GST_SCHRO_YUV_LIST)) ); GST_BOILERPLATE (GstSchroDec, gst_schro_dec, GstBaseVideoDecoder, @@ -313,12 +313,25 @@ parse_sequence_header (GstSchroDec * schro_dec, guint8 * data, int size) ret = schro_parse_decode_sequence_header (data + 13, size - 13, &video_format); if (ret) { - if (video_format.chroma_format == SCHRO_CHROMA_444) { - state->format = GST_VIDEO_FORMAT_AYUV; - } else if (video_format.chroma_format == SCHRO_CHROMA_422) { - state->format = GST_VIDEO_FORMAT_YUY2; - } else if (video_format.chroma_format == SCHRO_CHROMA_420) { - state->format = GST_VIDEO_FORMAT_I420; + int bit_depth; + + bit_depth = schro_video_format_get_bit_depth (&video_format); + + if (bit_depth == 8) { + if (video_format.chroma_format == SCHRO_CHROMA_444) { + state->format = GST_VIDEO_FORMAT_AYUV; + } else if (video_format.chroma_format == SCHRO_CHROMA_422) { + state->format = GST_VIDEO_FORMAT_UYVY; + } else if (video_format.chroma_format == SCHRO_CHROMA_420) { + state->format = GST_VIDEO_FORMAT_I420; + } + } else if (bit_depth <= 10) { + state->format = GST_VIDEO_FORMAT_v210; + } else if (bit_depth <= 16) { + state->format = GST_VIDEO_FORMAT_AYUV64; + } else { + GST_ERROR ("bit depth too large (%d > 16)", bit_depth); + state->format = GST_VIDEO_FORMAT_AYUV64; } state->fps_n = video_format.frame_rate_numerator; state->fps_d = video_format.frame_rate_denominator; diff --git a/ext/schroedinger/gstschroenc.c b/ext/schroedinger/gstschroenc.c index c2064d3ca..1fb75f98e 100644 --- a/ext/schroedinger/gstschroenc.c +++ b/ext/schroedinger/gstschroenc.c @@ -107,7 +107,7 @@ static GstStaticPadTemplate gst_schro_enc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ I420, YV12, YUY2, UYVY, AYUV }")) + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV (GST_SCHRO_YUV_LIST)) ); static GstStaticPadTemplate gst_schro_enc_src_template = @@ -271,13 +271,18 @@ gst_schro_enc_set_format (GstBaseVideoEncoder * base_video_encoder, switch (state->format) { case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_Y42B: schro_enc->video_format->chroma_format = SCHRO_CHROMA_420; break; case GST_VIDEO_FORMAT_YUY2: case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_v216: + case GST_VIDEO_FORMAT_v210: schro_enc->video_format->chroma_format = SCHRO_CHROMA_422; break; case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_AYUV64: schro_enc->video_format->chroma_format = SCHRO_CHROMA_444; break; case GST_VIDEO_FORMAT_ARGB: @@ -300,8 +305,24 @@ gst_schro_enc_set_format (GstBaseVideoEncoder * base_video_encoder, schro_enc->video_format->aspect_ratio_numerator = state->par_n; schro_enc->video_format->aspect_ratio_denominator = state->par_d; - schro_video_format_set_std_signal_range (schro_enc->video_format, - SCHRO_SIGNAL_RANGE_8BIT_VIDEO); + switch (state->format) { + default: + schro_video_format_set_std_signal_range (schro_enc->video_format, + SCHRO_SIGNAL_RANGE_8BIT_VIDEO); + break; + case GST_VIDEO_FORMAT_v210: + schro_video_format_set_std_signal_range (schro_enc->video_format, + SCHRO_SIGNAL_RANGE_10BIT_VIDEO); + break; + case GST_VIDEO_FORMAT_v216: + case GST_VIDEO_FORMAT_AYUV64: + schro_enc->video_format->luma_offset = 64 << 8; + schro_enc->video_format->luma_excursion = 219 << 8; + schro_enc->video_format->chroma_offset = 128 << 8; + schro_enc->video_format->chroma_excursion = 224 << 8; + break; + } + schro_video_format_set_std_colour_spec (schro_enc->video_format, SCHRO_COLOUR_SPEC_HDTV); diff --git a/ext/schroedinger/gstschroutils.c b/ext/schroedinger/gstschroutils.c index 66514a3d5..99a22c8a4 100644 --- a/ext/schroedinger/gstschroutils.c +++ b/ext/schroedinger/gstschroutils.c @@ -72,6 +72,29 @@ gst_schro_buffer_wrap (GstBuffer * buf, GstVideoFormat format, int width, frame = schro_frame_new_from_data_AYUV (GST_BUFFER_DATA (buf), width, height); break; + case GST_VIDEO_FORMAT_Y42B: + frame = + schro_frame_new_from_data_Y42B (GST_BUFFER_DATA (buf), width, height); + break; + case GST_VIDEO_FORMAT_Y444: + frame = + schro_frame_new_from_data_Y444 (GST_BUFFER_DATA (buf), width, height); + break; + case GST_VIDEO_FORMAT_v210: + frame = + schro_frame_new_from_data_v210 (GST_BUFFER_DATA (buf), width, height); + break; + case GST_VIDEO_FORMAT_v216: + frame = + schro_frame_new_from_data_v216 (GST_BUFFER_DATA (buf), width, height); + break; +#ifdef SCHRO_FRAME_FORMAT_AY64 + /* Added in 1.0.11 */ + case GST_VIDEO_FORMAT_AYUV64: + frame = + schro_frame_new_from_data_AY64 (GST_BUFFER_DATA (buf), width, height); + break; +#endif #if 0 case GST_VIDEO_FORMAT_ARGB: { diff --git a/ext/schroedinger/gstschroutils.h b/ext/schroedinger/gstschroutils.h index 4e8ca2de3..a9924a633 100644 --- a/ext/schroedinger/gstschroutils.h +++ b/ext/schroedinger/gstschroutils.h @@ -24,6 +24,12 @@ #include <gst/video/video.h> #include <schroedinger/schro.h> +#ifdef SCHRO_FRAME_FORMAT_AY64 +#define GST_SCHRO_YUV_LIST "{ I420, YV12, YUY2, UYVY, AYUV, Y42B, Y444, v216, v210, AY64 }" +#else +#define GST_SCHRO_YUV_LIST "{ I420, YV12, YUY2, UYVY, AYUV, Y42B, Y444 }" +#endif + SchroFrame * gst_schro_buffer_wrap (GstBuffer *buf, GstVideoFormat format, int width, int height); diff --git a/ext/spc/gstspc.c b/ext/spc/gstspc.c index 2c74a9c56..916718235 100644 --- a/ext/spc/gstspc.c +++ b/ext/spc/gstspc.c @@ -169,6 +169,8 @@ gst_spc_dec_dispose (GObject * object) } spc_tag_free (&spc->tag_info); + + GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); } static GstFlowReturn diff --git a/ext/vp8/gstvp8enc.c b/ext/vp8/gstvp8enc.c index 7a1832843..ea92a76ce 100644 --- a/ext/vp8/gstvp8enc.c +++ b/ext/vp8/gstvp8enc.c @@ -1174,6 +1174,9 @@ gst_vp8_enc_shape_output (GstBaseVideoEncoder * base_video_encoder, gst_util_uint64_scale (frame->presentation_frame_number + 1, GST_SECOND * state->fps_d, state->fps_n); + GST_LOG_OBJECT (base_video_encoder, "src ts: %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + ret = gst_pad_push (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder), buf); if (ret != GST_FLOW_OK) { GST_WARNING_OBJECT (encoder, "flow error %d", ret); |