summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--REQUIREMENTS3
-rw-r--r--configure.ac28
-rw-r--r--ext/Makefile.am8
-rw-r--r--ext/chromaprint/Makefile.am14
-rw-r--r--ext/chromaprint/gstchromaprint.c317
-rw-r--r--ext/chromaprint/gstchromaprint.h77
-rw-r--r--ext/cog/gstcogmse.c8
-rw-r--r--ext/gme/gstgme.c2
-rw-r--r--ext/gsm/gstgsmdec.c257
-rw-r--r--ext/gsm/gstgsmdec.h20
-rw-r--r--ext/gsm/gstgsmenc.c147
-rw-r--r--ext/gsm/gstgsmenc.h12
-rw-r--r--ext/kate/gstkateenc.c41
-rw-r--r--ext/opencv/gsttemplatematch.c2
-rw-r--r--ext/resindvd/resindvdbin.c23
-rw-r--r--ext/resindvd/resindvdsrc.c1
-rw-r--r--ext/resindvd/rsnaudiomunge.c2
-rw-r--r--ext/resindvd/rsndec.c34
-rw-r--r--ext/rsvg/gstrsvgoverlay.c13
-rw-r--r--ext/schroedinger/gstschrodec.c27
-rw-r--r--ext/schroedinger/gstschroenc.c27
-rw-r--r--ext/schroedinger/gstschroutils.c23
-rw-r--r--ext/schroedinger/gstschroutils.h6
-rw-r--r--ext/spc/gstspc.c2
-rw-r--r--ext/vp8/gstvp8enc.c3
-rw-r--r--gst-libs/gst/codecparsers/gsth264parser.c16
-rw-r--r--gst-libs/gst/codecparsers/gsth264parser.h2
-rw-r--r--gst-libs/gst/video/gstbasevideoencoder.c2
-rw-r--r--gst/adpcmdec/Makefile.am5
-rw-r--r--gst/adpcmdec/adpcmdec.c261
-rw-r--r--gst/adpcmenc/Makefile.am5
-rw-r--r--gst/adpcmenc/adpcmenc.c215
-rw-r--r--gst/debugutils/gstdebugspy.c2
-rw-r--r--gst/festival/gstfestival.c29
-rw-r--r--gst/inter/Makefile.am4
-rw-r--r--gst/inter/gstinter.c10
-rw-r--r--gst/inter/gstinteraudiosink.c7
-rw-r--r--gst/inter/gstinteraudiosrc.c7
-rw-r--r--gst/inter/gstintersubsink.c325
-rw-r--r--gst/inter/gstintersubsink.h57
-rw-r--r--gst/inter/gstintersubsrc.c455
-rw-r--r--gst/inter/gstintersubsrc.h57
-rw-r--r--gst/inter/gstintersurface.c33
-rw-r--r--gst/inter/gstintersurface.h4
-rw-r--r--gst/inter/gstintervideosink.c29
-rw-r--r--gst/inter/gstintervideosink.h1
-rw-r--r--gst/inter/gstintervideosrc.c37
-rw-r--r--gst/inter/gstintervideosrc.h2
-rw-r--r--gst/mpegdemux/flutspmtstreaminfo.c2
-rw-r--r--gst/mpegdemux/gstmpegdemux.c84
-rw-r--r--gst/mpegdemux/gstmpegtsdemux.c11
-rw-r--r--gst/mpegdemux/mpegtsparse.c2
-rw-r--r--gst/mpegtsdemux/mpegtsbase.c2
-rw-r--r--gst/mpegtsdemux/tsdemux.c1
-rw-r--r--gst/mve/gstmvemux.c2
-rw-r--r--gst/mve/mvevideoenc16.c3
-rw-r--r--gst/nuvdemux/gstnuvdemux.c4
-rw-r--r--gst/siren/gstsirenenc.c2
-rw-r--r--gst/videoparsers/Makefile.am1
-rw-r--r--sys/avc/Makefile.am2
-rw-r--r--sys/linsys/gstlinsyssdisink.c5
-rw-r--r--sys/linsys/gstlinsyssdisrc.c5
62 files changed, 2043 insertions, 745 deletions
diff --git a/REQUIREMENTS b/REQUIREMENTS
index ca498fcf2..601cebb4f 100644
--- a/REQUIREMENTS
+++ b/REQUIREMENTS
@@ -63,7 +63,8 @@ libamrwb (for AMR-WB support)
(http://www.penguin.cz/~utx/amr)
libkate (for Kate support)
(http://libkate.googlecode.com/)
-
+librtmp (for RTMP support)
+ (http://rtmpdump.mplayerhq.hu/)
Optional (debian) packages:
===========================
diff --git a/configure.ac b/configure.ac
index 035cf1944..c90b7a243 100644
--- a/configure.ac
+++ b/configure.ac
@@ -71,6 +71,8 @@ AG_GST_GETTEXT([gst-plugins-bad-$GST_MAJORMINOR])
dnl *** check for arguments to configure ***
+AG_GST_ARG_DISABLE_FATAL_WARNINGS
+
AG_GST_ARG_DEBUG
AG_GST_ARG_PROFILING
AG_GST_ARG_VALGRIND
@@ -208,9 +210,11 @@ AM_CONDITIONAL(HAVE_GST_CHECK, test "x$HAVE_GST_CHECK" = "xyes")
AG_GST_CHECK_GST_PLUGINS_BASE($GST_MAJORMINOR, [$GSTPB_REQ], yes)
dnl check for uninstalled plugin directories for unit tests
-AG_GST_CHECK_GST_PLUGINS_GOOD($GST_MAJORMINOR, [0.11.0])
-AG_GST_CHECK_GST_PLUGINS_UGLY($GST_MAJORMINOR, [0.11.0])
-AG_GST_CHECK_GST_PLUGINS_FFMPEG($GST_MAJORMINOR, [0.11.0])
+AG_GST_CHECK_UNINSTALLED_SETUP([
+ AG_GST_CHECK_GST_PLUGINS_GOOD($GST_MAJORMINOR, [0.11.0])
+ AG_GST_CHECK_GST_PLUGINS_UGLY($GST_MAJORMINOR, [0.11.0])
+ AG_GST_CHECK_GST_PLUGINS_FFMPEG($GST_MAJORMINOR, [0.11.0])
+])
dnl Check for documentation xrefs
GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`"
@@ -288,14 +292,14 @@ AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO([$PACKAGE_VERSION_NANO],
dnl define an ERROR_CFLAGS Makefile variable
dnl -Waggregate-return - libexif returns aggregates
dnl -Wundef - Windows headers check _MSC_VER unconditionally
-AG_GST_SET_ERROR_CFLAGS($GST_GIT, [
+AG_GST_SET_ERROR_CFLAGS($FATAL_WARNINGS, [
-Wmissing-declarations -Wmissing-prototypes -Wredundant-decls
-Wwrite-strings -Wformat-security -Wold-style-definition
-Winit-self -Wmissing-include-dirs -Waddress -Wno-multichar
-Wnested-externs])
dnl define an ERROR_CXXFLAGS Makefile variable
-AG_GST_SET_ERROR_CXXFLAGS($GST_GIT, [
+AG_GST_SET_ERROR_CXXFLAGS($FATAL_WARNINGS, [
-Wmissing-declarations -Wredundant-decls
-Wwrite-strings -Wformat-nonliteral -Wformat-security
-Winit-self -Wmissing-include-dirs -Waddress -Wno-multichar ])
@@ -755,6 +759,16 @@ AG_GST_CHECK_FEATURE(CELT, [celt], celt, [
AC_SUBST(CELT_LIBS)
])
+dnl *** chromaprint ***
+translit(dnm, m, l) AM_CONDITIONAL(USE_CHROMAPRINT, true)
+AG_GST_CHECK_FEATURE(CHROMAPRINT, [chromaprint], chromaprint, [
+ PKG_CHECK_MODULES(CHROMAPRINT, libchromaprint, HAVE_CHROMAPRINT="yes", [
+ HAVE_CHROMAPRINT="no"
+ ])
+ AC_SUBST(CHROMAPRINT_CFLAGS)
+ AC_SUBST(CHROMAPRINT_LIBS)
+])
+
dnl *** Cog ***
translit(dnm, m, l) AM_CONDITIONAL(USE_COG, true)
AG_GST_CHECK_FEATURE(COG, [Cog plugin], cog, [
@@ -1712,7 +1726,7 @@ AG_GST_CHECK_FEATURE(VDPAU, [VDPAU], vdpau, [
dnl *** schroedinger ***
translit(dnm, m, l) AM_CONDITIONAL(USE_SCHRO, true)
AG_GST_CHECK_FEATURE(SCHRO, [Schroedinger video codec], schro, [
- AG_GST_PKG_CHECK_MODULES(SCHRO, schroedinger-1.0 >= 1.0.7)
+ AG_GST_PKG_CHECK_MODULES(SCHRO, schroedinger-1.0 >= 1.0.10)
])
dnl *** zbar ***
@@ -1800,6 +1814,7 @@ AM_CONDITIONAL(USE_APEXSINK, false)
AM_CONDITIONAL(USE_BZ2, false)
AM_CONDITIONAL(USE_CDAUDIO, false)
AM_CONDITIONAL(USE_CELT, false)
+AM_CONDITIONAL(USE_CHROMAPRINT, false)
AM_CONDITIONAL(USE_COG, false)
AM_CONDITIONAL(USE_CURL, false)
AM_CONDITIONAL(USE_DC1394, false)
@@ -2056,6 +2071,7 @@ ext/apexsink/Makefile
ext/bz2/Makefile
ext/cdaudio/Makefile
ext/celt/Makefile
+ext/chromaprint/Makefile
ext/cog/Makefile
ext/curl/Makefile
ext/dc1394/Makefile
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);
diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c
index 6a164ecb1..b96965091 100644
--- a/gst-libs/gst/codecparsers/gsth264parser.c
+++ b/gst-libs/gst/codecparsers/gsth264parser.c
@@ -518,6 +518,7 @@ gst_h264_parse_hrd_parameters (GstH264HRDParams * hrd, NalReader * nr)
for (sched_sel_idx = 0; sched_sel_idx <= hrd->cpb_cnt_minus1; sched_sel_idx++) {
READ_UE (nr, hrd->bit_rate_value_minus1[sched_sel_idx]);
READ_UE (nr, hrd->cpb_size_value_minus1[sched_sel_idx]);
+ READ_UINT8 (nr, hrd->cbr_flag[sched_sel_idx], 1);
}
READ_UINT8 (nr, hrd->initial_cpb_removal_delay_length_minus1, 5);
@@ -747,22 +748,26 @@ slice_parse_ref_pic_list_modification_1 (GstH264SliceHdr * slice,
NalReader * nr, guint list)
{
GstH264RefPicListModification *entries;
- guint8 *ref_pic_list_modification_flag;
+ guint8 *ref_pic_list_modification_flag, *n_ref_pic_list_modification;
guint32 modification_of_pic_nums_idc;
guint i = 0;
if (list == 0) {
entries = slice->ref_pic_list_modification_l0;
ref_pic_list_modification_flag = &slice->ref_pic_list_modification_flag_l0;
+ n_ref_pic_list_modification = &slice->n_ref_pic_list_modification_l0;
} else {
entries = slice->ref_pic_list_modification_l1;
ref_pic_list_modification_flag = &slice->ref_pic_list_modification_flag_l1;
+ n_ref_pic_list_modification = &slice->n_ref_pic_list_modification_l1;
}
READ_UINT8 (nr, *ref_pic_list_modification_flag, 1);
if (*ref_pic_list_modification_flag) {
- do {
+ while (1) {
READ_UE (nr, modification_of_pic_nums_idc);
+ if (modification_of_pic_nums_idc == 3)
+ break;
if (modification_of_pic_nums_idc == 0 ||
modification_of_pic_nums_idc == 1) {
READ_UE_ALLOWED (nr, entries[i].value.abs_diff_pic_num_minus1, 0,
@@ -770,9 +775,10 @@ slice_parse_ref_pic_list_modification_1 (GstH264SliceHdr * slice,
} else if (modification_of_pic_nums_idc == 2) {
READ_UE (nr, entries[i].value.long_term_pic_num);
}
- } while (modification_of_pic_nums_idc != 3);
+ entries[i++].modification_of_pic_nums_idc = modification_of_pic_nums_idc;
+ }
}
-
+ *n_ref_pic_list_modification = i;
return TRUE;
error:
@@ -1050,6 +1056,8 @@ gst_h264_parse_clock_timestamp (GstH264ClockTimestamp * tim,
if (time_offset_length > 0)
READ_UINT32 (nr, tim->time_offset, time_offset_length);
+ return TRUE;
+
error:
GST_WARNING ("error parsing \"Clock timestamp\"");
return FALSE;
diff --git a/gst-libs/gst/codecparsers/gsth264parser.h b/gst-libs/gst/codecparsers/gsth264parser.h
index d58f1b07d..3c221560e 100644
--- a/gst-libs/gst/codecparsers/gsth264parser.h
+++ b/gst-libs/gst/codecparsers/gsth264parser.h
@@ -573,8 +573,10 @@ struct _GstH264SliceHdr
guint8 num_ref_idx_l1_active_minus1;
guint8 ref_pic_list_modification_flag_l0;
+ guint8 n_ref_pic_list_modification_l0;
GstH264RefPicListModification ref_pic_list_modification_l0[32];
guint8 ref_pic_list_modification_flag_l1;
+ guint8 n_ref_pic_list_modification_l1;
GstH264RefPicListModification ref_pic_list_modification_l1[32];
GstH264PredWeightTable pred_weight_table;
diff --git a/gst-libs/gst/video/gstbasevideoencoder.c b/gst-libs/gst/video/gstbasevideoencoder.c
index 8126c120f..5482e67c1 100644
--- a/gst-libs/gst/video/gstbasevideoencoder.c
+++ b/gst-libs/gst/video/gstbasevideoencoder.c
@@ -1132,7 +1132,7 @@ void
gst_base_video_encoder_set_latency (GstBaseVideoEncoder * base_video_encoder,
GstClockTime min_latency, GstClockTime max_latency)
{
- g_return_if_fail (min_latency >= 0);
+ g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min_latency));
g_return_if_fail (max_latency >= min_latency);
GST_OBJECT_LOCK (base_video_encoder);
diff --git a/gst/adpcmdec/Makefile.am b/gst/adpcmdec/Makefile.am
index 2521fe6f1..84e125224 100644
--- a/gst/adpcmdec/Makefile.am
+++ b/gst/adpcmdec/Makefile.am
@@ -5,8 +5,9 @@ libgstadpcmdec_la_SOURCES = adpcmdec.c
# flags used to compile this plugin
# add other _CFLAGS and _LIBS as needed
-libgstadpcmdec_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS)
-libgstadpcmdec_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS)
+libgstadpcmdec_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
+libgstadpcmdec_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-@GST_MAJORMINOR@ \
+ $(GST_LIBS)
libgstadpcmdec_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstadpcmdec_la_LIBTOOLFLAGS = --tag=disable-static
diff --git a/gst/adpcmdec/adpcmdec.c b/gst/adpcmdec/adpcmdec.c
index 0fcfeb03f..c6eb749d3 100644
--- a/gst/adpcmdec/adpcmdec.c
+++ b/gst/adpcmdec/adpcmdec.c
@@ -28,7 +28,7 @@
#endif
#include <gst/gst.h>
-#include <gst/base/gstadapter.h>
+#include <gst/audio/gstaudiodecoder.h>
#define GST_TYPE_ADPCM_DEC \
(adpcmdec_get_type ())
@@ -69,80 +69,29 @@ enum adpcm_layout
typedef struct _ADPCMDecClass
{
- GstElementClass parent_class;
+ GstAudioDecoderClass parent_class;
} ADPCMDecClass;
typedef struct _ADPCMDec
{
- GstElement parent;
-
- GstPad *sinkpad;
- GstPad *srcpad;
-
- GstCaps *output_caps;
+ GstAudioDecoder parent;
enum adpcm_layout layout;
int rate;
int channels;
int blocksize;
-
- gboolean is_setup;
-
- GstClockTime timestamp;
- GstClockTime base_timestamp;
-
- guint64 out_samples;
-
- GstAdapter *adapter;
-
} ADPCMDec;
GType adpcmdec_get_type (void);
-GST_BOILERPLATE (ADPCMDec, adpcmdec, GstElement, GST_TYPE_ELEMENT);
-static gboolean
-adpcmdec_setup (ADPCMDec * dec)
-{
- dec->output_caps = gst_caps_new_simple ("audio/x-raw-int",
- "rate", G_TYPE_INT, dec->rate,
- "channels", G_TYPE_INT, dec->channels,
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "endianness", G_TYPE_INT, G_BYTE_ORDER,
- "signed", G_TYPE_BOOLEAN, TRUE, NULL);
-
- if (dec->output_caps) {
- gst_pad_set_caps (dec->srcpad, dec->output_caps);
- }
-
- dec->is_setup = TRUE;
- dec->timestamp = GST_CLOCK_TIME_NONE;
- dec->base_timestamp = GST_CLOCK_TIME_NONE;
- dec->adapter = gst_adapter_new ();
- dec->out_samples = 0;
-
- return TRUE;
-}
-
-static void
-adpcmdec_teardown (ADPCMDec * dec)
-{
- if (dec->output_caps) {
- gst_caps_unref (dec->output_caps);
- dec->output_caps = NULL;
- }
- if (dec->adapter) {
- g_object_unref (dec->adapter);
- dec->adapter = NULL;
- }
- dec->is_setup = FALSE;
-}
+GST_BOILERPLATE (ADPCMDec, adpcmdec, GstAudioDecoder, GST_TYPE_AUDIO_DECODER);
static gboolean
-adpcmdec_sink_setcaps (GstPad * pad, GstCaps * caps)
+adpcmdec_set_format (GstAudioDecoder * bdec, GstCaps * in_caps)
{
- ADPCMDec *dec = (ADPCMDec *) gst_pad_get_parent (pad);
- GstStructure *structure = gst_caps_get_structure (caps, 0);
+ ADPCMDec *dec = (ADPCMDec *) (bdec);
+ GstStructure *structure = gst_caps_get_structure (in_caps, 0);
const gchar *layout;
+ GstCaps *caps;
layout = gst_structure_get_string (structure, "layout");
if (!layout)
@@ -163,9 +112,16 @@ adpcmdec_sink_setcaps (GstPad * pad, GstCaps * caps)
if (!gst_structure_get_int (structure, "channels", &dec->channels))
return FALSE;
- if (dec->is_setup)
- adpcmdec_teardown (dec);
- gst_object_unref (dec);
+ caps = gst_caps_new_simple ("audio/x-raw-int",
+ "rate", G_TYPE_INT, dec->rate,
+ "channels", G_TYPE_INT, dec->channels,
+ "width", G_TYPE_INT, 16,
+ "depth", G_TYPE_INT, 16,
+ "endianness", G_TYPE_INT, G_BYTE_ORDER,
+ "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+
+ gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (bdec), caps);
+ gst_caps_unref (caps);
return TRUE;
}
@@ -377,10 +333,10 @@ adpcmdec_decode_ima_block (ADPCMDec * dec, int n_samples, const guint8 * data,
return TRUE;
}
-static GstFlowReturn
+static GstBuffer *
adpcmdec_decode_block (ADPCMDec * dec, const guint8 * data, int blocksize)
{
- gboolean res;
+ gboolean res = FALSE;
GstBuffer *outbuf = NULL;
int outsize;
int samples;
@@ -390,7 +346,7 @@ adpcmdec_decode_block (ADPCMDec * dec, const guint8 * data, int blocksize)
give two initial sample values per channel. Then the remainder gives
two samples per byte */
if (blocksize < 7 * dec->channels)
- return GST_FLOW_ERROR;
+ goto exit;
samples = (blocksize - 7 * dec->channels) * 2 + 2 * dec->channels;
outsize = 2 * samples;
outbuf = gst_buffer_new_and_alloc (outsize);
@@ -401,7 +357,7 @@ adpcmdec_decode_block (ADPCMDec * dec, const guint8 * data, int blocksize)
/* Each block has a 4 byte header per channel, include an initial sample.
Then the remainder gives two samples per byte */
if (blocksize < 4 * dec->channels)
- return GST_FLOW_ERROR;
+ goto exit;
samples = (blocksize - 4 * dec->channels) * 2 + dec->channels;
outsize = 2 * samples;
outbuf = gst_buffer_new_and_alloc (outsize);
@@ -410,155 +366,114 @@ adpcmdec_decode_block (ADPCMDec * dec, const guint8 * data, int blocksize)
(gint16 *) (GST_BUFFER_DATA (outbuf)));
} else {
GST_WARNING_OBJECT (dec, "Unknown layout");
- return GST_FLOW_ERROR;
}
if (!res) {
- gst_buffer_unref (outbuf);
+ if (outbuf)
+ gst_buffer_unref (outbuf);
+ outbuf = NULL;
GST_WARNING_OBJECT (dec, "Decode of block failed");
- return GST_FLOW_ERROR;
}
- gst_buffer_set_caps (outbuf, dec->output_caps);
- GST_BUFFER_TIMESTAMP (outbuf) = dec->timestamp;
- dec->out_samples += samples / dec->channels;
- dec->timestamp = dec->base_timestamp +
- gst_util_uint64_scale_int (dec->out_samples, GST_SECOND, dec->rate);
- GST_BUFFER_DURATION (outbuf) = dec->timestamp - GST_BUFFER_TIMESTAMP (outbuf);
-
- return gst_pad_push (dec->srcpad, outbuf);
+exit:
+ return outbuf;
}
static GstFlowReturn
-adpcmdec_chain (GstPad * pad, GstBuffer * buf)
+adpcmdec_parse (GstAudioDecoder * bdec, GstAdapter * adapter,
+ gint * offset, gint * length)
{
- ADPCMDec *dec = (ADPCMDec *) gst_pad_get_parent (pad);
- GstFlowReturn ret = GST_FLOW_OK;
- guint8 *data;
- GstBuffer *databuf = NULL;
+ ADPCMDec *dec = (ADPCMDec *) (bdec);
+ guint size;
- if (!dec->is_setup)
- adpcmdec_setup (dec);
+ size = gst_adapter_available (adapter);
+ g_return_val_if_fail (size > 0, GST_FLOW_ERROR);
- if (dec->base_timestamp == GST_CLOCK_TIME_NONE) {
- dec->base_timestamp = GST_BUFFER_TIMESTAMP (buf);
- if (dec->base_timestamp == GST_CLOCK_TIME_NONE)
- dec->base_timestamp = 0;
- dec->timestamp = dec->base_timestamp;
+ if (dec->blocksize < 0) {
+ /* No explicit blocksize; we just process one input buffer at a time */
+ *offset = 0;
+ *length = size;
+ } else {
+ if (size >= dec->blocksize) {
+ *offset = 0;
+ *length = dec->blocksize;
+ } else {
+ return GST_FLOW_UNEXPECTED;
+ }
}
- if (dec->blocksize > 0) {
- gst_adapter_push (dec->adapter, buf);
+ return GST_FLOW_OK;
+}
- while (gst_adapter_available (dec->adapter) >= dec->blocksize) {
- databuf = gst_adapter_take_buffer (dec->adapter, dec->blocksize);
- data = GST_BUFFER_DATA (databuf);
+static GstFlowReturn
+adpcmdec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buffer)
+{
+ ADPCMDec *dec = (ADPCMDec *) (bdec);
+ GstFlowReturn ret = GST_FLOW_OK;
+ guint8 *data;
+ GstBuffer *outbuf = NULL;
- ret = adpcmdec_decode_block (dec, data, dec->blocksize);
+ /* no fancy draining */
+ if (G_UNLIKELY (!buffer))
+ return GST_FLOW_OK;
- /* Done with input data, free it */
- gst_buffer_unref (databuf);
+ if (!dec->blocksize)
+ return GST_FLOW_NOT_NEGOTIATED;
- if (ret != GST_FLOW_OK)
- goto done;
- }
- } else {
- /* No explicit blocksize; we just process one input buffer at a time */
- ret = adpcmdec_decode_block (dec, GST_BUFFER_DATA (buf),
- GST_BUFFER_SIZE (buf));
- gst_buffer_unref (buf);
+ data = GST_BUFFER_DATA (buffer);
+ outbuf = adpcmdec_decode_block (dec, data, dec->blocksize);
+
+ if (outbuf == NULL) {
+ GST_AUDIO_DECODER_ERROR (bdec, 1, STREAM, DECODE, (NULL),
+ ("frame decode failed"), ret);
}
-done:
- gst_object_unref (dec);
+ if (ret == GST_FLOW_OK)
+ ret = gst_audio_decoder_finish_frame (bdec, outbuf, 1);
return ret;
}
static gboolean
-adpcmdec_sink_event (GstPad * pad, GstEvent * event)
+adpcmdec_start (GstAudioDecoder * bdec)
{
- ADPCMDec *dec = (ADPCMDec *) gst_pad_get_parent (pad);
- gboolean res;
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_STOP:
- dec->out_samples = 0;
- dec->timestamp = GST_CLOCK_TIME_NONE;
- dec->base_timestamp = GST_CLOCK_TIME_NONE;
- gst_adapter_clear (dec->adapter);
- /* Fall through */
- default:
- res = gst_pad_push_event (dec->srcpad, event);
- break;
- }
- gst_object_unref (dec);
- return res;
-}
+ ADPCMDec *dec = (ADPCMDec *) bdec;
-static GstStateChangeReturn
-adpcmdec_change_state (GstElement * element, GstStateChange transition)
-{
- GstStateChangeReturn ret;
- ADPCMDec *dec = (ADPCMDec *) element;
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- default:
- break;
- }
+ GST_DEBUG_OBJECT (dec, "start");
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- adpcmdec_teardown (dec);
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- break;
- default:
- break;
- }
- return ret;
+ dec->blocksize = 0;
+ dec->rate = 0;
+ dec->channels = 0;
+
+ return TRUE;
}
-static void
-adpcmdec_dispose (GObject * obj)
+static gboolean
+adpcmdec_stop (GstAudioDecoder * dec)
{
- G_OBJECT_CLASS (parent_class)->dispose (obj);
+ GST_DEBUG_OBJECT (dec, "stop");
+
+ return TRUE;
}
static void
adpcmdec_init (ADPCMDec * dec, ADPCMDecClass * klass)
{
- dec->sinkpad =
- gst_pad_new_from_static_template (&adpcmdec_sink_template, "sink");
- gst_pad_set_setcaps_function (dec->sinkpad,
- GST_DEBUG_FUNCPTR (adpcmdec_sink_setcaps));
- gst_pad_set_chain_function (dec->sinkpad, GST_DEBUG_FUNCPTR (adpcmdec_chain));
- gst_pad_set_event_function (dec->sinkpad,
- GST_DEBUG_FUNCPTR (adpcmdec_sink_event));
- gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
- dec->srcpad =
- gst_pad_new_from_static_template (&adpcmdec_src_template, "src");
- gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
}
static void
adpcmdec_class_init (ADPCMDecClass * klass)
{
- GObjectClass *gobjectclass = (GObjectClass *) klass;
- GstElementClass *gstelement_class = (GstElementClass *) klass;
- gobjectclass->dispose = adpcmdec_dispose;
- gstelement_class->change_state = adpcmdec_change_state;
-} static void
+ GstAudioDecoderClass *base_class = (GstAudioDecoderClass *) klass;
+
+ base_class->start = GST_DEBUG_FUNCPTR (adpcmdec_start);
+ base_class->stop = GST_DEBUG_FUNCPTR (adpcmdec_stop);
+ base_class->set_format = GST_DEBUG_FUNCPTR (adpcmdec_set_format);
+ base_class->parse = GST_DEBUG_FUNCPTR (adpcmdec_parse);
+ base_class->handle_frame = GST_DEBUG_FUNCPTR (adpcmdec_handle_frame);
+}
+static void
adpcmdec_base_init (gpointer klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
diff --git a/gst/adpcmenc/Makefile.am b/gst/adpcmenc/Makefile.am
index 17b3ecd28..bfd945d50 100644
--- a/gst/adpcmenc/Makefile.am
+++ b/gst/adpcmenc/Makefile.am
@@ -5,8 +5,9 @@ libgstadpcmenc_la_SOURCES = adpcmenc.c
# flags used to compile this plugin
# add other _CFLAGS and _LIBS as needed
-libgstadpcmenc_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS)
-libgstadpcmenc_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS)
+libgstadpcmenc_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
+libgstadpcmenc_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-@GST_MAJORMINOR@ \
+ $(GST_LIBS)
libgstadpcmenc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstadpcmenc_la_LIBTOOLFLAGS = --tag=disable-static
diff --git a/gst/adpcmenc/adpcmenc.c b/gst/adpcmenc/adpcmenc.c
index 5f6a24424..0761c5c1a 100644
--- a/gst/adpcmenc/adpcmenc.c
+++ b/gst/adpcmenc/adpcmenc.c
@@ -28,7 +28,7 @@
#endif
#include <gst/gst.h>
-#include <gst/base/gstadapter.h>
+#include <gst/audio/gstaudioencoder.h>
#define GST_TYPE_ADPCM_ENC \
(adpcmenc_get_type ())
@@ -113,17 +113,12 @@ adpcmenc_layout_get_type (void)
typedef struct _ADPCMEncClass
{
- GstElementClass parent_class;
+ GstAudioEncoderClass parent_class;
} ADPCMEncClass;
typedef struct _ADPCMEnc
{
- GstElement parent;
-
- GstPad *sinkpad;
- GstPad *srcpad;
-
- GstCaps *output_caps;
+ GstAudioEncoder parent;
enum adpcm_layout layout;
int rate;
@@ -133,19 +128,11 @@ typedef struct _ADPCMEnc
guint8 step_index[2];
- gboolean is_setup;
-
- GstClockTime timestamp;
- GstClockTime base_timestamp;
-
- guint64 out_samples;
-
- GstAdapter *adapter;
-
} ADPCMEnc;
GType adpcmenc_get_type (void);
-GST_BOILERPLATE (ADPCMEnc, adpcmenc, GstElement, GST_TYPE_ELEMENT);
+GST_BOILERPLATE (ADPCMEnc, adpcmenc, GstAudioEncoder, GST_TYPE_AUDIO_ENCODER);
+
static gboolean
adpcmenc_setup (ADPCMEnc * enc)
{
@@ -153,6 +140,7 @@ adpcmenc_setup (ADPCMEnc * enc)
const int ADPCM_SAMPLES_PER_BYTE = 2;
guint64 sample_bytes;
const char *layout;
+ GstCaps *caps;
switch (enc->layout) {
case LAYOUT_ADPCM_DVI:
@@ -168,21 +156,14 @@ adpcmenc_setup (ADPCMEnc * enc)
return FALSE;
}
- enc->output_caps = gst_caps_new_simple ("audio/x-adpcm",
+ caps = gst_caps_new_simple ("audio/x-adpcm",
"rate", G_TYPE_INT, enc->rate,
"channels", G_TYPE_INT, enc->channels,
"layout", G_TYPE_STRING, layout,
"block_align", G_TYPE_INT, enc->blocksize, NULL);
- if (enc->output_caps) {
- gst_pad_set_caps (enc->srcpad, enc->output_caps);
- }
-
- enc->is_setup = TRUE;
- enc->timestamp = GST_CLOCK_TIME_NONE;
- enc->base_timestamp = GST_CLOCK_TIME_NONE;
- enc->adapter = gst_adapter_new ();
- enc->out_samples = 0;
+ gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), caps);
+ gst_caps_unref (caps);
/* Step index state is carried between blocks. */
enc->step_index[0] = 0;
@@ -191,37 +172,21 @@ adpcmenc_setup (ADPCMEnc * enc)
return TRUE;
}
-static void
-adpcmenc_teardown (ADPCMEnc * enc)
-{
- if (enc->output_caps) {
- gst_caps_unref (enc->output_caps);
- enc->output_caps = NULL;
- }
- if (enc->adapter) {
- g_object_unref (enc->adapter);
- enc->adapter = NULL;
- }
- enc->is_setup = FALSE;
-}
-
static gboolean
-adpcmenc_sink_setcaps (GstPad * pad, GstCaps * caps)
+adpcmenc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
{
- ADPCMEnc *enc = (ADPCMEnc *) gst_pad_get_parent (pad);
- GstStructure *structure = gst_caps_get_structure (caps, 0);
+ ADPCMEnc *enc = (ADPCMEnc *) (benc);
- if (!gst_structure_get_int (structure, "rate", &enc->rate))
- return FALSE;
- if (!gst_structure_get_int (structure, "channels", &enc->channels))
- return FALSE;
+ enc->rate = GST_AUDIO_INFO_RATE (info);
+ enc->channels = GST_AUDIO_INFO_CHANNELS (info);
- if (enc->is_setup) {
- adpcmenc_teardown (enc);
- }
- adpcmenc_setup (enc);
+ if (!adpcmenc_setup (enc))
+ return FALSE;
- gst_object_unref (enc);
+ /* report needs to base class */
+ gst_audio_encoder_set_frame_samples_min (benc, enc->samples_per_block);
+ gst_audio_encoder_set_frame_samples_max (benc, enc->samples_per_block);
+ gst_audio_encoder_set_frame_max (benc, 1);
return TRUE;
}
@@ -368,148 +333,86 @@ adpcmenc_encode_ima_block (ADPCMEnc * enc, const gint16 * samples,
return TRUE;
}
-static GstFlowReturn
+static GstBuffer *
adpcmenc_encode_block (ADPCMEnc * enc, const gint16 * samples, int blocksize)
{
- gboolean res;
+ gboolean res = FALSE;
GstBuffer *outbuf = NULL;
if (enc->layout == LAYOUT_ADPCM_DVI) {
outbuf = gst_buffer_new_and_alloc (enc->blocksize);
res = adpcmenc_encode_ima_block (enc, samples, GST_BUFFER_DATA (outbuf));
} else {
+ /* should not happen afaics */
+ g_assert_not_reached ();
GST_WARNING_OBJECT (enc, "Unknown layout");
- return GST_FLOW_ERROR;
+ res = FALSE;
}
if (!res) {
- gst_buffer_unref (outbuf);
+ if (outbuf)
+ gst_buffer_unref (outbuf);
+ outbuf = NULL;
GST_WARNING_OBJECT (enc, "Encode of block failed");
- return GST_FLOW_ERROR;
}
- gst_buffer_set_caps (outbuf, enc->output_caps);
- GST_BUFFER_TIMESTAMP (outbuf) = enc->timestamp;
-
- enc->out_samples += enc->samples_per_block;
- enc->timestamp = enc->base_timestamp +
- gst_util_uint64_scale_int (enc->out_samples, GST_SECOND, enc->rate);
- GST_BUFFER_DURATION (outbuf) = enc->timestamp - GST_BUFFER_TIMESTAMP (outbuf);
-
- return gst_pad_push (enc->srcpad, outbuf);
+ return outbuf;
}
static GstFlowReturn
-adpcmenc_chain (GstPad * pad, GstBuffer * buf)
+adpcmenc_handle_frame (GstAudioEncoder * benc, GstBuffer * buffer)
{
- ADPCMEnc *enc = (ADPCMEnc *) gst_pad_get_parent (pad);
+ ADPCMEnc *enc = (ADPCMEnc *) (benc);
GstFlowReturn ret = GST_FLOW_OK;
gint16 *samples;
- GstBuffer *databuf = NULL;
+ GstBuffer *outbuf;
int input_bytes_per_block;
const int BYTES_PER_SAMPLE = 2;
- if (enc->base_timestamp == GST_CLOCK_TIME_NONE) {
- enc->base_timestamp = GST_BUFFER_TIMESTAMP (buf);
- if (enc->base_timestamp == GST_CLOCK_TIME_NONE)
- enc->base_timestamp = 0;
- enc->timestamp = enc->base_timestamp;
+ /* we don't deal with squeezing remnants, so simply discard those */
+ if (G_UNLIKELY (buffer == NULL)) {
+ GST_DEBUG_OBJECT (benc, "no data");
+ goto done;
}
- gst_adapter_push (enc->adapter, buf);
-
input_bytes_per_block =
enc->samples_per_block * BYTES_PER_SAMPLE * enc->channels;
- while (gst_adapter_available (enc->adapter) >= input_bytes_per_block) {
- databuf = gst_adapter_take_buffer (enc->adapter, input_bytes_per_block);
- samples = (gint16 *) GST_BUFFER_DATA (databuf);
- ret = adpcmenc_encode_block (enc, samples, enc->blocksize);
- gst_buffer_unref (databuf);
- if (ret != GST_FLOW_OK)
- goto done;
+ if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < input_bytes_per_block)) {
+ GST_DEBUG_OBJECT (enc, "discarding trailing data %d",
+ GST_BUFFER_SIZE (buffer));
+ ret = gst_audio_encoder_finish_frame (benc, NULL, -1);
+ goto done;
}
+ samples = (gint16 *) GST_BUFFER_DATA (buffer);
+ outbuf = adpcmenc_encode_block (enc, samples, enc->blocksize);
+
+ ret = gst_audio_encoder_finish_frame (benc, outbuf, enc->samples_per_block);
+
done:
- gst_object_unref (enc);
return ret;
}
static gboolean
-adpcmenc_sink_event (GstPad * pad, GstEvent * event)
+adpcmenc_start (GstAudioEncoder * enc)
{
- ADPCMEnc *enc = (ADPCMEnc *) gst_pad_get_parent (pad);
- gboolean res;
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_STOP:
- enc->out_samples = 0;
- enc->timestamp = GST_CLOCK_TIME_NONE;
- enc->base_timestamp = GST_CLOCK_TIME_NONE;
- gst_adapter_clear (enc->adapter);
- /* Fall through */
- default:
- res = gst_pad_push_event (enc->srcpad, event);
- break;
- }
- gst_object_unref (enc);
- return res;
-}
-
-static GstStateChangeReturn
-adpcmenc_change_state (GstElement * element, GstStateChange transition)
-{
- GstStateChangeReturn ret;
- ADPCMEnc *enc = (ADPCMEnc *) element;
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+ GST_DEBUG_OBJECT (enc, "start");
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- adpcmenc_teardown (enc);
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- break;
- default:
- break;
- }
- return ret;
+ return TRUE;
}
-static void
-adpcmenc_dispose (GObject * obj)
+static gboolean
+adpcmenc_stop (GstAudioEncoder * enc)
{
- G_OBJECT_CLASS (parent_class)->dispose (obj);
+ GST_DEBUG_OBJECT (enc, "stop");
+
+ return TRUE;
}
static void
adpcmenc_init (ADPCMEnc * enc, ADPCMEncClass * klass)
{
- enc->sinkpad =
- gst_pad_new_from_static_template (&adpcmenc_sink_template, "sink");
- gst_pad_set_setcaps_function (enc->sinkpad,
- GST_DEBUG_FUNCPTR (adpcmenc_sink_setcaps));
- gst_pad_set_chain_function (enc->sinkpad, GST_DEBUG_FUNCPTR (adpcmenc_chain));
- gst_pad_set_event_function (enc->sinkpad,
- GST_DEBUG_FUNCPTR (adpcmenc_sink_event));
- gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
-
- enc->srcpad =
- gst_pad_new_from_static_template (&adpcmenc_src_template, "src");
- gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
-
/* Set defaults. */
enc->blocksize = DEFAULT_ADPCM_BLOCK_SIZE;
enc->layout = DEFAULT_ADPCM_LAYOUT;
@@ -519,11 +422,16 @@ static void
adpcmenc_class_init (ADPCMEncClass * klass)
{
GObjectClass *gobjectclass = (GObjectClass *) klass;
- GstElementClass *gstelement_class = (GstElementClass *) klass;
+ GstAudioEncoderClass *base_class = (GstAudioEncoderClass *) klass;
gobjectclass->set_property = adpcmenc_set_property;
gobjectclass->get_property = adpcmenc_get_property;
+ base_class->start = GST_DEBUG_FUNCPTR (adpcmenc_start);
+ base_class->stop = GST_DEBUG_FUNCPTR (adpcmenc_stop);
+ base_class->set_format = GST_DEBUG_FUNCPTR (adpcmenc_set_format);
+ base_class->handle_frame = GST_DEBUG_FUNCPTR (adpcmenc_handle_frame);
+
g_object_class_install_property (gobjectclass, ARG_LAYOUT,
g_param_spec_enum ("layout", "Layout",
"Layout for output stream",
@@ -537,10 +445,9 @@ adpcmenc_class_init (ADPCMEncClass * klass)
DEFAULT_ADPCM_BLOCK_SIZE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- gobjectclass->dispose = adpcmenc_dispose;
- gstelement_class->change_state = adpcmenc_change_state;
-} static void
+}
+static void
adpcmenc_base_init (gpointer klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
diff --git a/gst/debugutils/gstdebugspy.c b/gst/debugutils/gstdebugspy.c
index 0c9e3300f..d9ecc3d2c 100644
--- a/gst/debugutils/gstdebugspy.c
+++ b/gst/debugutils/gstdebugspy.c
@@ -227,6 +227,8 @@ gst_debug_spy_transform_ip (GstBaseTransform * transform, GstBuffer * buf)
"size", G_TYPE_UINT, GST_BUFFER_SIZE (buf),
"caps", GST_TYPE_CAPS, GST_BUFFER_CAPS (buf), NULL);
+ g_free (checksum);
+
message =
gst_message_new_element (GST_OBJECT (transform), message_structure);
diff --git a/gst/festival/gstfestival.c b/gst/festival/gstfestival.c
index 6423bf5b9..3c9e0949c 100644
--- a/gst/festival/gstfestival.c
+++ b/gst/festival/gstfestival.c
@@ -297,22 +297,29 @@ gst_festival_chain (GstPad * pad, GstBuffer * buf)
GstFlowReturn ret = GST_FLOW_OK;
GstFestival *festival;
guint8 *p, *ep;
+ gint f;
FILE *fd;
festival = GST_FESTIVAL (GST_PAD_PARENT (pad));
GST_LOG_OBJECT (festival, "Got text buffer, %u bytes", GST_BUFFER_SIZE (buf));
- fd = fdopen (dup (festival->info->server_fd), "wb");
+ f = dup (festival->info->server_fd);
+ if (f < 0)
+ goto fail_open;
+ fd = fdopen (f, "wb");
+ if (fd == NULL) {
+ close (f);
+ goto fail_open;
+ }
/* Copy text over to server, escaping any quotes */
fprintf (fd, "(Parameter.set 'Audio_Required_Rate 16000)\n");
fflush (fd);
GST_DEBUG_OBJECT (festival, "issued Parameter.set command");
if (read_response (festival) == FALSE) {
- ret = GST_FLOW_ERROR;
fclose (fd);
- goto out;
+ goto fail_read;
}
fprintf (fd, "(tts_textall \"");
@@ -332,11 +339,25 @@ gst_festival_chain (GstPad * pad, GstBuffer * buf)
/* Read back info from server */
if (read_response (festival) == FALSE)
- ret = GST_FLOW_ERROR;
+ goto fail_read;
out:
gst_buffer_unref (buf);
return ret;
+
+ /* ERRORS */
+fail_open:
+ {
+ GST_ELEMENT_ERROR (festival, RESOURCE, OPEN_WRITE, (NULL), (NULL));
+ ret = GST_FLOW_ERROR;
+ goto out;
+ }
+fail_read:
+ {
+ GST_ELEMENT_ERROR (festival, RESOURCE, READ, (NULL), (NULL));
+ ret = GST_FLOW_ERROR;
+ goto out;
+ }
}
static FT_Info *
diff --git a/gst/inter/Makefile.am b/gst/inter/Makefile.am
index 4a7e78aea..7728de991 100644
--- a/gst/inter/Makefile.am
+++ b/gst/inter/Makefile.am
@@ -5,6 +5,8 @@ noinst_PROGRAMS = gstintertest
libgstinter_la_SOURCES = \
gstinteraudiosink.c \
gstinteraudiosrc.c \
+ gstintersubsink.c \
+ gstintersubsrc.c \
gstintervideosink.c \
gstintervideosrc.c \
gstinter.c \
@@ -13,6 +15,8 @@ libgstinter_la_SOURCES = \
noinst_HEADERS = \
gstinteraudiosink.h \
gstinteraudiosrc.h \
+ gstintersubsink.h \
+ gstintersubsrc.h \
gstintervideosink.h \
gstintervideosrc.h \
gstintersurface.h
diff --git a/gst/inter/gstinter.c b/gst/inter/gstinter.c
index 60c5bd6a7..8a7786dbc 100644
--- a/gst/inter/gstinter.c
+++ b/gst/inter/gstinter.c
@@ -1,5 +1,5 @@
/* GStreamer
- * Copyright (C) 2011 David A. Schleef <ds@schleef.org>
+ * Copyright (C) 2011 David Schleef <ds@entropywave.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -23,6 +23,8 @@
#include "gstinteraudiosrc.h"
#include "gstinteraudiosink.h"
+#include "gstintersubsrc.h"
+#include "gstintersubsink.h"
#include "gstintervideosrc.h"
#include "gstintervideosink.h"
#include "gstintersurface.h"
@@ -34,13 +36,15 @@ plugin_init (GstPlugin * plugin)
GST_TYPE_INTER_AUDIO_SRC);
gst_element_register (plugin, "interaudiosink", GST_RANK_NONE,
GST_TYPE_INTER_AUDIO_SINK);
+ gst_element_register (plugin, "intersubsrc", GST_RANK_NONE,
+ GST_TYPE_INTER_SUB_SRC);
+ gst_element_register (plugin, "intersubsink", GST_RANK_NONE,
+ GST_TYPE_INTER_SUB_SINK);
gst_element_register (plugin, "intervideosrc", GST_RANK_NONE,
GST_TYPE_INTER_VIDEO_SRC);
gst_element_register (plugin, "intervideosink", GST_RANK_NONE,
GST_TYPE_INTER_VIDEO_SINK);
- gst_inter_surface_init ();
-
return TRUE;
}
diff --git a/gst/inter/gstinteraudiosink.c b/gst/inter/gstinteraudiosink.c
index 1309fbc9e..e5ba92687 100644
--- a/gst/inter/gstinteraudiosink.c
+++ b/gst/inter/gstinteraudiosink.c
@@ -77,7 +77,8 @@ static gboolean gst_inter_audio_sink_unlock_stop (GstBaseSink * sink);
enum
{
- PROP_0
+ PROP_0,
+ PROP_CHANNEL
};
/* pad templates */
@@ -150,6 +151,10 @@ gst_inter_audio_sink_class_init (GstInterAudioSinkClass * klass)
base_sink_class->unlock_stop =
GST_DEBUG_FUNCPTR (gst_inter_audio_sink_unlock_stop);
+ g_object_class_install_property (gobject_class, PROP_CHANNEL,
+ g_param_spec_string ("channel", "Channel",
+ "Channel name to match inter src and sink elements",
+ "default", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static void
diff --git a/gst/inter/gstinteraudiosrc.c b/gst/inter/gstinteraudiosrc.c
index 11b8839e1..e659bf024 100644
--- a/gst/inter/gstinteraudiosrc.c
+++ b/gst/inter/gstinteraudiosrc.c
@@ -79,7 +79,8 @@ gst_inter_audio_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * seek,
enum
{
- PROP_0
+ PROP_0,
+ PROP_CHANNEL
};
/* pad templates */
@@ -158,6 +159,10 @@ gst_inter_audio_src_class_init (GstInterAudioSrcClass * klass)
base_src_class->prepare_seek_segment =
GST_DEBUG_FUNCPTR (gst_inter_audio_src_prepare_seek_segment);
+ g_object_class_install_property (gobject_class, PROP_CHANNEL,
+ g_param_spec_string ("channel", "Channel",
+ "Channel name to match inter src and sink elements",
+ "default", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
diff --git a/gst/inter/gstintersubsink.c b/gst/inter/gstintersubsink.c
new file mode 100644
index 000000000..1328b18a5
--- /dev/null
+++ b/gst/inter/gstintersubsink.c
@@ -0,0 +1,325 @@
+/* GStreamer
+ * Copyright (C) 2011 David Schleef <ds@entropywave.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., 51 Franklin Street, Suite 500,
+ * Boston, MA 02110-1335, USA.
+ */
+/**
+ * SECTION:element-gstintersubsink
+ *
+ * The intersubsink element does FIXME stuff.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v fakesrc ! intersubsink ! FIXME ! fakesink
+ * ]|
+ * FIXME Describe what the pipeline does.
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstbasesink.h>
+#include "gstintersubsink.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_inter_sub_sink_debug_category);
+#define GST_CAT_DEFAULT gst_inter_sub_sink_debug_category
+
+/* prototypes */
+
+
+static void gst_inter_sub_sink_set_property (GObject * object,
+ guint property_id, const GValue * value, GParamSpec * pspec);
+static void gst_inter_sub_sink_get_property (GObject * object,
+ guint property_id, GValue * value, GParamSpec * pspec);
+static void gst_inter_sub_sink_dispose (GObject * object);
+static void gst_inter_sub_sink_finalize (GObject * object);
+
+static GstCaps *gst_inter_sub_sink_get_caps (GstBaseSink * sink);
+static gboolean gst_inter_sub_sink_set_caps (GstBaseSink * sink,
+ GstCaps * caps);
+static GstFlowReturn gst_inter_sub_sink_buffer_alloc (GstBaseSink * sink,
+ guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
+static void gst_inter_sub_sink_get_times (GstBaseSink * sink,
+ GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
+static gboolean gst_inter_sub_sink_start (GstBaseSink * sink);
+static gboolean gst_inter_sub_sink_stop (GstBaseSink * sink);
+static gboolean gst_inter_sub_sink_unlock (GstBaseSink * sink);
+static gboolean gst_inter_sub_sink_event (GstBaseSink * sink, GstEvent * event);
+static GstFlowReturn
+gst_inter_sub_sink_preroll (GstBaseSink * sink, GstBuffer * buffer);
+static GstFlowReturn
+gst_inter_sub_sink_render (GstBaseSink * sink, GstBuffer * buffer);
+static GstStateChangeReturn gst_inter_sub_sink_async_play (GstBaseSink * sink);
+static gboolean gst_inter_sub_sink_activate_pull (GstBaseSink * sink,
+ gboolean active);
+static gboolean gst_inter_sub_sink_unlock_stop (GstBaseSink * sink);
+
+enum
+{
+ PROP_0
+};
+
+/* pad templates */
+
+static GstStaticPadTemplate gst_inter_sub_sink_sink_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("text/plain")
+ );
+
+
+/* class initialization */
+
+#define DEBUG_INIT(bla) \
+ GST_DEBUG_CATEGORY_INIT (gst_inter_sub_sink_debug_category, "intersubsink", 0, \
+ "debug category for intersubsink element");
+
+GST_BOILERPLATE_FULL (GstInterSubSink, gst_inter_sub_sink, GstBaseSink,
+ GST_TYPE_BASE_SINK, DEBUG_INIT);
+
+static void
+gst_inter_sub_sink_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_inter_sub_sink_sink_template));
+
+ gst_element_class_set_details_simple (element_class, "FIXME Long name",
+ "Generic", "FIXME Description", "FIXME <fixme@example.com>");
+}
+
+static void
+gst_inter_sub_sink_class_init (GstInterSubSinkClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstBaseSinkClass *base_sink_class = GST_BASE_SINK_CLASS (klass);
+
+ gobject_class->set_property = gst_inter_sub_sink_set_property;
+ gobject_class->get_property = gst_inter_sub_sink_get_property;
+ gobject_class->dispose = gst_inter_sub_sink_dispose;
+ gobject_class->finalize = gst_inter_sub_sink_finalize;
+ base_sink_class->get_caps = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_get_caps);
+ base_sink_class->set_caps = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_set_caps);
+ if (0)
+ base_sink_class->buffer_alloc =
+ GST_DEBUG_FUNCPTR (gst_inter_sub_sink_buffer_alloc);
+ base_sink_class->get_times = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_get_times);
+ base_sink_class->start = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_start);
+ base_sink_class->stop = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_stop);
+ base_sink_class->unlock = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_unlock);
+ if (0)
+ base_sink_class->event = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_event);
+ base_sink_class->preroll = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_preroll);
+ base_sink_class->render = GST_DEBUG_FUNCPTR (gst_inter_sub_sink_render);
+ if (0)
+ base_sink_class->async_play =
+ GST_DEBUG_FUNCPTR (gst_inter_sub_sink_async_play);
+ if (0)
+ base_sink_class->activate_pull =
+ GST_DEBUG_FUNCPTR (gst_inter_sub_sink_activate_pull);
+ base_sink_class->unlock_stop =
+ GST_DEBUG_FUNCPTR (gst_inter_sub_sink_unlock_stop);
+
+}
+
+static void
+gst_inter_sub_sink_init (GstInterSubSink * intersubsink,
+ GstInterSubSinkClass * intersubsink_class)
+{
+
+ intersubsink->surface = gst_inter_surface_get ("default");
+
+ intersubsink->fps_n = 1;
+ intersubsink->fps_d = 1;
+}
+
+void
+gst_inter_sub_sink_set_property (GObject * object, guint property_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ /* GstInterSubSink *intersubsink = GST_INTER_SUB_SINK (object); */
+
+ switch (property_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+void
+gst_inter_sub_sink_get_property (GObject * object, guint property_id,
+ GValue * value, GParamSpec * pspec)
+{
+ /* GstInterSubSink *intersubsink = GST_INTER_SUB_SINK (object); */
+
+ switch (property_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+void
+gst_inter_sub_sink_dispose (GObject * object)
+{
+ /* GstInterSubSink *intersubsink = GST_INTER_SUB_SINK (object); */
+
+ /* clean up as possible. may be called multiple times */
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+void
+gst_inter_sub_sink_finalize (GObject * object)
+{
+ /* GstInterSubSink *intersubsink = GST_INTER_SUB_SINK (object); */
+
+ /* clean up object here */
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+
+static GstCaps *
+gst_inter_sub_sink_get_caps (GstBaseSink * sink)
+{
+
+ return NULL;
+}
+
+static gboolean
+gst_inter_sub_sink_set_caps (GstBaseSink * sink, GstCaps * caps)
+{
+
+ return FALSE;
+}
+
+static GstFlowReturn
+gst_inter_sub_sink_buffer_alloc (GstBaseSink * sink, guint64 offset, guint size,
+ GstCaps * caps, GstBuffer ** buf)
+{
+
+ return GST_FLOW_ERROR;
+}
+
+static void
+gst_inter_sub_sink_get_times (GstBaseSink * sink, GstBuffer * buffer,
+ GstClockTime * start, GstClockTime * end)
+{
+ GstInterSubSink *intersubsink = GST_INTER_SUB_SINK (sink);
+
+ if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) {
+ *start = GST_BUFFER_TIMESTAMP (buffer);
+ if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
+ *end = *start + GST_BUFFER_DURATION (buffer);
+ } else {
+ if (intersubsink->fps_n > 0) {
+ *end = *start +
+ gst_util_uint64_scale_int (GST_SECOND, intersubsink->fps_d,
+ intersubsink->fps_n);
+ }
+ }
+ }
+
+
+}
+
+static gboolean
+gst_inter_sub_sink_start (GstBaseSink * sink)
+{
+
+ return TRUE;
+}
+
+static gboolean
+gst_inter_sub_sink_stop (GstBaseSink * sink)
+{
+ GstInterSubSink *intersubsink = GST_INTER_SUB_SINK (sink);
+
+ g_mutex_lock (intersubsink->surface->mutex);
+ if (intersubsink->surface->sub_buffer) {
+ gst_buffer_unref (intersubsink->surface->sub_buffer);
+ }
+ intersubsink->surface->sub_buffer = NULL;
+ g_mutex_unlock (intersubsink->surface->mutex);
+
+ return TRUE;
+}
+
+static gboolean
+gst_inter_sub_sink_unlock (GstBaseSink * sink)
+{
+
+ return TRUE;
+}
+
+static gboolean
+gst_inter_sub_sink_event (GstBaseSink * sink, GstEvent * event)
+{
+
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_inter_sub_sink_preroll (GstBaseSink * sink, GstBuffer * buffer)
+{
+
+ return GST_FLOW_OK;
+}
+
+static GstFlowReturn
+gst_inter_sub_sink_render (GstBaseSink * sink, GstBuffer * buffer)
+{
+ GstInterSubSink *intersubsink = GST_INTER_SUB_SINK (sink);
+
+ g_mutex_lock (intersubsink->surface->mutex);
+ if (intersubsink->surface->sub_buffer) {
+ gst_buffer_unref (intersubsink->surface->sub_buffer);
+ }
+ intersubsink->surface->sub_buffer = gst_buffer_ref (buffer);
+ //intersubsink->surface->sub_buffer_count = 0;
+ g_mutex_unlock (intersubsink->surface->mutex);
+
+ return GST_FLOW_OK;
+}
+
+static GstStateChangeReturn
+gst_inter_sub_sink_async_play (GstBaseSink * sink)
+{
+
+ return GST_STATE_CHANGE_SUCCESS;
+}
+
+static gboolean
+gst_inter_sub_sink_activate_pull (GstBaseSink * sink, gboolean active)
+{
+
+ return TRUE;
+}
+
+static gboolean
+gst_inter_sub_sink_unlock_stop (GstBaseSink * sink)
+{
+
+ return TRUE;
+}
diff --git a/gst/inter/gstintersubsink.h b/gst/inter/gstintersubsink.h
new file mode 100644
index 000000000..be2da9b3b
--- /dev/null
+++ b/gst/inter/gstintersubsink.h
@@ -0,0 +1,57 @@
+/* GStreamer
+ * Copyright (C) 2011 David Schleef <ds@entropywave.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.
+ */
+
+#ifndef _GST_INTER_SUB_SINK_H_
+#define _GST_INTER_SUB_SINK_H_
+
+#include <gst/base/gstbasesink.h>
+#include "gstintersurface.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_INTER_SUB_SINK (gst_inter_sub_sink_get_type())
+#define GST_INTER_SUB_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_INTER_SUB_SINK,GstInterSubSink))
+#define GST_INTER_SUB_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_INTER_SUB_SINK,GstInterSubSinkClass))
+#define GST_IS_INTER_SUB_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_INTER_SUB_SINK))
+#define GST_IS_INTER_SUB_SINK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_INTER_SUB_SINK))
+
+typedef struct _GstInterSubSink GstInterSubSink;
+typedef struct _GstInterSubSinkClass GstInterSubSinkClass;
+
+struct _GstInterSubSink
+{
+ GstBaseSink base_intersubsink;
+
+ GstPad *sinkpad;
+ GstInterSurface *surface;
+
+ int fps_n;
+ int fps_d;
+};
+
+struct _GstInterSubSinkClass
+{
+ GstBaseSinkClass base_intersubsink_class;
+};
+
+GType gst_inter_sub_sink_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/gst/inter/gstintersubsrc.c b/gst/inter/gstintersubsrc.c
new file mode 100644
index 000000000..60a29b3d7
--- /dev/null
+++ b/gst/inter/gstintersubsrc.c
@@ -0,0 +1,455 @@
+/* GStreamer
+ * Copyright (C) 2011 David Schleef <ds@entropywave.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., 51 Franklin Street, Suite 500,
+ * Boston, MA 02110-1335, USA.
+ */
+/**
+ * SECTION:element-gstintersubsrc
+ *
+ * The intersubsrc element is a subtitle source element. It is used
+ * in connection with a intersubsink element in a different pipeline,
+ * similar to interaudiosink and interaudiosrc.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v intersubsrc ! kateenc ! oggmux ! filesink location=out.ogv
+ * ]|
+ *
+ * The intersubsrc element cannot be used effectively with gst-launch,
+ * as it requires a second pipeline in the application to send subtitles.
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/base/gstbasesrc.h>
+#include "gstintersubsrc.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_inter_sub_src_debug_category);
+#define GST_CAT_DEFAULT gst_inter_sub_src_debug_category
+
+/* prototypes */
+
+
+static void gst_inter_sub_src_set_property (GObject * object,
+ guint property_id, const GValue * value, GParamSpec * pspec);
+static void gst_inter_sub_src_get_property (GObject * object,
+ guint property_id, GValue * value, GParamSpec * pspec);
+static void gst_inter_sub_src_dispose (GObject * object);
+static void gst_inter_sub_src_finalize (GObject * object);
+
+static GstCaps *gst_inter_sub_src_get_caps (GstBaseSrc * src);
+static gboolean gst_inter_sub_src_set_caps (GstBaseSrc * src, GstCaps * caps);
+static gboolean gst_inter_sub_src_negotiate (GstBaseSrc * src);
+static gboolean gst_inter_sub_src_newsegment (GstBaseSrc * src);
+static gboolean gst_inter_sub_src_start (GstBaseSrc * src);
+static gboolean gst_inter_sub_src_stop (GstBaseSrc * src);
+static void
+gst_inter_sub_src_get_times (GstBaseSrc * src, GstBuffer * buffer,
+ GstClockTime * start, GstClockTime * end);
+static gboolean gst_inter_sub_src_is_seekable (GstBaseSrc * src);
+static gboolean gst_inter_sub_src_unlock (GstBaseSrc * src);
+static gboolean gst_inter_sub_src_event (GstBaseSrc * src, GstEvent * event);
+static GstFlowReturn
+gst_inter_sub_src_create (GstBaseSrc * src, guint64 offset, guint size,
+ GstBuffer ** buf);
+static gboolean gst_inter_sub_src_do_seek (GstBaseSrc * src,
+ GstSegment * segment);
+static gboolean gst_inter_sub_src_query (GstBaseSrc * src, GstQuery * query);
+static gboolean gst_inter_sub_src_check_get_range (GstBaseSrc * src);
+static void gst_inter_sub_src_fixate (GstBaseSrc * src, GstCaps * caps);
+static gboolean gst_inter_sub_src_unlock_stop (GstBaseSrc * src);
+static gboolean
+gst_inter_sub_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * seek,
+ GstSegment * segment);
+
+enum
+{
+ PROP_0
+};
+
+/* pad templates */
+
+static GstStaticPadTemplate gst_inter_sub_src_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("application/unknown")
+ );
+
+
+/* class initialization */
+
+#define DEBUG_INIT(bla) \
+ GST_DEBUG_CATEGORY_INIT (gst_inter_sub_src_debug_category, "intersubsrc", 0, \
+ "debug category for intersubsrc element");
+
+GST_BOILERPLATE_FULL (GstInterSubSrc, gst_inter_sub_src, GstBaseSrc,
+ GST_TYPE_BASE_SRC, DEBUG_INIT);
+
+static void
+gst_inter_sub_src_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_inter_sub_src_src_template));
+
+ gst_element_class_set_details_simple (element_class,
+ "Inter-pipeline subtitle source",
+ "Source/Subtitle", "Inter-pipeline subtitle source",
+ "David Schleef <ds@entropywave.com>");
+}
+
+static void
+gst_inter_sub_src_class_init (GstInterSubSrcClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstBaseSrcClass *base_src_class = GST_BASE_SRC_CLASS (klass);
+
+ gobject_class->set_property = gst_inter_sub_src_set_property;
+ gobject_class->get_property = gst_inter_sub_src_get_property;
+ gobject_class->dispose = gst_inter_sub_src_dispose;
+ gobject_class->finalize = gst_inter_sub_src_finalize;
+ if (0)
+ base_src_class->get_caps = GST_DEBUG_FUNCPTR (gst_inter_sub_src_get_caps);
+ base_src_class->set_caps = GST_DEBUG_FUNCPTR (gst_inter_sub_src_set_caps);
+ if (0)
+ base_src_class->negotiate = GST_DEBUG_FUNCPTR (gst_inter_sub_src_negotiate);
+ if (0)
+ base_src_class->newsegment =
+ GST_DEBUG_FUNCPTR (gst_inter_sub_src_newsegment);
+ base_src_class->start = GST_DEBUG_FUNCPTR (gst_inter_sub_src_start);
+ base_src_class->stop = GST_DEBUG_FUNCPTR (gst_inter_sub_src_stop);
+ base_src_class->get_times = GST_DEBUG_FUNCPTR (gst_inter_sub_src_get_times);
+ if (0)
+ base_src_class->is_seekable =
+ GST_DEBUG_FUNCPTR (gst_inter_sub_src_is_seekable);
+ base_src_class->unlock = GST_DEBUG_FUNCPTR (gst_inter_sub_src_unlock);
+ base_src_class->event = GST_DEBUG_FUNCPTR (gst_inter_sub_src_event);
+ base_src_class->create = GST_DEBUG_FUNCPTR (gst_inter_sub_src_create);
+ if (0)
+ base_src_class->do_seek = GST_DEBUG_FUNCPTR (gst_inter_sub_src_do_seek);
+ base_src_class->query = GST_DEBUG_FUNCPTR (gst_inter_sub_src_query);
+ if (0)
+ base_src_class->check_get_range =
+ GST_DEBUG_FUNCPTR (gst_inter_sub_src_check_get_range);
+ base_src_class->fixate = GST_DEBUG_FUNCPTR (gst_inter_sub_src_fixate);
+ if (0)
+ base_src_class->unlock_stop =
+ GST_DEBUG_FUNCPTR (gst_inter_sub_src_unlock_stop);
+ if (0)
+ base_src_class->prepare_seek_segment =
+ GST_DEBUG_FUNCPTR (gst_inter_sub_src_prepare_seek_segment);
+
+
+}
+
+static void
+gst_inter_sub_src_init (GstInterSubSrc * intersubsrc,
+ GstInterSubSrcClass * intersubsrc_class)
+{
+
+ intersubsrc->srcpad =
+ gst_pad_new_from_static_template (&gst_inter_sub_src_src_template, "src");
+
+ gst_base_src_set_format (GST_BASE_SRC (intersubsrc), GST_FORMAT_TIME);
+ gst_base_src_set_live (GST_BASE_SRC (intersubsrc), TRUE);
+
+ intersubsrc->surface = gst_inter_surface_get ("default");
+}
+
+void
+gst_inter_sub_src_set_property (GObject * object, guint property_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ /* GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (object); */
+
+ switch (property_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+void
+gst_inter_sub_src_get_property (GObject * object, guint property_id,
+ GValue * value, GParamSpec * pspec)
+{
+ /* GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (object); */
+
+ switch (property_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+void
+gst_inter_sub_src_dispose (GObject * object)
+{
+ /* GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (object); */
+
+ /* clean up as possible. may be called multiple times */
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+void
+gst_inter_sub_src_finalize (GObject * object)
+{
+ /* GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (object); */
+
+ /* clean up object here */
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static GstCaps *
+gst_inter_sub_src_get_caps (GstBaseSrc * src)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "get_caps");
+
+ return NULL;
+}
+
+static gboolean
+gst_inter_sub_src_set_caps (GstBaseSrc * src, GstCaps * caps)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "set_caps");
+
+ return TRUE;
+}
+
+static gboolean
+gst_inter_sub_src_negotiate (GstBaseSrc * src)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "negotiate");
+
+ return TRUE;
+}
+
+static gboolean
+gst_inter_sub_src_newsegment (GstBaseSrc * src)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "newsegment");
+
+ return TRUE;
+}
+
+static gboolean
+gst_inter_sub_src_start (GstBaseSrc * src)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "start");
+
+ return TRUE;
+}
+
+static gboolean
+gst_inter_sub_src_stop (GstBaseSrc * src)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "stop");
+
+ return TRUE;
+}
+
+static void
+gst_inter_sub_src_get_times (GstBaseSrc * src, GstBuffer * buffer,
+ GstClockTime * start, GstClockTime * end)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "get_times");
+
+ /* for live sources, sync on the timestamp of the buffer */
+ if (gst_base_src_is_live (src)) {
+ GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
+
+ if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+ /* get duration to calculate end time */
+ GstClockTime duration = GST_BUFFER_DURATION (buffer);
+
+ if (GST_CLOCK_TIME_IS_VALID (duration)) {
+ *end = timestamp + duration;
+ }
+ *start = timestamp;
+ }
+ } else {
+ *start = -1;
+ *end = -1;
+ }
+}
+
+static gboolean
+gst_inter_sub_src_is_seekable (GstBaseSrc * src)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "is_seekable");
+
+ return FALSE;
+}
+
+static gboolean
+gst_inter_sub_src_unlock (GstBaseSrc * src)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "unlock");
+
+ return TRUE;
+}
+
+static gboolean
+gst_inter_sub_src_event (GstBaseSrc * src, GstEvent * event)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "event");
+
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_inter_sub_src_create (GstBaseSrc * src, guint64 offset, guint size,
+ GstBuffer ** buf)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+ GstBuffer *buffer;
+
+ GST_DEBUG_OBJECT (intersubsrc, "create");
+
+ buffer = NULL;
+
+ g_mutex_lock (intersubsrc->surface->mutex);
+ if (intersubsrc->surface->sub_buffer) {
+ buffer = gst_buffer_ref (intersubsrc->surface->sub_buffer);
+ //intersubsrc->surface->sub_buffer_count++;
+ //if (intersubsrc->surface->sub_buffer_count >= 30) {
+ gst_buffer_unref (intersubsrc->surface->sub_buffer);
+ intersubsrc->surface->sub_buffer = NULL;
+ //}
+ }
+ g_mutex_unlock (intersubsrc->surface->mutex);
+
+ if (buffer == NULL) {
+ guint8 *data;
+
+ buffer = gst_buffer_new_and_alloc (1);
+
+ data = GST_BUFFER_DATA (buffer);
+ data[0] = 0;
+ }
+
+ buffer = gst_buffer_make_metadata_writable (buffer);
+
+ GST_BUFFER_TIMESTAMP (buffer) =
+ gst_util_uint64_scale_int (GST_SECOND, intersubsrc->n_frames,
+ intersubsrc->rate);
+ GST_DEBUG_OBJECT (intersubsrc, "create ts %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
+ GST_BUFFER_DURATION (buffer) =
+ gst_util_uint64_scale_int (GST_SECOND, (intersubsrc->n_frames + 1),
+ intersubsrc->rate) - GST_BUFFER_TIMESTAMP (buffer);
+ GST_BUFFER_OFFSET (buffer) = intersubsrc->n_frames;
+ GST_BUFFER_OFFSET_END (buffer) = -1;
+ GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DISCONT);
+ if (intersubsrc->n_frames == 0) {
+ GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
+ }
+ gst_buffer_set_caps (buffer, GST_PAD_CAPS (GST_BASE_SRC_PAD (intersubsrc)));
+ intersubsrc->n_frames++;
+
+ *buf = buffer;
+
+ return GST_FLOW_OK;
+}
+
+static gboolean
+gst_inter_sub_src_do_seek (GstBaseSrc * src, GstSegment * segment)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "do_seek");
+
+ return FALSE;
+}
+
+static gboolean
+gst_inter_sub_src_query (GstBaseSrc * src, GstQuery * query)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "query");
+
+ return TRUE;
+}
+
+static gboolean
+gst_inter_sub_src_check_get_range (GstBaseSrc * src)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "get_range");
+
+ return FALSE;
+}
+
+static void
+gst_inter_sub_src_fixate (GstBaseSrc * src, GstCaps * caps)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "fixate");
+}
+
+static gboolean
+gst_inter_sub_src_unlock_stop (GstBaseSrc * src)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "stop");
+
+ return TRUE;
+}
+
+static gboolean
+gst_inter_sub_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * seek,
+ GstSegment * segment)
+{
+ GstInterSubSrc *intersubsrc = GST_INTER_SUB_SRC (src);
+
+ GST_DEBUG_OBJECT (intersubsrc, "seek_segment");
+
+ return FALSE;
+}
diff --git a/gst/inter/gstintersubsrc.h b/gst/inter/gstintersubsrc.h
new file mode 100644
index 000000000..74bfed1e7
--- /dev/null
+++ b/gst/inter/gstintersubsrc.h
@@ -0,0 +1,57 @@
+/* GStreamer
+ * Copyright (C) 2011 David Schleef <ds@entropywave.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.
+ */
+
+#ifndef _GST_INTER_SUB_SRC_H_
+#define _GST_INTER_SUB_SRC_H_
+
+#include <gst/base/gstbasesrc.h>
+#include "gstintersurface.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_INTER_SUB_SRC (gst_inter_sub_src_get_type())
+#define GST_INTER_SUB_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_INTER_SUB_SRC,GstInterSubSrc))
+#define GST_INTER_SUB_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_INTER_SUB_SRC,GstInterSubSrcClass))
+#define GST_IS_INTER_SUB_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_INTER_SUB_SRC))
+#define GST_IS_INTER_SUB_SRC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_INTER_SUB_SRC))
+
+typedef struct _GstInterSubSrc GstInterSubSrc;
+typedef struct _GstInterSubSrcClass GstInterSubSrcClass;
+
+struct _GstInterSubSrc
+{
+ GstBaseSrc base_intersubsrc;
+
+ GstPad *srcpad;
+ GstInterSurface *surface;
+
+ int rate;
+ int n_frames;
+};
+
+struct _GstInterSubSrcClass
+{
+ GstBaseSrcClass base_intersubsrc_class;
+};
+
+GType gst_inter_sub_src_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/gst/inter/gstintersurface.c b/gst/inter/gstintersurface.c
index 545cd6ffa..1d23e5de1 100644
--- a/gst/inter/gstintersurface.c
+++ b/gst/inter/gstintersurface.c
@@ -21,22 +21,43 @@
#include "config.h"
#endif
+#include <string.h>
+
#include "gstintersurface.h"
-static GstInterSurface *surface;
+static GList *list;
+static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
GstInterSurface *
gst_inter_surface_get (const char *name)
{
- return surface;
+ GList *g;
+ GstInterSurface *surface;
-}
+ g_static_mutex_lock (&mutex);
+
+ for (g = list; g; g = g_list_next (g)) {
+ surface = (GstInterSurface *) g->data;
+ if (strcmp (name, surface->name) == 0) {
+ g_static_mutex_unlock (&mutex);
+ return surface;
+ }
+ }
-void
-gst_inter_surface_init (void)
-{
surface = g_malloc0 (sizeof (GstInterSurface));
+ surface->name = g_strdup (name);
surface->mutex = g_mutex_new ();
surface->audio_adapter = gst_adapter_new ();
+
+ list = g_list_append (list, surface);
+ g_static_mutex_unlock (&mutex);
+
+ return surface;
+}
+
+void
+gst_inter_surface_unref (GstInterSurface * surface)
+{
+
}
diff --git a/gst/inter/gstintersurface.h b/gst/inter/gstintersurface.h
index 92440448a..d8ba11f4c 100644
--- a/gst/inter/gstintersurface.h
+++ b/gst/inter/gstintersurface.h
@@ -30,6 +30,7 @@ typedef struct _GstInterSurface GstInterSurface;
struct _GstInterSurface
{
GMutex *mutex;
+ char *name;
/* video */
GstVideoFormat format;
@@ -45,12 +46,13 @@ struct _GstInterSurface
int n_channels;
GstBuffer *video_buffer;
+ GstBuffer *sub_buffer;
GstAdapter *audio_adapter;
};
GstInterSurface * gst_inter_surface_get (const char *name);
-void gst_inter_surface_init (void);
+void gst_inter_surface_unref (GstInterSurface *surface);
G_END_DECLS
diff --git a/gst/inter/gstintervideosink.c b/gst/inter/gstintervideosink.c
index 9e1d782e5..b6be4e99a 100644
--- a/gst/inter/gstintervideosink.c
+++ b/gst/inter/gstintervideosink.c
@@ -76,7 +76,8 @@ static gboolean gst_inter_video_sink_unlock_stop (GstBaseSink * sink);
enum
{
- PROP_0
+ PROP_0,
+ PROP_CHANNEL
};
/* pad templates */
@@ -144,6 +145,10 @@ gst_inter_video_sink_class_init (GstInterVideoSinkClass * klass)
base_sink_class->unlock_stop =
GST_DEBUG_FUNCPTR (gst_inter_video_sink_unlock_stop);
+ g_object_class_install_property (gobject_class, PROP_CHANNEL,
+ g_param_spec_string ("channel", "Channel",
+ "Channel name to match inter src and sink elements",
+ "default", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static void
@@ -151,15 +156,21 @@ gst_inter_video_sink_init (GstInterVideoSink * intervideosink,
GstInterVideoSinkClass * intervideosink_class)
{
intervideosink->surface = gst_inter_surface_get ("default");
+
+ intervideosink->channel = g_strdup ("default");
}
void
gst_inter_video_sink_set_property (GObject * object, guint property_id,
const GValue * value, GParamSpec * pspec)
{
- /* GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (object); */
+ GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (object);
switch (property_id) {
+ case PROP_CHANNEL:
+ g_free (intervideosink->channel);
+ intervideosink->channel = g_value_dup_string (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -170,9 +181,12 @@ void
gst_inter_video_sink_get_property (GObject * object, guint property_id,
GValue * value, GParamSpec * pspec)
{
- /* GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (object); */
+ GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (object);
switch (property_id) {
+ case PROP_CHANNEL:
+ g_value_set_string (value, intervideosink->channel);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -192,9 +206,10 @@ gst_inter_video_sink_dispose (GObject * object)
void
gst_inter_video_sink_finalize (GObject * object)
{
- /* GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (object); */
+ GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (object);
/* clean up object here */
+ g_free (intervideosink->channel);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -248,6 +263,9 @@ gst_inter_video_sink_get_times (GstBaseSink * sink, GstBuffer * buffer,
static gboolean
gst_inter_video_sink_start (GstBaseSink * sink)
{
+ GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (sink);
+
+ intervideosink->surface = gst_inter_surface_get (intervideosink->channel);
return TRUE;
}
@@ -264,6 +282,9 @@ gst_inter_video_sink_stop (GstBaseSink * sink)
intervideosink->surface->video_buffer = NULL;
g_mutex_unlock (intervideosink->surface->mutex);
+ gst_inter_surface_unref (intervideosink->surface);
+ intervideosink->surface = NULL;
+
return TRUE;
}
diff --git a/gst/inter/gstintervideosink.h b/gst/inter/gstintervideosink.h
index 5b02efe62..5e421c6d0 100644
--- a/gst/inter/gstintervideosink.h
+++ b/gst/inter/gstintervideosink.h
@@ -39,6 +39,7 @@ struct _GstInterVideoSink
GstBaseSink base_intervideosink;
GstInterSurface *surface;
+ char *channel;
int fps_n;
int fps_d;
diff --git a/gst/inter/gstintervideosrc.c b/gst/inter/gstintervideosrc.c
index 69214d7bf..65fc7f0e5 100644
--- a/gst/inter/gstintervideosrc.c
+++ b/gst/inter/gstintervideosrc.c
@@ -80,7 +80,8 @@ gst_inter_video_src_prepare_seek_segment (GstBaseSrc * src, GstEvent * seek,
enum
{
- PROP_0
+ PROP_0,
+ PROP_CHANNEL
};
/* pad templates */
@@ -156,6 +157,10 @@ gst_inter_video_src_class_init (GstInterVideoSrcClass * klass)
base_src_class->prepare_seek_segment =
GST_DEBUG_FUNCPTR (gst_inter_video_src_prepare_seek_segment);
+ g_object_class_install_property (gobject_class, PROP_CHANNEL,
+ g_param_spec_string ("channel", "Channel",
+ "Channel name to match inter src and sink elements",
+ "default", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
@@ -166,16 +171,20 @@ gst_inter_video_src_init (GstInterVideoSrc * intervideosrc,
gst_base_src_set_format (GST_BASE_SRC (intervideosrc), GST_FORMAT_TIME);
gst_base_src_set_live (GST_BASE_SRC (intervideosrc), TRUE);
- intervideosrc->surface = gst_inter_surface_get ("default");
+ intervideosrc->channel = g_strdup ("default");
}
void
gst_inter_video_src_set_property (GObject * object, guint property_id,
const GValue * value, GParamSpec * pspec)
{
- /* GstInterVideoSrc *intervideosrc = GST_INTER_VIDEO_SRC (object); */
+ GstInterVideoSrc *intervideosrc = GST_INTER_VIDEO_SRC (object);
switch (property_id) {
+ case PROP_CHANNEL:
+ g_free (intervideosrc->channel);
+ intervideosrc->channel = g_value_dup_string (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -186,9 +195,12 @@ void
gst_inter_video_src_get_property (GObject * object, guint property_id,
GValue * value, GParamSpec * pspec)
{
- /* GstInterVideoSrc *intervideosrc = GST_INTER_VIDEO_SRC (object); */
+ GstInterVideoSrc *intervideosrc = GST_INTER_VIDEO_SRC (object);
switch (property_id) {
+ case PROP_CHANNEL:
+ g_value_set_string (value, intervideosrc->channel);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -208,9 +220,10 @@ gst_inter_video_src_dispose (GObject * object)
void
gst_inter_video_src_finalize (GObject * object)
{
- /* GstInterVideoSrc *intervideosrc = GST_INTER_VIDEO_SRC (object); */
+ GstInterVideoSrc *intervideosrc = GST_INTER_VIDEO_SRC (object);
/* clean up object here */
+ g_free (intervideosrc->channel);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -279,6 +292,8 @@ gst_inter_video_src_start (GstBaseSrc * src)
GST_DEBUG_OBJECT (intervideosrc, "start");
+ intervideosrc->surface = gst_inter_surface_get (intervideosrc->channel);
+
return TRUE;
}
@@ -289,6 +304,9 @@ gst_inter_video_src_stop (GstBaseSrc * src)
GST_DEBUG_OBJECT (intervideosrc, "stop");
+ gst_inter_surface_unref (intervideosrc->surface);
+ intervideosrc->surface = NULL;
+
return TRUE;
}
@@ -391,15 +409,6 @@ gst_inter_video_src_create (GstBaseSrc * src, guint64 offset, guint size,
intervideosrc->width) *
gst_video_format_get_component_height (intervideosrc->format, 1,
intervideosrc->height));
-
-#if 0
- {
- int i;
- for (i = 0; i < 10000; i++) {
- data[i] = g_random_int () & 0xff;
- }
- }
-#endif
}
buffer = gst_buffer_make_metadata_writable (buffer);
diff --git a/gst/inter/gstintervideosrc.h b/gst/inter/gstintervideosrc.h
index e7a3cd045..100c21489 100644
--- a/gst/inter/gstintervideosrc.h
+++ b/gst/inter/gstintervideosrc.h
@@ -41,6 +41,8 @@ struct _GstInterVideoSrc
GstInterSurface *surface;
+ char *channel;
+
GstVideoFormat format;
int fps_n;
int fps_d;
diff --git a/gst/mpegdemux/flutspmtstreaminfo.c b/gst/mpegdemux/flutspmtstreaminfo.c
index 9fd449c83..7ab5ba43c 100644
--- a/gst/mpegdemux/flutspmtstreaminfo.c
+++ b/gst/mpegdemux/flutspmtstreaminfo.c
@@ -122,6 +122,8 @@ mpegts_pmt_stream_info_finalize (GObject * object)
g_value_array_free (info->languages);
g_value_array_free (info->descriptors);
+
+ GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
}
MpegTsPmtStreamInfo *
diff --git a/gst/mpegdemux/gstmpegdemux.c b/gst/mpegdemux/gstmpegdemux.c
index 55a567eb0..ef29208de 100644
--- a/gst/mpegdemux/gstmpegdemux.c
+++ b/gst/mpegdemux/gstmpegdemux.c
@@ -60,6 +60,8 @@
#define SEGMENT_THRESHOLD (300*GST_MSECOND)
#define VIDEO_SEGMENT_THRESHOLD (500*GST_MSECOND)
+#define DURATION_SCAN_LIMIT 4 * 1024 * 1024
+
typedef enum
{
SCAN_SCR,
@@ -154,9 +156,9 @@ static GstStateChangeReturn gst_flups_demux_change_state (GstElement * element,
GstStateChange transition);
static inline gboolean gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux,
- guint64 * pos, SCAN_MODE mode, guint64 * rts);
+ guint64 * pos, SCAN_MODE mode, guint64 * rts, gint limit);
static inline gboolean gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux,
- guint64 * pos, SCAN_MODE mode, guint64 * rts);
+ guint64 * pos, SCAN_MODE mode, guint64 * rts, gint limit);
static inline void gst_flups_demux_send_segment_updates (GstFluPSDemux * demux,
GstClockTime new_time);
@@ -399,8 +401,13 @@ gst_flups_demux_create_stream (GstFluPSDemux * demux, gint id, gint stream_type)
break;
}
- if (name == NULL || template == NULL || caps == NULL)
- return NULL;
+ if (name == NULL || template == NULL || caps == NULL) {
+ if (name)
+ g_free (name);
+ if (caps)
+ gst_caps_unref (caps);
+ return FALSE;
+ }
stream = g_new0 (GstFluPSStream, 1);
stream->id = id;
@@ -1046,19 +1053,22 @@ gst_flups_demux_do_seek (GstFluPSDemux * demux, GstSegment * seeksegment)
MIN (gst_util_uint64_scale (scr - demux->first_scr, scr_rate_n,
scr_rate_d), demux->sink_segment.stop);
- found = gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr);
+ found = gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr, 0);
if (!found) {
- found = gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &fscr);
+ found =
+ gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &fscr, 0);
}
while (found && fscr < scr) {
offset++;
- found = gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr);
+ found =
+ gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr, 0);
}
while (found && fscr > scr && offset > 0) {
offset--;
- found = gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &fscr);
+ found =
+ gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &fscr, 0);
}
GST_INFO_OBJECT (demux, "doing seek at offset %" G_GUINT64_FORMAT
@@ -2377,7 +2387,7 @@ beach:
static inline gboolean
gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, guint64 * pos,
- SCAN_MODE mode, guint64 * rts)
+ SCAN_MODE mode, guint64 * rts, gint limit)
{
GstFlowReturn ret = GST_FLOW_OK;
GstBuffer *buffer = NULL;
@@ -2387,12 +2397,15 @@ gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, guint64 * pos,
guint scan_sz = (mode == SCAN_SCR ? SCAN_SCR_SZ : SCAN_PTS_SZ);
guint cursor, to_read = BLOCK_SZ;
guint8 *data;
- guint end_scan;
+ guint end_scan, data_size;
do {
if (offset + scan_sz > demux->sink_segment.stop)
return FALSE;
+ if (limit && offset > *pos + limit)
+ return FALSE;
+
if (offset + to_read > demux->sink_segment.stop)
to_read = demux->sink_segment.stop - offset;
@@ -2401,8 +2414,14 @@ gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, guint64 * pos,
if (G_UNLIKELY (ret != GST_FLOW_OK))
return FALSE;
+ /* may get a short buffer at the end of the file */
+ data_size = GST_BUFFER_SIZE (buffer);
+ if (G_UNLIKELY (data_size <= scan_sz))
+ return FALSE;
+
data = GST_BUFFER_DATA (buffer);
- end_scan = GST_BUFFER_SIZE (buffer) - scan_sz;
+ end_scan = data_size - scan_sz;
+
/* scan the block */
for (cursor = 0; !found && cursor <= end_scan; cursor++) {
found = gst_flups_demux_scan_ts (demux, data++, mode, &ts);
@@ -2424,7 +2443,7 @@ gst_flups_demux_scan_forward_ts (GstFluPSDemux * demux, guint64 * pos,
static inline gboolean
gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux, guint64 * pos,
- SCAN_MODE mode, guint64 * rts)
+ SCAN_MODE mode, guint64 * rts, gint limit)
{
GstFlowReturn ret = GST_FLOW_OK;
GstBuffer *buffer = NULL;
@@ -2433,13 +2452,16 @@ gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux, guint64 * pos,
guint64 ts = 0;
guint scan_sz = (mode == SCAN_SCR ? SCAN_SCR_SZ : SCAN_PTS_SZ);
guint cursor, to_read = BLOCK_SZ;
- guint start_scan;
+ guint start_scan, data_size;
guint8 *data;
do {
if (offset < scan_sz - 1)
return FALSE;
+ if (limit && offset < *pos - limit)
+ return FALSE;
+
if (offset > BLOCK_SZ)
offset -= BLOCK_SZ;
else {
@@ -2451,8 +2473,14 @@ gst_flups_demux_scan_backward_ts (GstFluPSDemux * demux, guint64 * pos,
if (G_UNLIKELY (ret != GST_FLOW_OK))
return FALSE;
- start_scan = GST_BUFFER_SIZE (buffer) - scan_sz;
+ /* may get a short buffer at the end of the file */
+ data_size = GST_BUFFER_SIZE (buffer);
+ if (G_UNLIKELY (data_size <= scan_sz))
+ return FALSE;
+
+ start_scan = data_size - scan_sz;
data = GST_BUFFER_DATA (buffer) + start_scan;
+
/* scan the block */
for (cursor = (start_scan + 1); !found && cursor > 0; cursor--) {
found = gst_flups_demux_scan_ts (demux, data--, mode, &ts);
@@ -2505,7 +2533,8 @@ gst_flups_sink_get_duration (GstFluPSDemux * demux)
/* Scan for notorious SCR and PTS to calculate the duration */
/* scan for first SCR in the stream */
offset = demux->sink_segment.start;
- gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &demux->first_scr);
+ gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &demux->first_scr,
+ DURATION_SCAN_LIMIT);
GST_DEBUG_OBJECT (demux, "First SCR: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
" in packet starting at %" G_GUINT64_FORMAT,
demux->first_scr, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_scr)),
@@ -2513,7 +2542,8 @@ gst_flups_sink_get_duration (GstFluPSDemux * demux)
demux->first_scr_offset = offset;
/* scan for last SCR in the stream */
offset = demux->sink_segment.stop;
- gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, &demux->last_scr);
+ gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR,
+ &demux->last_scr, 0);
GST_DEBUG_OBJECT (demux, "Last SCR: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
" in packet starting at %" G_GUINT64_FORMAT,
demux->last_scr, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->last_scr)),
@@ -2521,18 +2551,22 @@ gst_flups_sink_get_duration (GstFluPSDemux * demux)
demux->last_scr_offset = offset;
/* scan for first PTS in the stream */
offset = demux->sink_segment.start;
- gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_PTS, &demux->first_pts);
+ gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_PTS, &demux->first_pts,
+ DURATION_SCAN_LIMIT);
GST_DEBUG_OBJECT (demux, "First PTS: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
" in packet starting at %" G_GUINT64_FORMAT,
demux->first_pts, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_pts)),
offset);
- /* scan for last PTS in the stream */
- offset = demux->sink_segment.stop;
- gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_PTS, &demux->last_pts);
- GST_DEBUG_OBJECT (demux, "Last PTS: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
- " in packet starting at %" G_GUINT64_FORMAT,
- demux->last_pts, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->last_pts)),
- offset);
+ if (demux->first_pts != G_MAXUINT64) {
+ /* scan for last PTS in the stream */
+ offset = demux->sink_segment.stop;
+ gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_PTS,
+ &demux->last_pts, DURATION_SCAN_LIMIT);
+ GST_DEBUG_OBJECT (demux,
+ "Last PTS: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT
+ " in packet starting at %" G_GUINT64_FORMAT, demux->last_pts,
+ GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->last_pts)), offset);
+ }
/* Detect wrong SCR values */
if (demux->first_scr > demux->last_scr) {
GST_DEBUG_OBJECT (demux, "Wrong SCR values detected, searching for "
@@ -2540,7 +2574,7 @@ gst_flups_sink_get_duration (GstFluPSDemux * demux)
offset = demux->first_scr_offset;
for (i = 0; i < 10; i++) {
offset++;
- gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &scr);
+ gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &scr, 0);
if (scr < demux->last_scr) {
demux->first_scr = scr;
demux->first_scr_offset = offset;
diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c
index 5ee8daeb1..2c6db7da3 100644
--- a/gst/mpegdemux/gstmpegtsdemux.c
+++ b/gst/mpegdemux/gstmpegtsdemux.c
@@ -829,8 +829,13 @@ gst_mpegts_demux_fill_stream (GstMpegTSStream * stream, guint8 id,
default:
break;
}
- if (name == NULL || template == NULL || caps == NULL)
+ if (name == NULL || template == NULL || caps == NULL) {
+ if (name)
+ g_free (name);
+ if (caps)
+ gst_caps_unref (caps);
return FALSE;
+ }
stream->stream_type = stream_type;
stream->id = id;
@@ -1105,6 +1110,10 @@ gst_mpegts_demux_add_all_streams (GstMpegTSDemux * demux, GstClockTime pts)
GstPad *srcpad;
gboolean all_added = TRUE;
+ GST_DEBUG_OBJECT (demux, "Adding streams early fixes a wedge in some low "
+ "bitrate streams, but causes deadlocks - disabled for now");
+ return FALSE;
+
/* When adding a stream, require either a valid base PCR, or a valid PTS */
if (!gst_mpegts_demux_setup_base_pts (demux, pts)) {
GST_ERROR ("Can't set base pts");
diff --git a/gst/mpegdemux/mpegtsparse.c b/gst/mpegdemux/mpegtsparse.c
index d77fd23ad..bac482462 100644
--- a/gst/mpegdemux/mpegtsparse.c
+++ b/gst/mpegdemux/mpegtsparse.c
@@ -1275,6 +1275,8 @@ mpegts_parse_get_tags_from_sdt (MpegTSParse * parse, GstStructure * sdt_info)
* which looks like service-%d */
sid_str = gst_structure_get_name (service);
tmp = g_strstr_len (sid_str, -1, "-");
+ if (!tmp)
+ continue;
program_number = atoi (++tmp);
program = mpegts_parse_get_program (parse, program_number);
diff --git a/gst/mpegtsdemux/mpegtsbase.c b/gst/mpegtsdemux/mpegtsbase.c
index e7d856fd4..34736d7b0 100644
--- a/gst/mpegtsdemux/mpegtsbase.c
+++ b/gst/mpegtsdemux/mpegtsbase.c
@@ -1097,6 +1097,8 @@ mpegts_base_get_tags_from_sdt (MpegTSBase * base, GstStructure * sdt_info)
* which looks like service-%d */
sid_str = gst_structure_get_name (service);
tmp = g_strstr_len (sid_str, -1, "-");
+ if (!tmp)
+ continue;
program_number = atoi (++tmp);
program = mpegts_base_get_program (base, program_number);
diff --git a/gst/mpegtsdemux/tsdemux.c b/gst/mpegtsdemux/tsdemux.c
index 4f51abd5c..2ed04c516 100644
--- a/gst/mpegtsdemux/tsdemux.c
+++ b/gst/mpegtsdemux/tsdemux.c
@@ -1050,6 +1050,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
name = g_strdup_printf ("private_%04x", bstream->pid);
caps = gst_caps_new_empty_simple ("subpicture/x-dvb");
g_free (desc);
+ break;
}
/* hack for itv hd (sid 10510, video pid 3401 */
if (program->program_number == 10510 && bstream->pid == 3401) {
diff --git a/gst/mve/gstmvemux.c b/gst/mve/gstmvemux.c
index e6c2fcb6c..3bf07b01e 100644
--- a/gst/mve/gstmvemux.c
+++ b/gst/mve/gstmvemux.c
@@ -337,7 +337,7 @@ static void
gst_mve_mux_palette_analyze (GstMveMux * mvemux, const GstBuffer * pal,
guint16 * first, guint16 * last)
{
- guint i;
+ gint i;
guint32 *col1;
col1 = (guint32 *) GST_BUFFER_DATA (pal);
diff --git a/gst/mve/mvevideoenc16.c b/gst/mve/mvevideoenc16.c
index ec82523dc..d94e3daca 100644
--- a/gst/mve/mvevideoenc16.c
+++ b/gst/mve/mvevideoenc16.c
@@ -285,6 +285,9 @@ mve_quantize (const GstMveMux * mve, const guint16 * src,
}
}
+ if (G_UNLIKELY (!best))
+ continue;
+
++best->hits;
best->r_total += r;
best->g_total += g;
diff --git a/gst/nuvdemux/gstnuvdemux.c b/gst/nuvdemux/gstnuvdemux.c
index 3401c8157..22efb9402 100644
--- a/gst/nuvdemux/gstnuvdemux.c
+++ b/gst/nuvdemux/gstnuvdemux.c
@@ -488,7 +488,7 @@ gst_nuv_demux_stream_data (GstNuvDemux * nuv)
switch (h->i_type) {
case 'V':
{
- if (h->i_length == 0)
+ if (!buf)
break;
GST_BUFFER_OFFSET (buf) = nuv->video_offset;
@@ -499,7 +499,7 @@ gst_nuv_demux_stream_data (GstNuvDemux * nuv)
}
case 'A':
{
- if (h->i_length == 0)
+ if (!buf)
break;
GST_BUFFER_OFFSET (buf) = nuv->audio_offset;
diff --git a/gst/siren/gstsirenenc.c b/gst/siren/gstsirenenc.c
index 561d2689d..a78cdb8bc 100644
--- a/gst/siren/gstsirenenc.c
+++ b/gst/siren/gstsirenenc.c
@@ -158,7 +158,7 @@ gst_siren_enc_finalize (GObject * object)
Siren7_CloseEncoder (enc->encoder);
g_object_unref (enc->adapter);
- G_OBJECT_CLASS (parent_class)->dispose (object);
+ G_OBJECT_CLASS (parent_class)->finalize (object);
}
static gboolean
diff --git a/gst/videoparsers/Makefile.am b/gst/videoparsers/Makefile.am
index fb5497368..49baeacd1 100644
--- a/gst/videoparsers/Makefile.am
+++ b/gst/videoparsers/Makefile.am
@@ -33,6 +33,7 @@ Android.mk: Makefile.am $(BUILT_SOURCES)
$(libgstvideoparsersbad_la_LIBADD) \
-ldl \
-:LIBFILTER_STATIC gstbaseparse-@GST_MAJORMINOR@ \
+ gstcodecparsers-@GST_MAJORMINOR@ \
-:PASSTHROUGH LOCAL_ARM_MODE:=arm \
LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
> $@
diff --git a/sys/avc/Makefile.am b/sys/avc/Makefile.am
index 9bde7510b..963f51494 100644
--- a/sys/avc/Makefile.am
+++ b/sys/avc/Makefile.am
@@ -6,7 +6,7 @@ libgstavc_la_CPPFLAGS = \
$(GST_PLUGINS_BAD_CXXFLAGS) \
$(GST_PLUGINS_BASE_CXXFLAGS) \
$(GST_CXXFLAGS) \
- -framework AVCVideoServices
+ -framework AVCVideoServices \
-Wno-deprecated-declarations
libgstavc_la_LIBADD = \
$(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) \
diff --git a/sys/linsys/gstlinsyssdisink.c b/sys/linsys/gstlinsyssdisink.c
index 3e9ad165b..57813d39a 100644
--- a/sys/linsys/gstlinsyssdisink.c
+++ b/sys/linsys/gstlinsyssdisink.c
@@ -196,9 +196,14 @@ gst_linsys_sdi_sink_get_property (GObject * object, guint property_id,
void
gst_linsys_sdi_sink_dispose (GObject * object)
{
+ GstLinsysSdiSink *linsyssdisink;
+
g_return_if_fail (GST_IS_LINSYS_SDI_SINK (object));
+ linsyssdisink = GST_LINSYS_SDI_SINK (object);
/* clean up as possible. may be called multiple times */
+ g_free (linsyssdisink->device);
+ linsyssdisink->device = NULL;
G_OBJECT_CLASS (parent_class)->dispose (object);
}
diff --git a/sys/linsys/gstlinsyssdisrc.c b/sys/linsys/gstlinsyssdisrc.c
index c5a928c68..f3cd72a40 100644
--- a/sys/linsys/gstlinsyssdisrc.c
+++ b/sys/linsys/gstlinsyssdisrc.c
@@ -212,9 +212,12 @@ gst_linsys_sdi_src_get_property (GObject * object, guint property_id,
void
gst_linsys_sdi_src_dispose (GObject * object)
{
- g_return_if_fail (GST_IS_LINSYS_SDI_SRC (object));
+ GstLinsysSdiSrc *linsyssdisrc = GST_LINSYS_SDI_SRC (object);
+ g_return_if_fail (linsyssdisrc != NULL);
/* clean up as possible. may be called multiple times */
+ g_free (linsyssdisrc->device);
+ linsyssdisrc->device = NULL;
G_OBJECT_CLASS (parent_class)->dispose (object);
}