summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian.droege@collabora.co.uk>2012-01-10 14:32:32 +0100
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2012-01-10 14:32:32 +0100
commit93e3ed5a869afb79f9658f22ced4691ce475e8a1 (patch)
treebaaec96daaf22857d61128401c12e2649ef25304
parent692e00cc00d772fe2b01f518cb9ac88d124807d1 (diff)
parent2b2c0940f1b7ce8a858a26ad5e246fd645a83830 (diff)
Merge branch 'master' into 0.11
Conflicts: ext/cairo/gsttextoverlay.c ext/pulse/pulseaudiosink.c gst/audioparsers/gstaacparse.c gst/avi/gstavimux.c gst/flv/gstflvmux.c gst/interleave/interleave.c gst/isomp4/gstqtmux.c gst/matroska/matroska-demux.c gst/matroska/matroska-mux.c gst/matroska/matroska-mux.h gst/matroska/matroska-read-common.c gst/multifile/gstmultifilesink.c gst/multipart/multipartmux.c gst/shapewipe/gstshapewipe.c gst/smpte/gstsmpte.c gst/udp/gstmultiudpsink.c gst/videobox/gstvideobox.c gst/videocrop/gstaspectratiocrop.c gst/videomixer/videomixer.c gst/videomixer/videomixer2.c gst/wavparse/gstwavparse.c po/ja.po po/lv.po po/sr.po tests/check/Makefile.am tests/check/elements/qtmux.c tests/check/elements/rgvolume.c
-rw-r--r--Makefile.am3
-rw-r--r--configure.ac9
-rw-r--r--ext/cairo/gsttextoverlay.c38
-rw-r--r--ext/cairo/gsttextoverlay.h8
-rw-r--r--ext/dv/gstdvdemux.c5
-rw-r--r--ext/flac/gstflacdec.c5
-rw-r--r--ext/gdk_pixbuf/gstgdkpixbufsink.c4
-rw-r--r--ext/jack/gstjackaudioclient.c2
-rw-r--r--ext/jack/gstjackaudiosink.c39
-rw-r--r--ext/jack/gstjackaudiosink.h1
-rw-r--r--ext/jack/gstjackaudiosrc.c39
-rw-r--r--ext/jack/gstjackaudiosrc.h1
-rw-r--r--ext/jpeg/gstjpegdec.c2
-rw-r--r--ext/pulse/pulsesink.c2
-rw-r--r--ext/soup/gstsouphttpclientsink.c40
-rw-r--r--ext/wavpack/gstwavpackparse.c5
-rw-r--r--gst-libs/gst/glib-compat-private.h135
-rw-r--r--gst/alpha/gstalpha.c22
-rw-r--r--gst/alpha/gstalpha.h4
-rw-r--r--gst/audiofx/audiochebband.c2
-rw-r--r--gst/audiofx/audiocheblimit.c2
-rw-r--r--gst/audiofx/audiofirfilter.c2
-rw-r--r--gst/audiofx/audioiirfilter.c2
-rw-r--r--gst/audiofx/audiowsincband.c2
-rw-r--r--gst/audiofx/audiowsinclimit.c2
-rw-r--r--gst/audioparsers/gstaacparse.c440
-rw-r--r--gst/audioparsers/gstaacparse.h2
-rw-r--r--gst/audioparsers/gstac3parse.c4
-rw-r--r--gst/avi/gstavidemux.c4
-rw-r--r--gst/avi/gstavimux.c57
-rw-r--r--gst/avi/gstavimux.h9
-rw-r--r--gst/equalizer/gstiirequalizer.c2
-rw-r--r--gst/flv/gstflvdemux.c4
-rw-r--r--gst/flv/gstflvmux.c167
-rw-r--r--gst/flv/gstflvmux.h8
-rw-r--r--gst/imagefreeze/gstimagefreeze.c6
-rw-r--r--gst/interleave/interleave.c37
-rw-r--r--gst/interleave/interleave.h4
-rw-r--r--gst/isomp4/gstqtmoovrecover.c4
-rw-r--r--gst/isomp4/gstqtmux.c113
-rw-r--r--gst/isomp4/gstqtmux.h9
-rw-r--r--gst/isomp4/qtdemux.c13
-rw-r--r--gst/matroska/matroska-demux.c54
-rw-r--r--gst/matroska/matroska-demux.h3
-rw-r--r--gst/matroska/matroska-mux.c582
-rw-r--r--gst/matroska/matroska-mux.h9
-rw-r--r--gst/matroska/matroska-read-common.c15
-rw-r--r--gst/multifile/gstmultifilesink.c15
-rw-r--r--gst/multipart/multipartmux.c22
-rw-r--r--gst/multipart/multipartmux.h6
-rw-r--r--gst/rtpmanager/gstrtpbin.c2
-rw-r--r--gst/rtpmanager/gstrtpjitterbuffer.c2
-rw-r--r--gst/rtpmanager/gstrtpsession.c7
-rw-r--r--gst/rtpmanager/gstrtpssrcdemux.c4
-rw-r--r--gst/rtpmanager/rtpsession.c2
-rw-r--r--gst/rtsp/gstrtspsrc.c4
-rw-r--r--gst/smpte/gstsmpte.c32
-rw-r--r--gst/smpte/gstsmpte.h4
-rw-r--r--gst/udp/gstmultiudpsink.c2
-rw-r--r--gst/udp/gstudpsrc.c17
-rw-r--r--gst/videocrop/gstaspectratiocrop.c2
-rw-r--r--gst/videomixer/videomixer2.c4
-rw-r--r--gst/wavparse/gstwavparse.c190
-rw-r--r--gst/wavparse/gstwavparse.h2
-rw-r--r--po/LINGUAS2
-rw-r--r--po/eo.po832
-rw-r--r--sys/Makefile.am8
-rw-r--r--sys/oss4/oss4-mixer.c6
-rw-r--r--sys/v4l2/gstv4l2bufferpool.c1
-rw-r--r--sys/v4l2/gstv4l2videooverlay.c1
-rw-r--r--sys/waveform/Makefile.am10
-rw-r--r--sys/waveform/gstwaveformsink.c12
-rw-r--r--sys/ximage/gstximagesrc.c2
-rw-r--r--tests/check/Makefile.am4
-rw-r--r--tests/check/elements/.gitignore1
-rw-r--r--tests/check/elements/qtmux.c7
-rw-r--r--tests/check/elements/rgvolume.c47
-rw-r--r--tests/check/elements/souphttpsrc.c7
-rw-r--r--tests/check/elements/udpsrc.c120
-rw-r--r--tests/files/Makefile.am1
-rw-r--r--tests/icles/equalizer-test.c2
-rw-r--r--tests/icles/gdkpixbufsink-test.c2
-rw-r--r--tests/icles/test-oss4.c2
-rw-r--r--tests/icles/v4l2src-test.c8
-rw-r--r--tests/icles/videocrop-test.c2
85 files changed, 2635 insertions, 681 deletions
diff --git a/Makefile.am b/Makefile.am
index 0119fad4c..9638883cb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -26,7 +26,8 @@ DISTCLEANFILES = _stdint.h
noinst_HEADERS = \
gst-libs/gst/gettext.h \
- gst-libs/gst/gst-i18n-plugin.h
+ gst-libs/gst/gst-i18n-plugin.h \
+ gst-libs/gst/glib-compat-private.h
ACLOCAL_AMFLAGS = -I m4 -I common/m4
diff --git a/configure.ac b/configure.ac
index f2e608bda..5e16f67b1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -203,7 +203,7 @@ AC_CHECK_TYPE([struct ip_mreqn], [
dnl *** checks for dependency libraries ***
dnl GLib is required
-AG_GST_GLIB_CHECK([2.20])
+AG_GST_GLIB_CHECK([2.24])
PKG_CHECK_MODULES(GIO, [ gio-2.0 >= 2.20 ], , AC_MSG_ERROR([gio is required]))
dnl Orc
@@ -438,6 +438,12 @@ int main ()
AC_SUBST(HAVE_DIRECTSOUND)
])
+dnl *** Win32 WaveOut ***
+translit(dnm, m, l) AM_CONDITIONAL(USE_WAVEFORM, true)
+AG_GST_CHECK_FEATURE(WAVEFORM, [Win32 WaveForm], waveformsink, [
+ AC_CHECK_HEADER(mmsystem.h, HAVE_WAVEFORM="yes", HAVE_WAVEFORM="no", [#include <windows.h>])
+])
+
dnl *** OSS audio *** (Linux, *BSD)
translit(dnm, m, l) AM_CONDITIONAL(USE_OSS, true)
AG_GST_CHECK_FEATURE(OSS, [OSS audio], ossaudio, [
@@ -1005,6 +1011,7 @@ AM_CONDITIONAL(USE_SOUP, false)
AM_CONDITIONAL(USE_SPEEX, false)
AM_CONDITIONAL(USE_SUNAUDIO, false)
AM_CONDITIONAL(USE_TAGLIB, false)
+AM_CONDITIONAL(USE_WAVEFORM, false)
AM_CONDITIONAL(USE_WAVPACK, false)
AM_CONDITIONAL(USE_X, false)
AM_CONDITIONAL(USE_XSHM, false)
diff --git a/ext/cairo/gsttextoverlay.c b/ext/cairo/gsttextoverlay.c
index 7d79f98f7..2a09b9cb1 100644
--- a/ext/cairo/gsttextoverlay.c
+++ b/ext/cairo/gsttextoverlay.c
@@ -106,7 +106,7 @@ static gboolean gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps);
static GstPadLinkReturn gst_text_overlay_text_pad_linked (GstPad * pad,
GstPad * peer);
static void gst_text_overlay_text_pad_unlinked (GstPad * pad);
-static GstFlowReturn gst_text_overlay_collected (GstCollectPads * pads,
+static GstFlowReturn gst_text_overlay_collected (GstCollectPads2 * pads,
gpointer data);
static void gst_text_overlay_finalize (GObject * object);
static void gst_text_overlay_font_init (GstCairoTextOverlay * overlay);
@@ -215,7 +215,7 @@ gst_text_overlay_finalize (GObject * object)
{
GstCairoTextOverlay *overlay = GST_CAIRO_TEXT_OVERLAY (object);
- gst_collect_pads_stop (overlay->collect);
+ gst_collect_pads2_stop (overlay->collect);
gst_object_unref (overlay->collect);
g_free (overlay->text_fill_image);
@@ -279,16 +279,16 @@ gst_text_overlay_init (GstCairoTextOverlay * overlay,
overlay->fps_n = 0;
overlay->fps_d = 1;
- overlay->collect = gst_collect_pads_new ();
+ overlay->collect = gst_collect_pads2_new ();
- gst_collect_pads_set_function (overlay->collect,
+ gst_collect_pads2_set_function (overlay->collect,
GST_DEBUG_FUNCPTR (gst_text_overlay_collected), overlay);
- overlay->video_collect_data = gst_collect_pads_add_pad (overlay->collect,
- overlay->video_sinkpad, sizeof (GstCollectData), NULL);
+ overlay->video_collect_data = gst_collect_pads2_add_pad (overlay->collect,
+ overlay->video_sinkpad, sizeof (GstCollectData2));
/* FIXME: hacked way to override/extend the event function of
- * GstCollectPads; because it sets its own event function giving the
+ * GstCollectPads2; because it sets its own event function giving the
* element no access to events. Nicked from avimux. */
overlay->collect_event =
(GstPadEventFunction) GST_PAD_EVENTFUNC (overlay->video_sinkpad);
@@ -640,8 +640,8 @@ gst_text_overlay_text_pad_linked (GstPad * pad, GstPad * peer)
GST_DEBUG_OBJECT (overlay, "Text pad linked");
if (overlay->text_collect_data == NULL) {
- overlay->text_collect_data = gst_collect_pads_add_pad (overlay->collect,
- overlay->text_sinkpad, sizeof (GstCollectData), NULL);
+ overlay->text_collect_data = gst_collect_pads2_add_pad (overlay->collect,
+ overlay->text_sinkpad, sizeof (GstCollectData2));
}
overlay->need_render = TRUE;
@@ -660,7 +660,7 @@ gst_text_overlay_text_pad_unlinked (GstPad * pad)
GST_DEBUG_OBJECT (overlay, "Text pad unlinked");
if (overlay->text_collect_data) {
- gst_collect_pads_remove_pad (overlay->collect, overlay->text_sinkpad);
+ gst_collect_pads2_remove_pad (overlay->collect, overlay->text_sinkpad);
overlay->text_collect_data = NULL;
}
@@ -807,7 +807,7 @@ gst_text_overlay_pop_video (GstCairoTextOverlay * overlay)
{
GstBuffer *buf;
- buf = gst_collect_pads_pop (overlay->collect, overlay->video_collect_data);
+ buf = gst_collect_pads2_pop (overlay->collect, overlay->video_collect_data);
g_return_if_fail (buf != NULL);
gst_buffer_unref (buf);
}
@@ -818,7 +818,7 @@ gst_text_overlay_pop_text (GstCairoTextOverlay * overlay)
GstBuffer *buf;
if (overlay->text_collect_data) {
- buf = gst_collect_pads_pop (overlay->collect, overlay->text_collect_data);
+ buf = gst_collect_pads2_pop (overlay->collect, overlay->text_collect_data);
g_return_if_fail (buf != NULL);
gst_buffer_unref (buf);
}
@@ -828,7 +828,7 @@ gst_text_overlay_pop_text (GstCairoTextOverlay * overlay)
/* This function is called when there is data on all pads */
static GstFlowReturn
-gst_text_overlay_collected (GstCollectPads * pads, gpointer data)
+gst_text_overlay_collected (GstCollectPads2 * pads, gpointer data)
{
GstCairoTextOverlay *overlay;
GstFlowReturn ret = GST_FLOW_OK;
@@ -842,14 +842,14 @@ gst_text_overlay_collected (GstCollectPads * pads, gpointer data)
GST_DEBUG ("Collecting");
- video_frame = gst_collect_pads_peek (overlay->collect,
+ video_frame = gst_collect_pads2_peek (overlay->collect,
overlay->video_collect_data);
/* send EOS if video stream EOSed regardless of text stream */
if (video_frame == NULL) {
GST_DEBUG ("Video stream at EOS");
if (overlay->text_collect_data) {
- text_buf = gst_collect_pads_pop (overlay->collect,
+ text_buf = gst_collect_pads2_pop (overlay->collect,
overlay->text_collect_data);
}
gst_pad_push_event (overlay->srcpad, gst_event_new_eos ());
@@ -892,7 +892,7 @@ gst_text_overlay_collected (GstCollectPads * pads, gpointer data)
goto done;
}
- text_buf = gst_collect_pads_peek (overlay->collect,
+ text_buf = gst_collect_pads2_peek (overlay->collect,
overlay->text_collect_data);
/* just push the video frame if the text stream has EOSed */
@@ -1004,7 +1004,7 @@ gst_text_overlay_video_event (GstPad * pad, GstEvent * event)
gst_pad_push_event (overlay->srcpad, event);
}
- /* now GstCollectPads can take care of the rest, e.g. EOS */
+ /* now GstCollectPads2 can take care of the rest, e.g. EOS */
ret = overlay->collect_event (pad, event);
gst_object_unref (overlay);
return ret;
@@ -1018,12 +1018,12 @@ gst_text_overlay_change_state (GstElement * element, GstStateChange transition)
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
- gst_collect_pads_start (overlay->collect);
+ gst_collect_pads2_start (overlay->collect);
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
/* need to unblock the collectpads before calling the
* parent change_state so that streaming can finish */
- gst_collect_pads_stop (overlay->collect);
+ gst_collect_pads2_stop (overlay->collect);
break;
default:
break;
diff --git a/ext/cairo/gsttextoverlay.h b/ext/cairo/gsttextoverlay.h
index dbb21546f..1f98d3d58 100644
--- a/ext/cairo/gsttextoverlay.h
+++ b/ext/cairo/gsttextoverlay.h
@@ -3,7 +3,7 @@
#define __GST_CAIRO_TEXT_OVERLAY_H__
#include <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
+#include <gst/base/gstcollectpads2.h>
G_BEGIN_DECLS
@@ -45,9 +45,9 @@ struct _GstCairoTextOverlay {
GstPad *text_sinkpad;
GstPad *srcpad;
- GstCollectPads *collect;
- GstCollectData *video_collect_data;
- GstCollectData *text_collect_data;
+ GstCollectPads2 *collect;
+ GstCollectData2 *video_collect_data;
+ GstCollectData2 *text_collect_data;
GstPadEventFunction collect_event;
gint width;
diff --git a/ext/dv/gstdvdemux.c b/ext/dv/gstdvdemux.c
index d236c3ffa..d3618ed19 100644
--- a/ext/dv/gstdvdemux.c
+++ b/ext/dv/gstdvdemux.c
@@ -21,6 +21,11 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+
+/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
#include <string.h>
#include <math.h>
diff --git a/ext/flac/gstflacdec.c b/ext/flac/gstflacdec.c
index 94c0402cc..7066d7db9 100644
--- a/ext/flac/gstflacdec.c
+++ b/ext/flac/gstflacdec.c
@@ -41,6 +41,11 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+
+/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
#include <string.h>
#include "gstflacdec.h"
diff --git a/ext/gdk_pixbuf/gstgdkpixbufsink.c b/ext/gdk_pixbuf/gstgdkpixbufsink.c
index f18d3c183..923538677 100644
--- a/ext/gdk_pixbuf/gstgdkpixbufsink.c
+++ b/ext/gdk_pixbuf/gstgdkpixbufsink.c
@@ -271,7 +271,7 @@ gst_gdk_pixbuf_sink_set_caps (GstBaseSink * basesink, GstCaps * caps)
GST_INFO_OBJECT (sink, "format : %d", fmt);
GST_INFO_OBJECT (sink, "width x height : %d x %d", w, h);
- GST_INFO_OBJECT (sink, "pixel-aspect-ratio : %d/%d", par_d, par_n);
+ GST_INFO_OBJECT (sink, "pixel-aspect-ratio : %d/%d", par_n, par_d);
return TRUE;
}
@@ -344,7 +344,7 @@ gst_gdk_pixbuf_sink_handle_buffer (GstBaseSink * basesink, GstBuffer * buf,
* The structure will take its own ref to the pixbuf. */
s = gst_structure_new (msg_name,
"pixbuf", GDK_TYPE_PIXBUF, pixbuf,
- "pixel-aspect-ratio", GST_TYPE_FRACTION, sink->par_d, sink->par_n,
+ "pixel-aspect-ratio", GST_TYPE_FRACTION, sink->par_n, sink->par_d,
NULL);
msg = gst_message_new_element (GST_OBJECT_CAST (sink), s);
diff --git a/ext/jack/gstjackaudioclient.c b/ext/jack/gstjackaudioclient.c
index 1789edb60..2bb355529 100644
--- a/ext/jack/gstjackaudioclient.c
+++ b/ext/jack/gstjackaudioclient.c
@@ -23,6 +23,8 @@
#include "gstjackaudioclient.h"
+#include <gst/glib-compat-private.h>
+
GST_DEBUG_CATEGORY_STATIC (gst_jack_audio_client_debug);
#define GST_CAT_DEFAULT gst_jack_audio_client_debug
diff --git a/ext/jack/gstjackaudiosink.c b/ext/jack/gstjackaudiosink.c
index fe911840f..8055f9219 100644
--- a/ext/jack/gstjackaudiosink.c
+++ b/ext/jack/gstjackaudiosink.c
@@ -329,7 +329,11 @@ gst_jack_ring_buffer_open_device (GstAudioRingBuffer * buf)
GST_DEBUG_OBJECT (sink, "open");
- name = g_get_application_name ();
+ if (sink->client_name) {
+ name = sink->client_name;
+ } else {
+ name = g_get_application_name ();
+ }
if (!name)
name = "GStreamer";
@@ -648,8 +652,9 @@ enum
SIGNAL_LAST
};
-#define DEFAULT_PROP_CONNECT GST_JACK_CONNECT_AUTO
-#define DEFAULT_PROP_SERVER NULL
+#define DEFAULT_PROP_CONNECT GST_JACK_CONNECT_AUTO
+#define DEFAULT_PROP_SERVER NULL
+#define DEFAULT_PROP_CLIENT_NAME NULL
enum
{
@@ -657,6 +662,7 @@ enum
PROP_CONNECT,
PROP_SERVER,
PROP_CLIENT,
+ PROP_CLIENT_NAME,
PROP_LAST
};
@@ -705,6 +711,19 @@ gst_jack_audio_sink_class_init (GstJackAudioSinkClass * klass)
"The Jack server to connect to (NULL = default)",
DEFAULT_PROP_SERVER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstJackAudioSink:client-name
+ *
+ * The client name to use.
+ *
+ * Since: 0.10.31
+ */
+ g_object_class_install_property (gobject_class, PROP_CLIENT_NAME,
+ g_param_spec_string ("client-name", "Client name",
+ "The client name of the Jack instance (NULL = default)",
+ DEFAULT_PROP_CLIENT_NAME,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
g_object_class_install_property (gobject_class, PROP_CLIENT,
g_param_spec_boxed ("client", "JackClient", "Handle for jack client",
GST_TYPE_JACK_CLIENT,
@@ -738,6 +757,7 @@ gst_jack_audio_sink_init (GstJackAudioSink * sink)
sink->jclient = NULL;
sink->ports = NULL;
sink->port_count = 0;
+ sink->client_name = g_strdup (DEFAULT_PROP_CLIENT_NAME);
sink->buffers = NULL;
}
@@ -747,6 +767,12 @@ gst_jack_audio_sink_dispose (GObject * object)
GstJackAudioSink *sink = GST_JACK_AUDIO_SINK (object);
gst_caps_replace (&sink->caps, NULL);
+
+ if (sink->client_name != NULL) {
+ g_free (sink->client_name);
+ sink->client_name = NULL;
+ }
+
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -759,6 +785,10 @@ gst_jack_audio_sink_set_property (GObject * object, guint prop_id,
sink = GST_JACK_AUDIO_SINK (object);
switch (prop_id) {
+ case PROP_CLIENT_NAME:
+ g_free (sink->client_name);
+ sink->client_name = g_value_dup_string (value);
+ break;
case PROP_CONNECT:
sink->connect = g_value_get_enum (value);
break;
@@ -787,6 +817,9 @@ gst_jack_audio_sink_get_property (GObject * object, guint prop_id,
sink = GST_JACK_AUDIO_SINK (object);
switch (prop_id) {
+ case PROP_CLIENT_NAME:
+ g_value_set_string (value, sink->client_name);
+ break;
case PROP_CONNECT:
g_value_set_enum (value, sink->connect);
break;
diff --git a/ext/jack/gstjackaudiosink.h b/ext/jack/gstjackaudiosink.h
index 02a8db9fc..0dbc142e0 100644
--- a/ext/jack/gstjackaudiosink.h
+++ b/ext/jack/gstjackaudiosink.h
@@ -58,6 +58,7 @@ struct _GstJackAudioSink {
GstJackConnect connect;
gchar *server;
jack_client_t *jclient;
+ gchar *client_name;
/* our client */
GstJackAudioClient *client;
diff --git a/ext/jack/gstjackaudiosrc.c b/ext/jack/gstjackaudiosrc.c
index 4973a8b77..cf21cbfc1 100644
--- a/ext/jack/gstjackaudiosrc.c
+++ b/ext/jack/gstjackaudiosrc.c
@@ -336,7 +336,11 @@ gst_jack_ring_buffer_open_device (GstAudioRingBuffer * buf)
GST_DEBUG_OBJECT (src, "open");
- name = g_get_application_name ();
+ if (src->client_name) {
+ name = src->client_name;
+ } else {
+ name = g_get_application_name ();
+ }
if (!name)
name = "GStreamer";
@@ -651,8 +655,9 @@ enum
LAST_SIGNAL
};
-#define DEFAULT_PROP_CONNECT GST_JACK_CONNECT_AUTO
-#define DEFAULT_PROP_SERVER NULL
+#define DEFAULT_PROP_CONNECT GST_JACK_CONNECT_AUTO
+#define DEFAULT_PROP_SERVER NULL
+#define DEFAULT_PROP_CLIENT_NAME NULL
enum
{
@@ -660,6 +665,7 @@ enum
PROP_CONNECT,
PROP_SERVER,
PROP_CLIENT,
+ PROP_CLIENT_NAME,
PROP_LAST
};
@@ -726,6 +732,19 @@ gst_jack_audio_src_class_init (GstJackAudioSrcClass * klass)
"The Jack server to connect to (NULL = default)",
DEFAULT_PROP_SERVER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstJackAudioSrc:client-name
+ *
+ * The client name to use.
+ *
+ * Since: 0.10.31
+ */
+ g_object_class_install_property (gobject_class, PROP_CLIENT_NAME,
+ g_param_spec_string ("client-name", "Client name",
+ "The client name of the Jack instance (NULL = default)",
+ DEFAULT_PROP_CLIENT_NAME,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
g_object_class_install_property (gobject_class, PROP_CLIENT,
g_param_spec_boxed ("client", "JackClient", "Handle for jack client",
GST_TYPE_JACK_CLIENT,
@@ -765,6 +784,7 @@ gst_jack_audio_src_init (GstJackAudioSrc * src)
src->ports = NULL;
src->port_count = 0;
src->buffers = NULL;
+ src->client_name = g_strdup (DEFAULT_PROP_CLIENT_NAME);
}
static void
@@ -773,6 +793,12 @@ gst_jack_audio_src_dispose (GObject * object)
GstJackAudioSrc *src = GST_JACK_AUDIO_SRC (object);
gst_caps_replace (&src->caps, NULL);
+
+ if (src->client_name != NULL) {
+ g_free (src->client_name);
+ src->client_name = NULL;
+ }
+
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -783,6 +809,10 @@ gst_jack_audio_src_set_property (GObject * object, guint prop_id,
GstJackAudioSrc *src = GST_JACK_AUDIO_SRC (object);
switch (prop_id) {
+ case PROP_CLIENT_NAME:
+ g_free (src->client_name);
+ src->client_name = g_value_dup_string (value);
+ break;
case PROP_CONNECT:
src->connect = g_value_get_enum (value);
break;
@@ -809,6 +839,9 @@ gst_jack_audio_src_get_property (GObject * object, guint prop_id,
GstJackAudioSrc *src = GST_JACK_AUDIO_SRC (object);
switch (prop_id) {
+ case PROP_CLIENT_NAME:
+ g_value_set_string (value, src->client_name);
+ break;
case PROP_CONNECT:
g_value_set_enum (value, src->connect);
break;
diff --git a/ext/jack/gstjackaudiosrc.h b/ext/jack/gstjackaudiosrc.h
index fa119472c..1401d9b0d 100644
--- a/ext/jack/gstjackaudiosrc.h
+++ b/ext/jack/gstjackaudiosrc.h
@@ -75,6 +75,7 @@ struct _GstJackAudioSrc
GstJackConnect connect;
gchar *server;
jack_client_t *jclient;
+ gchar *client_name;
/* our client */
GstJackAudioClient *client;
diff --git a/ext/jpeg/gstjpegdec.c b/ext/jpeg/gstjpegdec.c
index 15658ed25..8301214ec 100644
--- a/ext/jpeg/gstjpegdec.c
+++ b/ext/jpeg/gstjpegdec.c
@@ -761,7 +761,7 @@ gst_jpeg_dec_getcaps (GstPad * pad, GstCaps * filter)
templ_caps = gst_pad_get_pad_template_caps (pad);
caps = gst_caps_intersect_full (peer_caps, templ_caps,
GST_CAPS_INTERSECT_FIRST);
-
+ gst_caps_unref (peer_caps);
gst_object_unref (peer);
} else {
caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
diff --git a/ext/pulse/pulsesink.c b/ext/pulse/pulsesink.c
index 4fa873c4d..371863e7a 100644
--- a/ext/pulse/pulsesink.c
+++ b/ext/pulse/pulsesink.c
@@ -58,6 +58,8 @@
#include <gst/pbutils/pbutils.h> /* only used for GST_PLUGINS_BASE_VERSION_* */
+#include <gst/glib-compat-private.h>
+
#include "pulsesink.h"
#include "pulseutil.h"
diff --git a/ext/soup/gstsouphttpclientsink.c b/ext/soup/gstsouphttpclientsink.c
index af238277f..d8f46df9d 100644
--- a/ext/soup/gstsouphttpclientsink.c
+++ b/ext/soup/gstsouphttpclientsink.c
@@ -42,6 +42,8 @@
#include <gst/base/gstbasesink.h>
#include "gstsouphttpclientsink.h"
+#include <gst/glib-compat-private.h>
+
GST_DEBUG_CATEGORY_STATIC (souphttpclientsink_dbg);
#define GST_CAT_DEFAULT souphttpclientsink_dbg
@@ -445,6 +447,20 @@ gst_soup_http_client_sink_get_times (GstBaseSink * sink, GstBuffer * buffer,
}
+static gboolean
+thread_ready_idle_cb (gpointer data)
+{
+ GstSoupHttpClientSink *souphttpsink = GST_SOUP_HTTP_CLIENT_SINK (data);
+
+ GST_LOG_OBJECT (souphttpsink, "thread ready");
+
+ g_mutex_lock (souphttpsink->mutex);
+ g_cond_signal (souphttpsink->cond);
+ g_mutex_unlock (souphttpsink->mutex);
+
+ return FALSE; /* only run once */
+}
+
static gpointer
thread_func (gpointer ptr)
{
@@ -452,7 +468,6 @@ thread_func (gpointer ptr)
GST_DEBUG ("thread start");
- souphttpsink->loop = g_main_loop_new (souphttpsink->context, TRUE);
g_main_loop_run (souphttpsink->loop);
GST_DEBUG ("thread quit");
@@ -468,12 +483,35 @@ gst_soup_http_client_sink_start (GstBaseSink * sink)
if (souphttpsink->prop_session) {
souphttpsink->session = souphttpsink->prop_session;
} else {
+ GSource *source;
GError *error = NULL;
souphttpsink->context = g_main_context_new ();
+ /* set up idle source to signal when the main loop is running and
+ * it's safe for ::stop() to call g_main_loop_quit() */
+ source = g_idle_source_new ();
+ g_source_set_callback (source, thread_ready_idle_cb, sink, NULL);
+ g_source_attach (source, souphttpsink->context);
+ g_source_unref (source);
+
+ souphttpsink->loop = g_main_loop_new (souphttpsink->context, TRUE);
+
+ g_mutex_lock (souphttpsink->mutex);
+
+ /* FIXME: error handling */
+#if !GLIB_CHECK_VERSION (2, 31, 0)
souphttpsink->thread = g_thread_create (thread_func, souphttpsink,
TRUE, &error);
+#else
+ souphttpsink->thread = g_thread_try_new ("souphttpclientsink-thread",
+ thread_func, souphttpsink, &error);
+#endif
+
+ GST_LOG_OBJECT (souphttpsink, "waiting for main loop thread to start up");
+ g_cond_wait (souphttpsink->cond, souphttpsink->mutex);
+ g_mutex_unlock (souphttpsink->mutex);
+ GST_LOG_OBJECT (souphttpsink, "main loop thread running");
souphttpsink->session =
soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
diff --git a/ext/wavpack/gstwavpackparse.c b/ext/wavpack/gstwavpackparse.c
index 50e1df933..4bb1e7e2b 100644
--- a/ext/wavpack/gstwavpackparse.c
+++ b/ext/wavpack/gstwavpackparse.c
@@ -41,6 +41,11 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+
+/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
#include <gst/gst.h>
#include <gst/gst-i18n-plugin.h>
diff --git a/gst-libs/gst/glib-compat-private.h b/gst-libs/gst/glib-compat-private.h
new file mode 100644
index 000000000..b9248e686
--- /dev/null
+++ b/gst-libs/gst/glib-compat-private.h
@@ -0,0 +1,135 @@
+/*
+ * glib-compat.c
+ * Functions copied from glib 2.10
+ *
+ * Copyright 2005 David Schleef <ds@schleef.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 __GLIB_COMPAT_PRIVATE_H__
+#define __GLIB_COMPAT_PRIVATE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#if !GLIB_CHECK_VERSION(2,25,0)
+
+#if defined (_MSC_VER) && !defined(_WIN64)
+typedef struct _stat32 GStatBuf;
+#else
+typedef struct stat GStatBuf;
+#endif
+
+#endif
+
+#if GLIB_CHECK_VERSION(2,26,0)
+#define GLIB_HAS_GDATETIME
+#endif
+
+/* See bug #651514 */
+#if GLIB_CHECK_VERSION(2,29,5)
+#define G_ATOMIC_POINTER_COMPARE_AND_EXCHANGE(a,b,c) \
+ g_atomic_pointer_compare_and_exchange ((a),(b),(c))
+#define G_ATOMIC_INT_COMPARE_AND_EXCHANGE(a,b,c) \
+ g_atomic_int_compare_and_exchange ((a),(b),(c))
+#else
+#define G_ATOMIC_POINTER_COMPARE_AND_EXCHANGE(a,b,c) \
+ g_atomic_pointer_compare_and_exchange ((volatile gpointer *)(a),(b),(c))
+#define G_ATOMIC_INT_COMPARE_AND_EXCHANGE(a,b,c) \
+ g_atomic_int_compare_and_exchange ((volatile int *)(a),(b),(c))
+#endif
+
+/* See bug #651514 */
+#if GLIB_CHECK_VERSION(2,29,5)
+#define G_ATOMIC_INT_ADD(a,b) g_atomic_int_add ((a),(b))
+#else
+#define G_ATOMIC_INT_ADD(a,b) g_atomic_int_exchange_and_add ((a),(b))
+#endif
+
+/* copies */
+
+#if GLIB_CHECK_VERSION (2, 31, 0)
+#define g_mutex_new gst_g_mutex_new
+static inline GMutex *
+gst_g_mutex_new (void)
+{
+ GMutex *mutex = g_slice_new (GMutex);
+ g_mutex_init (mutex);
+ return mutex;
+}
+#define g_mutex_free gst_g_mutex_free
+static inline void
+gst_g_mutex_free (GMutex *mutex)
+{
+ g_mutex_clear (mutex);
+ g_slice_free (GMutex, mutex);
+}
+#define g_static_rec_mutex_init gst_g_static_rec_mutex_init
+static inline void
+gst_g_static_rec_mutex_init (GStaticRecMutex *mutex)
+{
+ static const GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT;
+
+ *mutex = init_mutex;
+}
+#define g_cond_new gst_g_cond_new
+static inline GCond *
+gst_g_cond_new (void)
+{
+ GCond *cond = g_slice_new (GCond);
+ g_cond_init (cond);
+ return cond;
+}
+#define g_cond_free gst_g_cond_free
+static inline void
+gst_g_cond_free (GCond *cond)
+{
+ g_cond_clear (cond);
+ g_slice_free (GCond, cond);
+}
+#define g_cond_timed_wait gst_g_cond_timed_wait
+static inline gboolean
+gst_g_cond_timed_wait (GCond *cond, GMutex *mutex, GTimeVal *abs_time)
+{
+ gint64 end_time;
+
+ if (abs_time == NULL) {
+ g_cond_wait (cond, mutex);
+ return TRUE;
+ }
+
+ end_time = abs_time->tv_sec;
+ end_time *= 1000000;
+ end_time += abs_time->tv_usec;
+
+ /* would be nice if we had clock_rtoffset, but that didn't seem to
+ * make it into the kernel yet...
+ */
+ /* if CLOCK_MONOTONIC is not defined then g_get_montonic_time() and
+ * g_get_real_time() are returning the same clock and we'd add ~0
+ */
+ end_time += g_get_monotonic_time () - g_get_real_time ();
+ return g_cond_wait_until (cond, mutex, end_time);
+}
+#endif /* GLIB_CHECK_VERSION (2, 31, 0) */
+
+/* adaptations */
+
+G_END_DECLS
+
+#endif
diff --git a/gst/alpha/gstalpha.c b/gst/alpha/gstalpha.c
index c802c64e6..325bdc53b 100644
--- a/gst/alpha/gstalpha.c
+++ b/gst/alpha/gstalpha.c
@@ -145,6 +145,8 @@ GST_STATIC_PAD_TEMPLATE ("sink",
static GstStaticCaps gst_alpha_alpha_caps =
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, ARGB, BGRA, ABGR, RGBA }"));
+/* FIXME: why do we need our own lock for this? */
+#if !GLIB_CHECK_VERSION (2, 31, 0)
#define GST_ALPHA_LOCK(alpha) G_STMT_START { \
GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \
g_static_mutex_lock (&alpha->lock); \
@@ -155,6 +157,18 @@ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, ARGB, BGRA, ABGR, RGBA }"));
GST_LOG_OBJECT (alpha, "Unlocking alpha from thread %p", g_thread_self ()); \
g_static_mutex_unlock (&alpha->lock); \
} G_STMT_END
+#else
+#define GST_ALPHA_LOCK(alpha) G_STMT_START { \
+ GST_LOG_OBJECT (alpha, "Locking alpha from thread %p", g_thread_self ()); \
+ g_mutex_lock (&alpha->lock); \
+ GST_LOG_OBJECT (alpha, "Locked alpha from thread %p", g_thread_self ()); \
+} G_STMT_END
+
+#define GST_ALPHA_UNLOCK(alpha) G_STMT_START { \
+ GST_LOG_OBJECT (alpha, "Unlocking alpha from thread %p", g_thread_self ()); \
+ g_mutex_unlock (&alpha->lock); \
+} G_STMT_END
+#endif
static GstCaps *gst_alpha_transform_caps (GstBaseTransform * btrans,
GstPadDirection direction, GstCaps * caps, GstCaps * filter);
@@ -296,7 +310,11 @@ gst_alpha_init (GstAlpha * alpha)
alpha->black_sensitivity = DEFAULT_BLACK_SENSITIVITY;
alpha->white_sensitivity = DEFAULT_WHITE_SENSITIVITY;
+#if !GLIB_CHECK_VERSION (2, 31, 0)
g_static_mutex_init (&alpha->lock);
+#else
+ g_mutex_init (&alpha->lock);
+#endif
}
static void
@@ -304,7 +322,11 @@ gst_alpha_finalize (GObject * object)
{
GstAlpha *alpha = GST_ALPHA (object);
+#if !GLIB_CHECK_VERSION (2, 31, 0)
g_static_mutex_free (&alpha->lock);
+#else
+ g_mutex_clear (&alpha->lock);
+#endif
G_OBJECT_CLASS (parent_class)->finalize (object);
}
diff --git a/gst/alpha/gstalpha.h b/gst/alpha/gstalpha.h
index c24b753ba..48592f1bb 100644
--- a/gst/alpha/gstalpha.h
+++ b/gst/alpha/gstalpha.h
@@ -69,7 +69,11 @@ struct _GstAlpha
/* <private> */
/* caps */
+#if !GLIB_CHECK_VERSION (2, 31, 0)
GStaticMutex lock;
+#else
+ GMutex lock;
+#endif
gboolean in_sdtv, out_sdtv;
diff --git a/gst/audiofx/audiochebband.c b/gst/audiofx/audiochebband.c
index f0d2e34f0..cf431618e 100644
--- a/gst/audiofx/audiochebband.c
+++ b/gst/audiofx/audiochebband.c
@@ -83,6 +83,8 @@
#include "audiochebband.h"
+#include "gst/glib-compat-private.h"
+
#define GST_CAT_DEFAULT gst_audio_cheb_band_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
diff --git a/gst/audiofx/audiocheblimit.c b/gst/audiofx/audiocheblimit.c
index 250857ec0..9654a0564 100644
--- a/gst/audiofx/audiocheblimit.c
+++ b/gst/audiofx/audiocheblimit.c
@@ -79,6 +79,8 @@
#include "audiocheblimit.h"
+#include "gst/glib-compat-private.h"
+
#define GST_CAT_DEFAULT gst_audio_cheb_limit_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
diff --git a/gst/audiofx/audiofirfilter.c b/gst/audiofx/audiofirfilter.c
index 414768920..9fa21111b 100644
--- a/gst/audiofx/audiofirfilter.c
+++ b/gst/audiofx/audiofirfilter.c
@@ -56,6 +56,8 @@
#include "audiofirfilter.h"
+#include "gst/glib-compat-private.h"
+
#define GST_CAT_DEFAULT gst_audio_fir_filter_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
diff --git a/gst/audiofx/audioiirfilter.c b/gst/audiofx/audioiirfilter.c
index f411d8871..dc3c17efb 100644
--- a/gst/audiofx/audioiirfilter.c
+++ b/gst/audiofx/audioiirfilter.c
@@ -52,6 +52,8 @@
#include "audioiirfilter.h"
+#include "gst/glib-compat-private.h"
+
#define GST_CAT_DEFAULT gst_audio_iir_filter_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
diff --git a/gst/audiofx/audiowsincband.c b/gst/audiofx/audiowsincband.c
index 3f23b561a..cd50b0655 100644
--- a/gst/audiofx/audiowsincband.c
+++ b/gst/audiofx/audiowsincband.c
@@ -63,6 +63,8 @@
#include "audiowsincband.h"
+#include "gst/glib-compat-private.h"
+
#define GST_CAT_DEFAULT gst_gst_audio_wsincband_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
diff --git a/gst/audiofx/audiowsinclimit.c b/gst/audiofx/audiowsinclimit.c
index f13d2d020..7a9f5713b 100644
--- a/gst/audiofx/audiowsinclimit.c
+++ b/gst/audiofx/audiowsinclimit.c
@@ -63,6 +63,8 @@
#include "audiowsinclimit.h"
+#include "gst/glib-compat-private.h"
+
#define GST_CAT_DEFAULT gst_audio_wsinclimit_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
diff --git a/gst/audioparsers/gstaacparse.c b/gst/audioparsers/gstaacparse.c
index 5c0d88a06..789731599 100644
--- a/gst/audioparsers/gstaacparse.c
+++ b/gst/audioparsers/gstaacparse.c
@@ -44,6 +44,7 @@
#include <string.h>
+#include <gst/base/gstbitreader.h>
#include "gstaacparse.h"
@@ -52,7 +53,7 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("audio/mpeg, "
"framed = (boolean) true, " "mpegversion = (int) { 2, 4 }, "
- "stream-format = (string) { raw, adts, adif };"));
+ "stream-format = (string) { raw, adts, adif, loas };"));
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
@@ -65,10 +66,21 @@ GST_DEBUG_CATEGORY_STATIC (aacparse_debug);
#define ADIF_MAX_SIZE 40 /* Should be enough */
#define ADTS_MAX_SIZE 10 /* Should be enough */
+#define LOAS_MAX_SIZE 3 /* Should be enough */
#define AAC_FRAME_DURATION(parse) (GST_SECOND/parse->frames_per_sec)
+static const gint loas_sample_rate_table[32] = {
+ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
+ 16000, 12000, 11025, 8000, 7350, 0, 0, 0
+};
+
+static const gint loas_channels_table[32] = {
+ 0, 1, 2, 3, 4, 5, 6, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
static gboolean gst_aac_parse_start (GstBaseParse * parse);
static gboolean gst_aac_parse_stop (GstBaseParse * parse);
@@ -190,6 +202,9 @@ gst_aac_parse_set_src_caps (GstAacParse * aacparse, GstCaps * sink_caps)
case DSPAAC_HEADER_ADIF:
stream_format = "adif";
break;
+ case DSPAAC_HEADER_LOAS:
+ stream_format = "loas";
+ break;
default:
stream_format = NULL;
}
@@ -329,6 +344,8 @@ gst_aac_parse_check_adts_frame (GstAacParse * aacparse,
const guint8 * data, const guint avail, gboolean drain,
guint * framesize, guint * needed_data)
{
+ *needed_data = 0;
+
if (G_UNLIKELY (avail < 2))
return FALSE;
@@ -367,6 +384,292 @@ gst_aac_parse_check_adts_frame (GstAacParse * aacparse,
return FALSE;
}
+static gboolean
+gst_aac_parse_latm_get_value (GstAacParse * aacparse, GstBitReader * br,
+ guint32 * value)
+{
+ guint8 bytes, i, byte;
+
+ *value = 0;
+ if (!gst_bit_reader_get_bits_uint8 (br, &bytes, 2))
+ return FALSE;
+ for (i = 0; i < bytes; ++i) {
+ *value <<= 8;
+ if (!gst_bit_reader_get_bits_uint8 (br, &byte, 8))
+ return FALSE;
+ *value += byte;
+ }
+ return TRUE;
+}
+
+static gboolean
+gst_aac_parse_get_audio_object_type (GstAacParse * aacparse, GstBitReader * br,
+ guint8 * audio_object_type)
+{
+ if (!gst_bit_reader_get_bits_uint8 (br, audio_object_type, 5))
+ return FALSE;
+ if (*audio_object_type == 31) {
+ if (!gst_bit_reader_get_bits_uint8 (br, audio_object_type, 6))
+ return FALSE;
+ *audio_object_type += 32;
+ }
+ GST_LOG_OBJECT (aacparse, "audio object type %u", *audio_object_type);
+ return TRUE;
+}
+
+static gboolean
+gst_aac_parse_get_audio_sample_rate (GstAacParse * aacparse, GstBitReader * br,
+ gint * sample_rate)
+{
+ guint8 sampling_frequency_index;
+ if (!gst_bit_reader_get_bits_uint8 (br, &sampling_frequency_index, 4))
+ return FALSE;
+ GST_LOG_OBJECT (aacparse, "sampling_frequency_index: %u",
+ sampling_frequency_index);
+ if (sampling_frequency_index == 0xf) {
+ guint32 sampling_rate;
+ if (!gst_bit_reader_get_bits_uint32 (br, &sampling_rate, 24))
+ return FALSE;
+ *sample_rate = sampling_rate;
+ } else {
+ *sample_rate = loas_sample_rate_table[sampling_frequency_index];
+ if (!*sample_rate)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* See table 1.13 in ISO/IEC 14496-3 */
+static gboolean
+gst_aac_parse_read_loas_audio_specific_config (GstAacParse * aacparse,
+ GstBitReader * br, gint * sample_rate, gint * channels, guint32 * bits)
+{
+ guint8 audio_object_type, channel_configuration;
+
+ if (!gst_aac_parse_get_audio_object_type (aacparse, br, &audio_object_type))
+ return FALSE;
+
+ if (!gst_aac_parse_get_audio_sample_rate (aacparse, br, sample_rate))
+ return FALSE;
+
+ if (!gst_bit_reader_get_bits_uint8 (br, &channel_configuration, 4))
+ return FALSE;
+ GST_LOG_OBJECT (aacparse, "channel_configuration: %d", channel_configuration);
+ *channels = loas_channels_table[channel_configuration];
+ if (!*channels)
+ return FALSE;
+
+ if (audio_object_type == 5) {
+ GST_LOG_OBJECT (aacparse,
+ "Audio object type 5, so rereading sampling rate...");
+ if (!gst_aac_parse_get_audio_sample_rate (aacparse, br, sample_rate))
+ return FALSE;
+ }
+
+ GST_INFO_OBJECT (aacparse, "Found LOAS config: %d Hz, %d channels",
+ *sample_rate, *channels);
+
+ /* There's LOTS of stuff next, but we ignore it for now as we have
+ what we want (sample rate and number of channels */
+ GST_DEBUG_OBJECT (aacparse,
+ "Need more code to parse humongous LOAS data, currently ignored");
+ if (bits)
+ *bits = 0;
+ return TRUE;
+}
+
+
+static gboolean
+gst_aac_parse_read_loas_config (GstAacParse * aacparse, const guint8 * data,
+ guint avail, gint * sample_rate, gint * channels, gint * version)
+{
+ GstBitReader br;
+ guint8 u8, v, vA;
+
+ /* No version in the bitstream, but the spec has LOAS in the MPEG-4 section */
+ if (version)
+ *version = 4;
+
+ gst_bit_reader_init (&br, data, avail);
+
+ /* skip sync word (11 bits) and size (13 bits) */
+ gst_bit_reader_skip (&br, 11 + 13);
+
+ /* First bit is "use last config" */
+ if (!gst_bit_reader_get_bits_uint8 (&br, &u8, 1))
+ return FALSE;
+ if (u8) {
+ GST_DEBUG_OBJECT (aacparse, "Frame uses previous config");
+ if (!aacparse->sample_rate || !aacparse->channels) {
+ GST_WARNING_OBJECT (aacparse, "No previous config to use");
+ }
+ *sample_rate = aacparse->sample_rate;
+ *channels = aacparse->channels;
+ return TRUE;
+ }
+
+ GST_DEBUG_OBJECT (aacparse, "Frame contains new config");
+
+ if (!gst_bit_reader_get_bits_uint8 (&br, &v, 1))
+ return FALSE;
+ if (v) {
+ if (!gst_bit_reader_get_bits_uint8 (&br, &vA, 1))
+ return FALSE;
+ } else
+ vA = 0;
+
+ GST_LOG_OBJECT (aacparse, "v %d, vA %d", v, vA);
+ if (vA == 0) {
+ guint8 same_time, subframes, num_program, prog;
+ if (v == 1) {
+ guint32 value;
+ if (!gst_aac_parse_latm_get_value (aacparse, &br, &value))
+ return FALSE;
+ }
+ if (!gst_bit_reader_get_bits_uint8 (&br, &same_time, 1))
+ return FALSE;
+ if (!gst_bit_reader_get_bits_uint8 (&br, &subframes, 6))
+ return FALSE;
+ if (!gst_bit_reader_get_bits_uint8 (&br, &num_program, 4))
+ return FALSE;
+ GST_LOG_OBJECT (aacparse, "same_time %d, subframes %d, num_program %d",
+ same_time, subframes, num_program);
+
+ for (prog = 0; prog <= num_program; ++prog) {
+ guint8 num_layer, layer;
+ if (!gst_bit_reader_get_bits_uint8 (&br, &num_layer, 3))
+ return FALSE;
+ GST_LOG_OBJECT (aacparse, "Program %d: %d layers", prog, num_layer);
+
+ for (layer = 0; layer <= num_layer; ++layer) {
+ guint8 use_same_config;
+ if (prog == 0 && layer == 0) {
+ use_same_config = 0;
+ } else {
+ if (!gst_bit_reader_get_bits_uint8 (&br, &use_same_config, 1))
+ return FALSE;
+ }
+ if (!use_same_config) {
+ if (v == 0) {
+ if (!gst_aac_parse_read_loas_audio_specific_config (aacparse, &br,
+ sample_rate, channels, NULL))
+ return FALSE;
+ } else {
+ guint32 bits, asc_len;
+ if (!gst_aac_parse_latm_get_value (aacparse, &br, &asc_len))
+ return FALSE;
+ if (!gst_aac_parse_read_loas_audio_specific_config (aacparse, &br,
+ sample_rate, channels, &bits))
+ return FALSE;
+ asc_len -= bits;
+ gst_bit_reader_skip (&br, asc_len);
+ }
+ }
+ }
+ }
+ GST_WARNING_OBJECT (aacparse, "More data ignored");
+ } else {
+ GST_WARNING_OBJECT (aacparse, "Spec says \"TBD\"...");
+ }
+ return TRUE;
+}
+
+/**
+ * gst_aac_parse_loas_get_frame_len:
+ * @data: block of data containing a LOAS header.
+ *
+ * This function calculates LOAS frame length from the given header.
+ *
+ * Returns: size of the LOAS frame.
+ */
+static inline guint
+gst_aac_parse_loas_get_frame_len (const guint8 * data)
+{
+ return (((data[1] & 0x1f) << 8) | data[2]) + 3;
+}
+
+
+/**
+ * gst_aac_parse_check_loas_frame:
+ * @aacparse: #GstAacParse.
+ * @data: Data to be checked.
+ * @avail: Amount of data passed.
+ * @framesize: If valid LOAS frame was found, this will be set to tell the
+ * found frame size in bytes.
+ * @needed_data: If frame was not found, this may be set to tell how much
+ * more data is needed in the next round to detect the frame
+ * reliably. This may happen when a frame header candidate
+ * is found but it cannot be guaranteed to be the header without
+ * peeking the following data.
+ *
+ * Check if the given data contains contains LOAS frame. The algorithm
+ * will examine LOAS frame header and calculate the frame size. Also, another
+ * consecutive LOAS frame header need to be present after the found frame.
+ * Otherwise the data is not considered as a valid LOAS frame. However, this
+ * "extra check" is omitted when EOS has been received. In this case it is
+ * enough when data[0] contains a valid LOAS header.
+ *
+ * This function may set the #needed_data to indicate that a possible frame
+ * candidate has been found, but more data (#needed_data bytes) is needed to
+ * be absolutely sure. When this situation occurs, FALSE will be returned.
+ *
+ * When a valid frame is detected, this function will use
+ * gst_base_parse_set_min_frame_size() function from #GstBaseParse class
+ * to set the needed bytes for next frame.This way next data chunk is already
+ * of correct size.
+ *
+ * LOAS can have three different formats, if I read the spec correctly. Only
+ * one of them is supported here, as the two samples I have use this one.
+ *
+ * Returns: TRUE if the given data contains a valid LOAS header.
+ */
+static gboolean
+gst_aac_parse_check_loas_frame (GstAacParse * aacparse,
+ const guint8 * data, const guint avail, gboolean drain,
+ guint * framesize, guint * needed_data)
+{
+ *needed_data = 0;
+
+ /* 3 byte header */
+ if (G_UNLIKELY (avail < 3))
+ return FALSE;
+
+ if ((data[0] == 0x56) && ((data[1] & 0xe0) == 0xe0)) {
+ *framesize = gst_aac_parse_loas_get_frame_len (data);
+ GST_DEBUG_OBJECT (aacparse, "Found %u byte LOAS frame", *framesize);
+
+ /* In EOS mode this is enough. No need to examine the data further.
+ We also relax the check when we have sync, on the assumption that
+ if we're not looking at random data, we have a much higher chance
+ to get the correct sync, and this avoids losing two frames when
+ a single bit corruption happens. */
+ if (drain || !GST_BASE_PARSE_LOST_SYNC (aacparse)) {
+ return TRUE;
+ }
+
+ if (*framesize + LOAS_MAX_SIZE > avail) {
+ /* We have found a possible frame header candidate, but can't be
+ sure since we don't have enough data to check the next frame */
+ GST_DEBUG ("NEED MORE DATA: we need %d, available %d",
+ *framesize + LOAS_MAX_SIZE, avail);
+ *needed_data = *framesize + LOAS_MAX_SIZE;
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
+ *framesize + LOAS_MAX_SIZE);
+ return FALSE;
+ }
+
+ if ((data[*framesize] == 0x56) && ((data[*framesize + 1] & 0xe0) == 0xe0)) {
+ guint nextlen = gst_aac_parse_loas_get_frame_len (data + (*framesize));
+
+ GST_LOG ("LOAS frame found, len: %d bytes", *framesize);
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
+ nextlen + LOAS_MAX_SIZE);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
/* caller ensure sufficient data */
static inline void
gst_aac_parse_parse_adts_header (GstAacParse * aacparse, const guint8 * data,
@@ -412,7 +715,7 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
guint * framesize, gint * skipsize)
{
gboolean found = FALSE;
- guint need_data = 0;
+ guint need_data_adts = 0, need_data_loas;
guint i = 0;
GST_DEBUG_OBJECT (aacparse, "Parsing header data");
@@ -421,12 +724,16 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
stream */
/* Can we even parse the header? */
- if (avail < ADTS_MAX_SIZE)
+ if (avail < MAX (ADTS_MAX_SIZE, LOAS_MAX_SIZE)) {
+ GST_DEBUG_OBJECT (aacparse, "Not enough data to check");
return FALSE;
+ }
for (i = 0; i < avail - 4; i++) {
if (((data[i] == 0xff) && ((data[i + 1] & 0xf6) == 0xf0)) ||
+ ((data[0] == 0x56) && ((data[1] & 0xe0) == 0xe0)) ||
strncmp ((char *) data + i, "ADIF", 4) == 0) {
+ GST_DEBUG_OBJECT (aacparse, "Found ADIF signature at offset %u", i);
found = TRUE;
if (i) {
@@ -446,7 +753,7 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
}
if (gst_aac_parse_check_adts_frame (aacparse, data, avail, drain,
- framesize, &need_data)) {
+ framesize, &need_data_adts)) {
gint rate, channels;
GST_INFO ("ADTS ID: %d, framesize: %d", (data[1] & 0x08) >> 3, *framesize);
@@ -464,7 +771,38 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
gst_base_parse_set_syncable (GST_BASE_PARSE (aacparse), TRUE);
return TRUE;
- } else if (need_data) {
+ }
+
+ if (gst_aac_parse_check_loas_frame (aacparse, data, avail, drain,
+ framesize, &need_data_loas)) {
+ gint rate, channels;
+
+ GST_INFO ("LOAS, framesize: %d", *framesize);
+
+ aacparse->header_type = DSPAAC_HEADER_LOAS;
+
+ if (!gst_aac_parse_read_loas_config (aacparse, data, avail, &rate,
+ &channels, &aacparse->mpegversion)) {
+ GST_WARNING_OBJECT (aacparse, "Error reading LOAS config");
+ return FALSE;
+ }
+
+ if (rate && channels) {
+ gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse), rate,
+ aacparse->frame_samples, 2, 2);
+
+ GST_DEBUG ("LOAS: samplerate %d, channels %d, objtype %d, version %d",
+ rate, channels, aacparse->object_type, aacparse->mpegversion);
+ aacparse->sample_rate = rate;
+ aacparse->channels = channels;
+ }
+
+ gst_base_parse_set_syncable (GST_BASE_PARSE (aacparse), TRUE);
+
+ return TRUE;
+ }
+
+ if (need_data_adts || need_data_loas) {
/* This tells the parent class not to skip any data */
*skipsize = 0;
return FALSE;
@@ -612,6 +950,18 @@ gst_aac_parse_check_valid_frame (GstBaseParse * parse,
needed_data);
}
+ } else if (aacparse->header_type == DSPAAC_HEADER_LOAS) {
+ guint needed_data = 1024;
+
+ ret = gst_aac_parse_check_loas_frame (aacparse, data,
+ size, GST_BASE_PARSE_DRAINING (parse), framesize, &needed_data);
+
+ if (!ret) {
+ GST_DEBUG ("buffer didn't contain valid frame");
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
+ needed_data);
+ }
+
} else {
GST_DEBUG ("buffer didn't contain valid frame");
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
@@ -632,7 +982,7 @@ gst_aac_parse_check_valid_frame (GstBaseParse * parse,
*
* Also determines frame overhead.
* ADTS streams have a 7 byte header in each frame. MP4 and ADIF streams don't have
- * a per-frame header.
+ * a per-frame header. LOAS has 3 bytes.
*
* We're making a couple of simplifying assumptions:
*
@@ -659,36 +1009,70 @@ gst_aac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
aacparse = GST_AAC_PARSE (parse);
buffer = frame->buffer;
- if (G_UNLIKELY (aacparse->header_type != DSPAAC_HEADER_ADTS))
- return ret;
+ if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
+ /* see above */
+ frame->overhead = 7;
- /* see above */
- frame->overhead = 7;
+ data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+ gst_aac_parse_parse_adts_header (aacparse, data,
+ &rate, &channels, NULL, NULL);
+ gst_buffer_unmap (buffer, data, size);
- data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
- gst_aac_parse_parse_adts_header (aacparse, data,
- &rate, &channels, NULL, NULL);
- gst_buffer_unmap (buffer, data, size);
-
- GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
+ GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
- if (G_UNLIKELY (rate != aacparse->sample_rate
- || channels != aacparse->channels)) {
- GstCaps *sinkcaps;
+ if (G_UNLIKELY (rate != aacparse->sample_rate
+ || channels != aacparse->channels)) {
+ GstCaps *sinkcaps;
- aacparse->sample_rate = rate;
- aacparse->channels = channels;
+ aacparse->sample_rate = rate;
+ aacparse->channels = channels;
- sinkcaps = gst_pad_get_current_caps (GST_BASE_PARSE (aacparse)->sinkpad);
- if (!gst_aac_parse_set_src_caps (aacparse, sinkcaps)) {
- /* If linking fails, we need to return appropriate error */
+ sinkcaps = gst_pad_get_current_caps (GST_BASE_PARSE (aacparse)->sinkpad);
+ if (!gst_aac_parse_set_src_caps (aacparse, sinkcaps)) {
+ /* If linking fails, we need to return appropriate error */
+ ret = GST_FLOW_NOT_LINKED;
+ }
gst_caps_unref (sinkcaps);
- ret = GST_FLOW_NOT_LINKED;
+
+ gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
+ aacparse->sample_rate, aacparse->frame_samples, 2, 2);
}
- gst_caps_unref (sinkcaps);
+ } else if (aacparse->header_type == DSPAAC_HEADER_LOAS) {
+ gboolean setcaps = FALSE;
+
+ /* see above */
+ frame->overhead = 3;
+
+ data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+ if (!gst_aac_parse_read_loas_config (aacparse, data, size, &rate, &channels,
+ NULL)) {
+ GST_WARNING_OBJECT (aacparse, "Error reading LOAS config");
+ } else if (G_UNLIKELY (rate != aacparse->sample_rate
+ || channels != aacparse->channels)) {
+ aacparse->sample_rate = rate;
+ aacparse->channels = channels;
+ setcaps = TRUE;
+ GST_INFO_OBJECT (aacparse, "New LOAS config: %d Hz, %d channels", rate,
+ channels);
+ }
+ gst_buffer_unmap (buffer, data, size);
+
+ /* We want to set caps both at start, and when rate/channels change.
+ Since only some LOAS frames have that info, we may receive frames
+ before knowing about rate/channels. */
+ if (setcaps
+ || !gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (aacparse))) {
+ GstCaps *sinkcaps =
+ gst_pad_get_current_caps (GST_BASE_PARSE (aacparse)->sinkpad);
+ if (!gst_aac_parse_set_src_caps (aacparse, sinkcaps)) {
+ /* If linking fails, we need to return appropriate error */
+ ret = GST_FLOW_NOT_LINKED;
+ }
+ gst_caps_unref (sinkcaps);
- gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
- aacparse->sample_rate, aacparse->frame_samples, 2, 2);
+ gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
+ aacparse->sample_rate, aacparse->frame_samples, 2, 2);
+ }
}
return ret;
diff --git a/gst/audioparsers/gstaacparse.h b/gst/audioparsers/gstaacparse.h
index 1907c2e44..11f75e683 100644
--- a/gst/audioparsers/gstaacparse.h
+++ b/gst/audioparsers/gstaacparse.h
@@ -45,6 +45,7 @@ G_BEGIN_DECLS
* @DSPAAC_HEADER_UNKNOWN: Unknown (not recognized) header.
* @DSPAAC_HEADER_ADIF: ADIF header found.
* @DSPAAC_HEADER_ADTS: ADTS header found.
+ * @DSPAAC_HEADER_LOAS: LOAS header found.
* @DSPAAC_HEADER_NONE: Raw stream, no header.
*
* Type header enumeration set in #header_type.
@@ -54,6 +55,7 @@ typedef enum {
DSPAAC_HEADER_UNKNOWN,
DSPAAC_HEADER_ADIF,
DSPAAC_HEADER_ADTS,
+ DSPAAC_HEADER_LOAS,
DSPAAC_HEADER_NONE
} GstAacHeaderType;
diff --git a/gst/audioparsers/gstac3parse.c b/gst/audioparsers/gstac3parse.c
index 26b619585..1c4b85326 100644
--- a/gst/audioparsers/gstac3parse.c
+++ b/gst/audioparsers/gstac3parse.c
@@ -324,7 +324,9 @@ gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
/* spec not quite clear here: decoder should decode if less than 8,
* but seemingly only defines 6 and 8 cases */
- if (bsid > 8) {
+ /* Files with 9 and 10 happen, and seem to comply with the <= 8
+ format, so let them through. The spec says nothing about 9 and 10 */
+ if (bsid > 10) {
GST_DEBUG_OBJECT (ac3parse, "unexpected bsid=%d", bsid);
goto cleanup;
} else if (bsid != 8 && bsid != 6) {
diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c
index da0943af7..1c2384b0b 100644
--- a/gst/avi/gstavidemux.c
+++ b/gst/avi/gstavidemux.c
@@ -45,6 +45,10 @@
#include "config.h"
#endif
+/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
#include <string.h>
#include <stdio.h>
diff --git a/gst/avi/gstavimux.c b/gst/avi/gstavimux.c
index bea410e66..f34046e60 100644
--- a/gst/avi/gstavimux.c
+++ b/gst/avi/gstavimux.c
@@ -190,10 +190,10 @@ static GstStaticPadTemplate audio_sink_factory =
static void gst_avi_mux_pad_reset (GstAviPad * avipad, gboolean free);
-static GstFlowReturn gst_avi_mux_collect_pads (GstCollectPads * pads,
+static GstFlowReturn gst_avi_mux_collect_pads (GstCollectPads2 * pads,
GstAviMux * avimux);
-static gboolean gst_avi_mux_handle_event (GstPad * pad, GstObject * parent,
- GstEvent * event);
+static gboolean gst_avi_mux_handle_event (GstCollectPads2 * pad,
+ GstCollectData2 * data, GstEvent * event, gpointer user_data);
static GstPad *gst_avi_mux_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
static void gst_avi_mux_release_pad (GstElement * element, GstPad * pad);
@@ -378,10 +378,13 @@ gst_avi_mux_init (GstAviMux * avimux)
/* property */
avimux->enable_large_avi = DEFAULT_BIGFILE;
- avimux->collect = gst_collect_pads_new ();
- gst_collect_pads_set_function (avimux->collect,
- (GstCollectPadsFunction) (GST_DEBUG_FUNCPTR (gst_avi_mux_collect_pads)),
+ avimux->collect = gst_collect_pads2_new ();
+ gst_collect_pads2_set_function (avimux->collect,
+ (GstCollectPads2Function) (GST_DEBUG_FUNCPTR (gst_avi_mux_collect_pads)),
avimux);
+ gst_collect_pads2_set_event_function (avimux->collect,
+ (GstCollectPads2EventFunction) (GST_DEBUG_FUNCPTR
+ (gst_avi_mux_handle_event)), avimux);
/* set to clean state */
gst_avi_mux_reset (avimux);
@@ -977,15 +980,9 @@ gst_avi_mux_request_new_pad (GstElement * element,
g_free (name);
- avipad->collect = gst_collect_pads_add_pad (avimux->collect,
- newpad, sizeof (GstAviCollectData), NULL);
+ avipad->collect = gst_collect_pads2_add_pad (avimux->collect,
+ newpad, sizeof (GstAviCollectData));
((GstAviCollectData *) (avipad->collect))->avipad = avipad;
- /* FIXME: hacked way to override/extend the event function of
- * GstCollectPads; because it sets its own event function giving the
- * element no access to events */
- avimux->collect_event = GST_PAD_EVENTFUNC (newpad);
- gst_pad_set_event_function (newpad,
- GST_DEBUG_FUNCPTR (gst_avi_mux_handle_event));
if (!gst_element_add_pad (element, newpad))
goto pad_add_failed;
@@ -1038,7 +1035,7 @@ gst_avi_mux_release_pad (GstElement * element, GstPad * pad)
* as it also represent number of streams present */
avipad->collect = NULL;
GST_DEBUG_OBJECT (avimux, "removed pad '%s'", GST_PAD_NAME (pad));
- gst_collect_pads_remove_pad (avimux->collect, pad);
+ gst_collect_pads2_remove_pad (avimux->collect, pad);
gst_element_remove_pad (element, pad);
/* if not started yet, we can remove any sign this pad ever existed */
/* in this case _start will take care of the real pad count */
@@ -1833,12 +1830,13 @@ gst_avi_mux_restart_file (GstAviMux * avimux)
/* handle events (search) */
static gboolean
-gst_avi_mux_handle_event (GstPad * pad, GstObject * parent, GstEvent * event)
+gst_avi_mux_handle_event (GstCollectPads2 * pads, GstCollectData2 * data,
+ GstEvent * event, gpointer user_data)
{
GstAviMux *avimux;
- gboolean ret = TRUE;
+ gboolean ret = FALSE;
- avimux = GST_AVI_MUX (parent);
+ avimux = GST_AVI_MUX (user_data);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CAPS:
@@ -1850,15 +1848,15 @@ gst_avi_mux_handle_event (GstPad * pad, GstObject * parent, GstEvent * event)
gst_event_parse_caps (event, &caps);
/* find stream data */
- collect_pad = (GstAviCollectData *) gst_pad_get_element_private (pad);
+ collect_pad = (GstAviCollectData *) data;
g_assert (collect_pad);
avipad = (GstAviVideoPad *) collect_pad->avipad;
g_assert (avipad);
if (avipad->parent.is_video) {
- ret = gst_avi_mux_vidsink_set_caps (pad, caps);
+ ret = gst_avi_mux_vidsink_set_caps (GST_PAD (avipad), caps);
} else {
- ret = gst_avi_mux_audsink_set_caps (pad, caps);
+ ret = gst_avi_mux_audsink_set_caps (GST_PAD (avipad), caps);
}
break;
}
@@ -1875,10 +1873,7 @@ gst_avi_mux_handle_event (GstPad * pad, GstObject * parent, GstEvent * event)
break;
}
- /* now GstCollectPads can take care of the rest, e.g. EOS */
- if (ret)
- ret = avimux->collect_event (pad, parent, event);
-
+ /* now GstCollectPads2 can take care of the rest, e.g. EOS */
return ret;
}
@@ -1909,7 +1904,7 @@ gst_avi_mux_do_buffer (GstAviMux * avimux, GstAviPad * avipad)
guint flags;
gsize datasize;
- data = gst_collect_pads_pop (avimux->collect, avipad->collect);
+ data = gst_collect_pads2_pop (avimux->collect, avipad->collect);
/* arrange downstream running time */
data = gst_buffer_make_writable (data);
GST_BUFFER_TIMESTAMP (data) =
@@ -2033,7 +2028,7 @@ gst_avi_mux_do_one_buffer (GstAviMux * avimux)
if (!avipad->hdr.fcc_handler)
goto not_negotiated;
- buffer = gst_collect_pads_peek (avimux->collect, avipad->collect);
+ buffer = gst_collect_pads2_peek (avimux->collect, avipad->collect);
if (!buffer)
continue;
time = GST_BUFFER_TIMESTAMP (buffer);
@@ -2046,7 +2041,7 @@ gst_avi_mux_do_one_buffer (GstAviMux * avimux)
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
GST_DEBUG_OBJECT (avimux, "clipping buffer on pad %s outside segment",
GST_PAD_NAME (avipad->collect->pad));
- buffer = gst_collect_pads_pop (avimux->collect, avipad->collect);
+ buffer = gst_collect_pads2_pop (avimux->collect, avipad->collect);
gst_buffer_unref (buffer);
return GST_FLOW_OK;
}
@@ -2085,7 +2080,7 @@ not_negotiated:
}
static GstFlowReturn
-gst_avi_mux_collect_pads (GstCollectPads * pads, GstAviMux * avimux)
+gst_avi_mux_collect_pads (GstCollectPads2 * pads, GstAviMux * avimux)
{
GstFlowReturn res;
@@ -2144,12 +2139,12 @@ gst_avi_mux_change_state (GstElement * element, GstStateChange transition)
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
- gst_collect_pads_start (avimux->collect);
+ gst_collect_pads2_start (avimux->collect);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_collect_pads_stop (avimux->collect);
+ gst_collect_pads2_stop (avimux->collect);
break;
default:
break;
diff --git a/gst/avi/gstavimux.h b/gst/avi/gstavimux.h
index 0d903928e..cb0cdb7b3 100644
--- a/gst/avi/gstavimux.h
+++ b/gst/avi/gstavimux.h
@@ -23,7 +23,7 @@
#include <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
+#include <gst/base/gstcollectpads2.h>
#include <gst/riff/riff-ids.h>
#include "avi-ids.h"
@@ -74,7 +74,7 @@ typedef GstFlowReturn (*GstAviPadHook) (GstAviMux * avi, GstAviPad * avipad,
struct _GstAviPad {
/* do not extend, link to it */
/* is NULL if original sink request pad has been removed */
- GstCollectData *collect;
+ GstCollectData2 *collect;
/* type */
gboolean is_video;
@@ -129,7 +129,7 @@ typedef struct _GstAviAudioPad {
typedef struct _GstAviCollectData {
/* extend the CollectData */
- GstCollectData collect;
+ GstCollectData2 collect;
GstAviPad *avipad;
} GstAviCollectData;
@@ -143,8 +143,7 @@ struct _GstAviMux {
GSList *sinkpads;
/* video restricted to 1 pad */
guint video_pads, audio_pads;
- GstCollectPads *collect;
- GstPadEventFunction collect_event;
+ GstCollectPads2 *collect;
/* the AVI header */
/* still some single stream video data in mux struct */
diff --git a/gst/equalizer/gstiirequalizer.c b/gst/equalizer/gstiirequalizer.c
index ee7ffee22..da7f8e43c 100644
--- a/gst/equalizer/gstiirequalizer.c
+++ b/gst/equalizer/gstiirequalizer.c
@@ -32,6 +32,8 @@
#include "gstiirequalizer3bands.h"
#include "gstiirequalizer10bands.h"
+#include "gst/glib-compat-private.h"
+
GST_DEBUG_CATEGORY (equalizer_debug);
#define GST_CAT_DEFAULT equalizer_debug
diff --git a/gst/flv/gstflvdemux.c b/gst/flv/gstflvdemux.c
index 324c2189c..7603dbaf8 100644
--- a/gst/flv/gstflvdemux.c
+++ b/gst/flv/gstflvdemux.c
@@ -34,6 +34,10 @@
#include "config.h"
#endif
+/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
#include "gstflvdemux.h"
#include "gstflvmux.h"
diff --git a/gst/flv/gstflvmux.c b/gst/flv/gstflvmux.c
index a7189e2ea..2249d3044 100644
--- a/gst/flv/gstflvmux.c
+++ b/gst/flv/gstflvmux.c
@@ -89,7 +89,11 @@ G_DEFINE_TYPE_WITH_CODE (GstFlvMux, gst_flv_mux, GST_TYPE_ELEMENT,
static void gst_flv_mux_finalize (GObject * object);
static GstFlowReturn
-gst_flv_mux_collected (GstCollectPads * pads, gpointer user_data);
+gst_flv_mux_handle_buffer (GstCollectPads2 * pads, GstCollectData2 * cdata,
+ GstBuffer * buf, gpointer user_data);
+static gboolean
+gst_flv_mux_handle_sink_event (GstCollectPads2 * pads, GstCollectData2 * data,
+ GstEvent * event, gpointer user_data);
static gboolean gst_flv_mux_handle_src_event (GstPad * pad, GstObject * parent,
GstEvent * event);
@@ -209,9 +213,13 @@ gst_flv_mux_init (GstFlvMux * mux)
mux->new_tags = FALSE;
- mux->collect = gst_collect_pads_new ();
- gst_collect_pads_set_function (mux->collect,
- (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_flv_mux_collected), mux);
+ mux->collect = gst_collect_pads2_new ();
+ gst_collect_pads2_set_buffer_function (mux->collect,
+ GST_DEBUG_FUNCPTR (gst_flv_mux_handle_buffer), mux);
+ gst_collect_pads2_set_event_function (mux->collect,
+ GST_DEBUG_FUNCPTR (gst_flv_mux_handle_sink_event), mux);
+ gst_collect_pads2_set_clip_function (mux->collect,
+ GST_DEBUG_FUNCPTR (gst_collect_pads2_clip_running_time), mux);
gst_flv_mux_reset (GST_ELEMENT (mux));
}
@@ -273,11 +281,11 @@ gst_flv_mux_handle_src_event (GstPad * pad, GstObject * parent,
}
static gboolean
-gst_flv_mux_handle_sink_event (GstPad * pad, GstObject * parent,
- GstEvent * event)
+gst_flv_mux_handle_sink_event (GstCollectPads2 * pads, GstCollectData2 * data,
+ GstEvent * event, gpointer user_data)
{
- GstFlvMux *mux = GST_FLV_MUX (parent);
- gboolean ret = TRUE;
+ GstFlvMux *mux = GST_FLV_MUX (user_data);
+ gboolean ret = FALSE;
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CAPS:
@@ -288,13 +296,13 @@ gst_flv_mux_handle_sink_event (GstPad * pad, GstObject * parent,
gst_event_parse_caps (event, &caps);
/* find stream data */
- flvpad = (GstFlvPad *) gst_pad_get_element_private (pad);
+ flvpad = (GstFlvPad *) data;
g_assert (flvpad);
if (flvpad->video) {
- ret = gst_flv_mux_video_pad_setcaps (pad, caps);
+ ret = gst_flv_mux_video_pad_setcaps (data->pad, caps);
} else {
- ret = gst_flv_mux_audio_pad_setcaps (pad, caps);
+ ret = gst_flv_mux_audio_pad_setcaps (data->pad, caps);
}
/* and eat */
ret = FALSE;
@@ -315,10 +323,7 @@ gst_flv_mux_handle_sink_event (GstPad * pad, GstObject * parent,
break;
}
- /* now GstCollectPads can take care of the rest, e.g. EOS */
- if (ret)
- ret = mux->collect_event (pad, parent, event);
-
+ /* now GstCollectPads2 can take care of the rest, e.g. EOS */
return ret;
}
@@ -567,20 +572,12 @@ gst_flv_mux_request_new_pad (GstElement * element,
pad = gst_pad_new_from_template (templ, name);
cpad = (GstFlvPad *)
- gst_collect_pads_add_pad (mux->collect, pad, sizeof (GstFlvPad), NULL);
+ gst_collect_pads2_add_pad (mux->collect, pad, sizeof (GstFlvPad));
cpad->audio_codec_data = NULL;
cpad->video_codec_data = NULL;
gst_flv_mux_reset_pad (mux, cpad, video);
- /* FIXME: hacked way to override/extend the event function of
- * GstCollectPads; because it sets its own event function giving the
- * element no access to events.
- */
- mux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (pad);
- gst_pad_set_event_function (pad,
- GST_DEBUG_FUNCPTR (gst_flv_mux_handle_sink_event));
-
gst_pad_set_active (pad, TRUE);
gst_element_add_pad (element, pad);
@@ -594,7 +591,7 @@ gst_flv_mux_release_pad (GstElement * element, GstPad * pad)
GstFlvPad *cpad = (GstFlvPad *) gst_pad_get_element_private (pad);
gst_flv_mux_reset_pad (mux, cpad, cpad->video);
- gst_collect_pads_remove_pad (mux->collect, pad);
+ gst_collect_pads2_remove_pad (mux->collect, pad);
gst_element_remove_pad (element, pad);
}
@@ -677,7 +674,7 @@ gst_flv_mux_create_number_script_value (const gchar * name, gdouble value)
}
static GstBuffer *
-gst_flv_mux_create_metadata (GstFlvMux * mux)
+gst_flv_mux_create_metadata (GstFlvMux * mux, gboolean full)
{
const GstTagList *tags;
GstBuffer *script_tag, *tmp;
@@ -719,6 +716,9 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
GST_WRITE_UINT32_BE (data + 1, n_tags);
script_tag = gst_buffer_join (script_tag, tmp);
+ if (!full)
+ goto tags;
+
/* Some players expect the 'duration' to be always set. Fill it out later,
after querying the pads or after getting EOS */
if (!mux->streamable) {
@@ -739,6 +739,7 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
GST_DEBUG_OBJECT (mux, "not preallocating index, streamable mode");
}
+tags:
for (i = 0; tags && i < n_tags; i++) {
const gchar *tag_name =
gst_structure_nth_field_name ((const GstStructure *) tags, i);
@@ -777,12 +778,15 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
}
}
+ if (!full)
+ goto end;
+
if (mux->duration == GST_CLOCK_TIME_NONE) {
GSList *l;
guint64 dur;
for (l = mux->collect->data; l; l = l->next) {
- GstCollectData *cdata = l->data;
+ GstCollectData2 *cdata = l->data;
if (gst_pad_peer_query_duration (cdata->pad, GST_FORMAT_TIME,
(gint64 *) & dur) && dur != GST_CLOCK_TIME_NONE) {
@@ -958,6 +962,14 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
tags_written++;
}
+end:
+
+ if (!tags_written) {
+ gst_buffer_unref (script_tag);
+ script_tag = NULL;
+ goto exit;
+ }
+
_gst_buffer_new_and_alloc (2 + 0 + 1, &tmp, &data);
data[0] = 0; /* 0 byte size */
data[1] = 0;
@@ -977,6 +989,7 @@ gst_flv_mux_create_metadata (GstFlvMux * mux)
GST_WRITE_UINT32_BE (data + 11 + 13 + 1, tags_written);
gst_buffer_unmap (script_tag, data, -1);
+exit:
return script_tag;
}
@@ -1125,7 +1138,7 @@ gst_flv_mux_write_header (GstFlvMux * mux)
GstFlowReturn ret;
header = gst_flv_mux_create_header (mux);
- metadata = gst_flv_mux_create_metadata (mux);
+ metadata = gst_flv_mux_create_metadata (mux, TRUE);
video_codec_data = NULL;
audio_codec_data = NULL;
@@ -1228,18 +1241,12 @@ gst_flv_mux_update_index (GstFlvMux * mux, GstBuffer * buffer, GstFlvPad * cpad)
}
static GstFlowReturn
-gst_flv_mux_write_buffer (GstFlvMux * mux, GstFlvPad * cpad)
+gst_flv_mux_write_buffer (GstFlvMux * mux, GstFlvPad * cpad, GstBuffer * buffer)
{
GstBuffer *tag;
- GstBuffer *buffer =
- gst_collect_pads_pop (mux->collect, (GstCollectData *) cpad);
GstFlowReturn ret;
- /* arrange downstream running time */
- buffer = gst_buffer_make_writable (buffer);
- GST_BUFFER_TIMESTAMP (buffer) =
- gst_segment_to_running_time (&cpad->collect.segment,
- GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer));
+ /* clipping function arranged for running_time */
if (!mux->streamable)
gst_flv_mux_update_index (mux, buffer, cpad);
@@ -1276,12 +1283,6 @@ gst_flv_mux_determine_duration (GstFlvMux * mux)
}
}
- if (duration == GST_CLOCK_TIME_NONE) {
- GST_DEBUG_OBJECT (mux, "not able to determine duration "
- "from pad timestamps, assuming 0");
- return 0;
- }
-
return duration;
}
@@ -1296,6 +1297,7 @@ gst_flv_mux_rewrite_header (GstFlvMux * mux)
guint32 index_len, allocate_size;
guint32 i, index_skip;
GstSegment segment;
+ GstClockTime dur;
if (mux->streamable)
return GST_FLOW_OK;
@@ -1309,9 +1311,12 @@ gst_flv_mux_rewrite_header (GstFlvMux * mux)
return GST_FLOW_OK;
}
- /* if we were not able to determine the duration before, set it now */
- if (mux->duration == GST_CLOCK_TIME_NONE)
- mux->duration = gst_flv_mux_determine_duration (mux);
+ /* determine duration now based on our own timestamping,
+ * so that it is likely many times better and consistent
+ * than whatever obtained by some query */
+ dur = gst_flv_mux_determine_duration (mux);
+ if (dur != GST_CLOCK_TIME_NONE)
+ mux->duration = dur;
/* rewrite the duration tag */
d = gst_guint64_to_gdouble (mux->duration);
@@ -1420,14 +1425,13 @@ gst_flv_mux_rewrite_header (GstFlvMux * mux)
}
static GstFlowReturn
-gst_flv_mux_collected (GstCollectPads * pads, gpointer user_data)
+gst_flv_mux_handle_buffer (GstCollectPads2 * pads, GstCollectData2 * cdata,
+ GstBuffer * buffer, gpointer user_data)
{
GstFlvMux *mux = GST_FLV_MUX (user_data);
GstFlvPad *best;
GstClockTime best_time;
GstFlowReturn ret;
- GSList *sl;
- gboolean eos = TRUE;
if (mux->state == GST_FLV_MUX_STATE_HEADER) {
GstSegment segment;
@@ -1450,51 +1454,18 @@ gst_flv_mux_collected (GstCollectPads * pads, gpointer user_data)
}
if (mux->new_tags) {
- GstBuffer *buf = gst_flv_mux_create_metadata (mux);
- gst_flv_mux_push (mux, buf);
+ GstBuffer *buf = gst_flv_mux_create_metadata (mux, FALSE);
+ if (buf)
+ gst_flv_mux_push (mux, buf);
mux->new_tags = FALSE;
}
-
- best = NULL;
- best_time = GST_CLOCK_TIME_NONE;
- for (sl = mux->collect->data; sl; sl = sl->next) {
- GstFlvPad *cpad = sl->data;
- GstBuffer *buffer = gst_collect_pads_peek (pads, (GstCollectData *) cpad);
- GstClockTime time;
-
- if (!buffer)
- continue;
-
- eos = FALSE;
-
- time = GST_BUFFER_TIMESTAMP (buffer);
- gst_buffer_unref (buffer);
-
- /* Use buffers without valid timestamp first */
- if (!GST_CLOCK_TIME_IS_VALID (time)) {
- GST_WARNING_OBJECT (pads, "Buffer without valid timestamp");
-
- best_time = cpad->last_timestamp;
- best = cpad;
- break;
- }
-
- time = gst_segment_to_running_time (&cpad->collect.segment,
- GST_FORMAT_TIME, time);
- if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
- GST_DEBUG_OBJECT (mux, "clipping buffer on pad %s outside segment",
- GST_PAD_NAME (cpad->collect.pad));
- buffer = gst_collect_pads_pop (pads, (GstCollectData *) cpad);
- gst_buffer_unref (buffer);
- return GST_FLOW_OK;
- }
-
- if (best == NULL || (GST_CLOCK_TIME_IS_VALID (best_time)
- && time < best_time)) {
- best = cpad;
- best_time = time;
- }
+ best = (GstFlvPad *) cdata;
+ if (best) {
+ g_assert (buffer);
+ best_time = GST_BUFFER_TIMESTAMP (buffer);
+ } else {
+ best_time = GST_CLOCK_TIME_NONE;
}
/* The FLV timestamp is an int32 field. For non-live streams error out if a
@@ -1503,17 +1474,17 @@ gst_flv_mux_collected (GstCollectPads * pads, gpointer user_data)
if (!mux->streamable && GST_CLOCK_TIME_IS_VALID (best_time)
&& best_time / GST_MSECOND > G_MAXINT32) {
GST_WARNING_OBJECT (mux, "Timestamp larger than FLV supports - EOS");
- eos = TRUE;
+ gst_buffer_unref (buffer);
+ buffer = NULL;
+ best = NULL;
}
- if (!eos && best) {
- return gst_flv_mux_write_buffer (mux, best);
- } else if (eos) {
+ if (best) {
+ return gst_flv_mux_write_buffer (mux, best, buffer);
+ } else {
gst_flv_mux_rewrite_header (mux);
gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
return GST_FLOW_EOS;
- } else {
- return GST_FLOW_OK;
}
}
@@ -1565,12 +1536,12 @@ gst_flv_mux_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_NULL_TO_READY:
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
- gst_collect_pads_start (mux->collect);
+ gst_collect_pads2_start (mux->collect);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_collect_pads_stop (mux->collect);
+ gst_collect_pads2_stop (mux->collect);
break;
default:
break;
diff --git a/gst/flv/gstflvmux.h b/gst/flv/gstflvmux.h
index fff51b9b3..b0e10ea32 100644
--- a/gst/flv/gstflvmux.h
+++ b/gst/flv/gstflvmux.h
@@ -22,7 +22,7 @@
#define __GST_FLV_MUX_H__
#include <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
+#include <gst/base/gstcollectpads2.h>
G_BEGIN_DECLS
@@ -39,7 +39,7 @@ G_BEGIN_DECLS
typedef struct
{
- GstCollectData collect;
+ GstCollectData2 collect;
gboolean video;
@@ -65,11 +65,9 @@ typedef struct _GstFlvMux {
GstElement element;
GstPad *srcpad;
- GstCollectPads *collect;
+ GstCollectPads2 *collect;
/* <private> */
- GstPadEventFunction collect_event;
-
GstFlvMuxState state;
gboolean have_audio;
gboolean have_video;
diff --git a/gst/imagefreeze/gstimagefreeze.c b/gst/imagefreeze/gstimagefreeze.c
index f4c67c76f..03c425d33 100644
--- a/gst/imagefreeze/gstimagefreeze.c
+++ b/gst/imagefreeze/gstimagefreeze.c
@@ -41,6 +41,12 @@
#include "config.h"
#endif
+/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
+#include <gst/glib-compat-private.h>
+
#include "gstimagefreeze.h"
static void gst_image_freeze_finalize (GObject * object);
diff --git a/gst/interleave/interleave.c b/gst/interleave/interleave.c
index c2cc2db78..e7e0b668c 100644
--- a/gst/interleave/interleave.c
+++ b/gst/interleave/interleave.c
@@ -227,7 +227,7 @@ static gboolean gst_interleave_sink_setcaps (GstPad * pad, GstCaps * caps);
static GstCaps *gst_interleave_sink_getcaps (GstPad * pad);
-static GstFlowReturn gst_interleave_collected (GstCollectPads * pads,
+static GstFlowReturn gst_interleave_collected (GstCollectPads2 * pads,
GstInterleave * self);
static void
@@ -407,9 +407,9 @@ gst_interleave_init (GstInterleave * self, GstInterleaveClass * klass)
gst_element_add_pad (GST_ELEMENT (self), self->src);
- self->collect = gst_collect_pads_new ();
- gst_collect_pads_set_function (self->collect,
- (GstCollectPadsFunction) gst_interleave_collected, self);
+ self->collect = gst_collect_pads2_new ();
+ gst_collect_pads2_set_function (self->collect,
+ (GstCollectPads2Function) gst_interleave_collected, self);
self->input_channel_positions = g_value_array_new (0);
self->channel_positions_from_input = TRUE;
@@ -500,11 +500,10 @@ gst_interleave_request_new_pad (GstElement * element, GstPadTemplate * templ,
gst_pad_set_getcaps_function (new_pad,
GST_DEBUG_FUNCPTR (gst_interleave_sink_getcaps));
- gst_collect_pads_add_pad (self->collect, new_pad, sizeof (GstCollectData),
- NULL);
+ gst_collect_pads2_add_pad (self->collect, new_pad, sizeof (GstCollectData2));
/* FIXME: hacked way to override/extend the event function of
- * GstCollectPads; because it sets its own event function giving the
+ * GstCollectPads2; because it sets its own event function giving the
* element no access to events */
self->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (new_pad);
gst_pad_set_event_function (new_pad,
@@ -550,7 +549,7 @@ not_sink_pad:
could_not_add:
{
GST_DEBUG_OBJECT (self, "could not add pad %s", GST_PAD_NAME (new_pad));
- gst_collect_pads_remove_pad (self->collect, new_pad);
+ gst_collect_pads2_remove_pad (self->collect, new_pad);
gst_object_unref (new_pad);
return NULL;
}
@@ -604,7 +603,7 @@ gst_interleave_release_pad (GstElement * element, GstPad * pad)
GST_OBJECT_UNLOCK (self->collect);
- gst_collect_pads_remove_pad (self->collect, pad);
+ gst_collect_pads2_remove_pad (self->collect, pad);
gst_element_remove_pad (element, pad);
}
@@ -626,7 +625,7 @@ gst_interleave_change_state (GstElement * element, GstStateChange transition)
self->segment_position = 0;
self->segment_rate = 1.0;
gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
- gst_collect_pads_start (self->collect);
+ gst_collect_pads2_start (self->collect);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break;
@@ -635,11 +634,11 @@ gst_interleave_change_state (GstElement * element, GstStateChange transition)
}
/* Stop before calling the parent's state change function as
- * GstCollectPads might take locks and we would deadlock in that
+ * GstCollectPads2 might take locks and we would deadlock in that
* case
*/
if (transition == GST_STATE_CHANGE_PAUSED_TO_READY)
- gst_collect_pads_stop (self->collect);
+ gst_collect_pads2_stop (self->collect);
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
@@ -879,7 +878,7 @@ gst_interleave_sink_event (GstPad * pad, GstEvent * event)
break;
}
- /* now GstCollectPads can take care of the rest, e.g. EOS */
+ /* now GstCollectPads2 can take care of the rest, e.g. EOS */
ret = self->collect_event (pad, event);
gst_object_unref (self);
@@ -1160,7 +1159,7 @@ gst_interleave_src_event (GstPad * pad, GstEvent * event)
/* check if we are flushing */
if (flags & GST_SEEK_FLAG_FLUSH) {
/* make sure we accept nothing anymore and return WRONG_STATE */
- gst_collect_pads_set_flushing (self->collect, TRUE);
+ gst_collect_pads2_set_flushing (self->collect, TRUE);
/* flushing seek, start flush downstream, the flush will be done
* when all pads received a FLUSH_STOP. */
@@ -1195,7 +1194,7 @@ gst_interleave_src_event (GstPad * pad, GstEvent * event)
}
static GstFlowReturn
-gst_interleave_collected (GstCollectPads * pads, GstInterleave * self)
+gst_interleave_collected (GstCollectPads2 * pads, GstInterleave * self)
{
guint size;
GstBuffer *outbuf;
@@ -1211,7 +1210,7 @@ gst_interleave_collected (GstCollectPads * pads, GstInterleave * self)
g_return_val_if_fail (self->channels > 0, GST_FLOW_NOT_NEGOTIATED);
g_return_val_if_fail (self->rate > 0, GST_FLOW_NOT_NEGOTIATED);
- size = gst_collect_pads_available (pads);
+ size = gst_collect_pads2_available (pads);
g_return_val_if_fail (size % width == 0, GST_FLOW_ERROR);
@@ -1238,13 +1237,13 @@ gst_interleave_collected (GstCollectPads * pads, GstInterleave * self)
memset (GST_BUFFER_DATA (outbuf), 0, size * self->channels);
for (collected = pads->data; collected != NULL; collected = collected->next) {
- GstCollectData *cdata;
+ GstCollectData2 *cdata;
GstBuffer *inbuf;
guint8 *outdata;
- cdata = (GstCollectData *) collected->data;
+ cdata = (GstCollectData2 *) collected->data;
- inbuf = gst_collect_pads_take_buffer (pads, cdata, size);
+ inbuf = gst_collect_pads2_take_buffer (pads, cdata, size);
if (inbuf == NULL) {
GST_DEBUG_OBJECT (cdata->pad, "No buffer available");
goto next;
diff --git a/gst/interleave/interleave.h b/gst/interleave/interleave.h
index fb3b27415..abe3439e4 100644
--- a/gst/interleave/interleave.h
+++ b/gst/interleave/interleave.h
@@ -27,7 +27,7 @@
#define __INTERLEAVE_H__
#include <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
+#include <gst/base/gstcollectpads2.h>
G_BEGIN_DECLS
@@ -49,7 +49,7 @@ struct _GstInterleave
GstElement element;
/*< private >*/
- GstCollectPads *collect;
+ GstCollectPads2 *collect;
gint channels;
gint padcounter;
diff --git a/gst/isomp4/gstqtmoovrecover.c b/gst/isomp4/gstqtmoovrecover.c
index 678ab3bb4..3fbfec329 100644
--- a/gst/isomp4/gstqtmoovrecover.c
+++ b/gst/isomp4/gstqtmoovrecover.c
@@ -65,6 +65,10 @@
#include "config.h"
#endif
+/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
#include <glib/gstdio.h>
#include <gst/gst.h>
diff --git a/gst/isomp4/gstqtmux.c b/gst/isomp4/gstqtmux.c
index 0c7caf6f4..510747827 100644
--- a/gst/isomp4/gstqtmux.c
+++ b/gst/isomp4/gstqtmux.c
@@ -226,11 +226,11 @@ static GstPad *gst_qt_mux_request_new_pad (GstElement * element,
static void gst_qt_mux_release_pad (GstElement * element, GstPad * pad);
/* event */
-static gboolean gst_qt_mux_sink_event (GstPad * pad, GstObject * parent,
- GstEvent * event);
+static gboolean gst_qt_mux_sink_event (GstCollectPads2 * pads,
+ GstCollectData2 * data, GstEvent * event, gpointer user_data);
-static GstFlowReturn gst_qt_mux_collected (GstCollectPads * pads,
- gpointer user_data);
+static GstFlowReturn gst_qt_mux_handle_buffer (GstCollectPads2 * pads,
+ GstCollectData2 * cdata, GstBuffer * buf, gpointer user_data);
static GstFlowReturn gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad,
GstBuffer * buf);
@@ -482,9 +482,13 @@ gst_qt_mux_init (GstQTMux * qtmux, GstQTMuxClass * qtmux_klass)
gst_element_add_pad (GST_ELEMENT (qtmux), qtmux->srcpad);
qtmux->sinkpads = NULL;
- qtmux->collect = gst_collect_pads_new ();
- gst_collect_pads_set_function (qtmux->collect,
- (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_qt_mux_collected), qtmux);
+ qtmux->collect = gst_collect_pads2_new ();
+ gst_collect_pads2_set_buffer_function (qtmux->collect,
+ GST_DEBUG_FUNCPTR (gst_qt_mux_handle_buffer), qtmux);
+ gst_collect_pads2_set_event_function (qtmux->collect,
+ GST_DEBUG_FUNCPTR (gst_qt_mux_sink_event), qtmux);
+ gst_collect_pads2_set_clip_function (qtmux->collect,
+ GST_DEBUG_FUNCPTR (gst_collect_pads2_clip_running_time), qtmux);
/* properties set to default upon construction */
@@ -1661,7 +1665,7 @@ gst_qt_mux_start_file (GstQTMux * qtmux)
gst_buffer_unref (prefix);
for (walk = qtmux->sinkpads; walk && !fail; walk = g_slist_next (walk)) {
- GstCollectData *cdata = (GstCollectData *) walk->data;
+ GstCollectData2 *cdata = (GstCollectData2 *) walk->data;
GstQTPad *qpad = (GstQTPad *) cdata;
/* write info for each stream */
fail = atoms_recov_write_trak_info (qtmux->moov_recov_file, qpad->trak);
@@ -1761,7 +1765,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
/* pushing last buffers for each pad */
for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
- GstCollectData *cdata = (GstCollectData *) walk->data;
+ GstCollectData2 *cdata = (GstCollectData2 *) walk->data;
GstQTPad *qtpad = (GstQTPad *) cdata;
/* avoid add_buffer complaining if not negotiated
@@ -1853,7 +1857,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
/* check for late streams */
first_ts = GST_CLOCK_TIME_NONE;
for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
- GstCollectData *cdata = (GstCollectData *) walk->data;
+ GstCollectData2 *cdata = (GstCollectData2 *) walk->data;
GstQTPad *qtpad = (GstQTPad *) cdata;
if (!GST_CLOCK_TIME_IS_VALID (first_ts) ||
@@ -1866,7 +1870,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
GST_TIME_ARGS (first_ts));
/* add EDTSs for late streams */
for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
- GstCollectData *cdata = (GstCollectData *) walk->data;
+ GstCollectData2 *cdata = (GstCollectData2 *) walk->data;
GstQTPad *qtpad = (GstQTPad *) cdata;
guint32 lateness;
guint32 duration;
@@ -2520,14 +2524,13 @@ not_negotiated:
}
static GstFlowReturn
-gst_qt_mux_collected (GstCollectPads * pads, gpointer user_data)
+gst_qt_mux_handle_buffer (GstCollectPads2 * pads, GstCollectData2 * cdata,
+ GstBuffer * buf, gpointer user_data)
{
GstFlowReturn ret = GST_FLOW_OK;
GstQTMux *qtmux = GST_QT_MUX_CAST (user_data);
- GSList *walk;
GstQTPad *best_pad = NULL;
- GstClockTime time, best_time = GST_CLOCK_TIME_NONE;
- GstBuffer *buf;
+ GstClockTime best_time = GST_CLOCK_TIME_NONE;
if (G_UNLIKELY (qtmux->state == GST_QT_MUX_STATE_STARTED)) {
if ((ret = gst_qt_mux_start_file (qtmux)) != GST_FLOW_OK)
@@ -2539,52 +2542,14 @@ gst_qt_mux_collected (GstCollectPads * pads, gpointer user_data)
if (G_UNLIKELY (qtmux->state == GST_QT_MUX_STATE_EOS))
return GST_FLOW_EOS;
- /* select the best buffer */
- walk = qtmux->collect->data;
- while (walk) {
- GstQTPad *pad;
- GstCollectData *data;
-
- data = (GstCollectData *) walk->data;
- pad = (GstQTPad *) data;
-
- walk = g_slist_next (walk);
-
- buf = gst_collect_pads_peek (pads, data);
- if (buf == NULL) {
- GST_LOG_OBJECT (qtmux, "Pad %s has no buffers",
- GST_PAD_NAME (pad->collect.pad));
- continue;
- }
- time = GST_BUFFER_TIMESTAMP (buf);
- gst_buffer_unref (buf);
-
- /* invalid should pass */
- if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) {
- time =
- gst_segment_to_running_time (&data->segment, GST_FORMAT_TIME, time);
- if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
- GST_DEBUG_OBJECT (qtmux, "clipping buffer on pad %s outside segment",
- GST_PAD_NAME (data->pad));
- buf = gst_collect_pads_pop (pads, data);
- gst_buffer_unref (buf);
- return GST_FLOW_OK;
- }
- }
-
- if (best_pad == NULL || !GST_CLOCK_TIME_IS_VALID (time) ||
- (GST_CLOCK_TIME_IS_VALID (best_time) && time < best_time)) {
- best_pad = pad;
- best_time = time;
- }
- }
+ best_pad = (GstQTPad *) cdata;
+ /* clipping already converted to running time */
if (best_pad != NULL) {
+ g_assert (buf);
+ best_time = GST_BUFFER_TIMESTAMP (buf);
GST_LOG_OBJECT (qtmux, "selected pad %s with time %" GST_TIME_FORMAT,
GST_PAD_NAME (best_pad->collect.pad), GST_TIME_ARGS (best_time));
- buf = gst_collect_pads_pop (pads, &best_pad->collect);
- buf = gst_buffer_make_writable (buf);
- GST_BUFFER_TIMESTAMP (buf) = best_time;
ret = gst_qt_mux_add_buffer (qtmux, best_pad, buf);
} else {
ret = gst_qt_mux_stop_file (qtmux);
@@ -3284,14 +3249,14 @@ refuse_renegotiation:
}
static gboolean
-gst_qt_mux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
+gst_qt_mux_sink_event (GstCollectPads2 * pads, GstCollectData2 * data,
+ GstEvent * event, gpointer user_data)
{
- gboolean ret;
GstQTMux *qtmux;
guint32 avg_bitrate = 0, max_bitrate = 0;
+ GstPad *pad = data->pad;
- qtmux = GST_QT_MUX_CAST (parent);
-
+ qtmux = GST_QT_MUX_CAST (user_data);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CAPS:
{
@@ -3316,8 +3281,9 @@ gst_qt_mux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
GST_OBJECT_LOCK (qtmux);
mode = gst_tag_setter_get_tag_merge_mode (setter);
- GST_DEBUG_OBJECT (qtmux, "received tag event");
gst_event_parse_tag (event, &list);
+ GST_DEBUG_OBJECT (qtmux, "received tag event on pad %s:%s : %"
+ GST_PTR_FORMAT, GST_DEBUG_PAD_NAME (pad), list);
gst_tag_setter_merge_tags (setter, list, mode);
GST_OBJECT_UNLOCK (qtmux);
@@ -3339,9 +3305,8 @@ gst_qt_mux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
break;
}
- ret = qtmux->collect_event (pad, parent, event);
-
- return ret;
+ /* now GstCollectPads2 can take care of the rest, e.g. EOS */
+ return FALSE;
}
static void
@@ -3363,7 +3328,7 @@ gst_qt_mux_release_pad (GstElement * element, GstPad * pad)
}
}
- gst_collect_pads_remove_pad (mux->collect, pad);
+ gst_collect_pads2_remove_pad (mux->collect, pad);
}
static GstPad *
@@ -3407,8 +3372,8 @@ gst_qt_mux_request_new_pad (GstElement * element,
newpad = gst_pad_new_from_template (templ, name);
g_free (name);
collect_pad = (GstQTPad *)
- gst_collect_pads_add_pad (qtmux->collect, newpad, sizeof (GstQTPad),
- (GstCollectDataDestroyNotify) (gst_qt_mux_pad_reset));
+ gst_collect_pads2_add_pad_full (qtmux->collect, newpad, sizeof (GstQTPad),
+ (GstCollectData2DestroyNotify) (gst_qt_mux_pad_reset), TRUE);
/* set up pad */
gst_qt_mux_pad_reset (collect_pad);
collect_pad->trak = atom_trak_new (qtmux->context);
@@ -3422,14 +3387,6 @@ gst_qt_mux_request_new_pad (GstElement * element,
else
collect_pad->set_caps = GST_DEBUG_FUNCPTR (gst_qt_mux_video_sink_set_caps);
- /* FIXME: hacked way to override/extend the event function of
- * GstCollectPads; because it sets its own event function giving the
- * element no access to events.
- */
- qtmux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
- gst_pad_set_event_function (newpad,
- GST_DEBUG_FUNCPTR (gst_qt_mux_sink_event));
-
gst_pad_set_active (newpad, TRUE);
gst_element_add_pad (element, newpad);
@@ -3566,13 +3523,13 @@ gst_qt_mux_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_NULL_TO_READY:
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
- gst_collect_pads_start (qtmux->collect);
+ gst_collect_pads2_start (qtmux->collect);
qtmux->state = GST_QT_MUX_STATE_STARTED;
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_collect_pads_stop (qtmux->collect);
+ gst_collect_pads2_stop (qtmux->collect);
break;
default:
break;
diff --git a/gst/isomp4/gstqtmux.h b/gst/isomp4/gstqtmux.h
index fdbbb5a54..c17ff25de 100644
--- a/gst/isomp4/gstqtmux.h
+++ b/gst/isomp4/gstqtmux.h
@@ -44,7 +44,7 @@
#define __GST_QT_MUX_H__
#include <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
+#include <gst/base/gstcollectpads2.h>
#include "fourcc.h"
#include "atoms.h"
@@ -82,7 +82,7 @@ typedef GstBuffer * (*GstQTPadPrepareBufferFunc) (GstQTPad * pad,
struct _GstQTPad
{
- GstCollectData collect; /* we extend the CollectData */
+ GstCollectData2 collect; /* we extend the CollectData2 */
/* fourcc id of stream */
guint32 fourcc;
@@ -145,7 +145,7 @@ struct _GstQTMux
GstElement element;
GstPad *srcpad;
- GstCollectPads *collect;
+ GstCollectPads2 *collect;
GSList *sinkpads;
/* state */
@@ -192,9 +192,6 @@ struct _GstQTMux
guint32 fragment_duration;
gboolean streamable;
- /* for collect pads event handling function */
- GstPadEventFunction collect_event;
-
/* for request pad naming */
guint video_pads, audio_pads;
};
diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c
index 2b9053fac..b7511c5c7 100644
--- a/gst/isomp4/qtdemux.c
+++ b/gst/isomp4/qtdemux.c
@@ -47,6 +47,10 @@
#include "config.h"
#endif
+/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
#include "gst/gst-i18n-plugin.h"
#include <glib/gprintf.h>
@@ -5317,8 +5321,13 @@ qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
/* make sure there's enough data */
- if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 2 * 4))
- goto corrupt_file;
+ if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
+ stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
+ GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
+ stream->n_sample_times);
+ if (!stream->n_sample_times)
+ goto corrupt_file;
+ }
/* sync sample atom */
stream->stps_present = FALSE;
diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c
index 404071c8c..f5fb27267 100644
--- a/gst/matroska/matroska-demux.c
+++ b/gst/matroska/matroska-demux.c
@@ -49,6 +49,10 @@
#include "config.h"
#endif
+/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
#include <math.h>
#include <string.h>
#include <glib/gprintf.h>
@@ -482,6 +486,8 @@ gst_matroska_demux_reset (GstElement * element)
gst_buffer_unref (demux->common.cached_buffer);
demux->common.cached_buffer = NULL;
}
+
+ demux->invalid_duration = FALSE;
}
static GstBuffer *
@@ -1356,10 +1362,12 @@ gst_matroska_demux_query (GstMatroskaDemux * demux, GstPad * pad,
GST_OBJECT_LOCK (demux);
if (context)
gst_query_set_position (query, GST_FORMAT_TIME,
- context->pos - demux->stream_start_time);
+ MAX (context->pos, demux->stream_start_time) -
+ demux->stream_start_time);
else
gst_query_set_position (query, GST_FORMAT_TIME,
- demux->common.segment.position - demux->stream_start_time);
+ MAX (demux->common.segment.position, demux->stream_start_time) -
+ demux->stream_start_time);
GST_OBJECT_UNLOCK (demux);
} else if (format == GST_FORMAT_DEFAULT && context
&& context->default_duration) {
@@ -1740,8 +1748,11 @@ gst_matroska_demux_search_pos (GstMatroskaDemux * demux, GstClockTime time)
otime = demux->common.segment.position;
GST_OBJECT_UNLOCK (demux);
+ /* sanitize */
+ time = MAX (time, demux->stream_start_time);
+
/* avoid division by zero in first estimation below */
- if (otime == 0)
+ if (otime <= demux->stream_start_time)
otime = time;
retry:
@@ -1918,6 +1929,14 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
* segment when we close the current segment. */
memcpy (&seeksegment, &demux->common.segment, sizeof (GstSegment));
+ /* pull mode without index means that the actual duration is not known,
+ * we might be playing a file that's still being recorded
+ * so, invalidate our current duration, which is only a moving target,
+ * and should not be used to clamp anything */
+ if (!demux->streaming && !demux->common.index && demux->invalid_duration) {
+ seeksegment.duration = GST_CLOCK_TIME_NONE;
+ }
+
if (event) {
GST_DEBUG_OBJECT (demux, "configuring seek");
gst_segment_do_seek (&seeksegment, rate, format, flags,
@@ -1932,6 +1951,10 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
}
}
+ /* restore segment duration (if any effect),
+ * would be determined again when parsing, but anyway ... */
+ seeksegment.duration = demux->common.segment.duration;
+
flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
keyunit = ! !(flags & GST_SEEK_FLAG_KEY_UNIT);
@@ -1952,7 +1975,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
seeksegment.position, &demux->seek_index, &demux->seek_entry)) ==
NULL) {
/* pull mode without index can scan later on */
- if (demux->common.index || demux->streaming) {
+ if (demux->streaming) {
GST_DEBUG_OBJECT (demux, "No matching seek entry in index");
GST_OBJECT_UNLOCK (demux);
return FALSE;
@@ -1989,7 +2012,7 @@ next:
GST_PAD_STREAM_LOCK (demux->common.sinkpad);
/* pull mode without index can do some scanning */
- if (!demux->streaming && !demux->common.index) {
+ if (!demux->streaming && !entry) {
/* need to stop flushing upstream as we need it next */
if (flush)
gst_pad_push_event (demux->common.sinkpad,
@@ -2011,9 +2034,9 @@ next:
if (keyunit) {
GST_DEBUG_OBJECT (demux, "seek to key unit, adjusting segment start to %"
GST_TIME_FORMAT, GST_TIME_ARGS (entry->time));
- seeksegment.start = entry->time;
- seeksegment.position = entry->time;
- seeksegment.time = entry->time - demux->stream_start_time;
+ seeksegment.start = MAX (entry->time, demux->stream_start_time);
+ seeksegment.position = seeksegment.start;
+ seeksegment.time = seeksegment.start - demux->stream_start_time;
}
exit:
@@ -3347,9 +3370,9 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
else if (GST_CLOCK_TIME_IS_VALID (segment->position))
segment_duration = segment->position - segment->start;
segment->base += segment_duration / fabs (segment->rate);
- segment->start = lace_time;
+ segment->start = MAX (lace_time, demux->stream_start_time);
segment->stop = GST_CLOCK_TIME_NONE;
- segment->position = lace_time - demux->stream_start_time;
+ segment->position = segment->start - demux->stream_start_time;
/* now convey our segment notion downstream */
gst_matroska_demux_send_event (demux, gst_event_new_segment (segment));
demux->need_segment = FALSE;
@@ -3535,14 +3558,15 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
GST_OBJECT_LOCK (demux);
if (demux->common.segment.duration == -1 ||
- demux->common.segment.duration <
- lace_time - demux->stream_start_time) {
+ demux->stream_start_time + demux->common.segment.duration <
+ last_stop_end) {
demux->common.segment.duration =
last_stop_end - demux->stream_start_time;
GST_OBJECT_UNLOCK (demux);
gst_element_post_message (GST_ELEMENT_CAST (demux),
gst_message_new_duration (GST_OBJECT_CAST (demux),
GST_FORMAT_TIME, GST_CLOCK_TIME_NONE));
+ demux->invalid_duration = TRUE;
} else {
GST_OBJECT_UNLOCK (demux);
}
@@ -4475,11 +4499,13 @@ pause:
/* Close the segment, i.e. update segment stop with the duration
* if no stop was set */
if (GST_CLOCK_TIME_IS_VALID (demux->last_stop_end) &&
- !GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop)) {
+ !GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop) &&
+ GST_CLOCK_TIME_IS_VALID (demux->common.segment.start) &&
+ demux->last_stop_end > demux->common.segment.start) {
GstSegment segment = demux->common.segment;
GstEvent *event;
- segment.stop = MAX (demux->last_stop_end, segment.start);
+ segment.stop = demux->last_stop_end;
event = gst_event_new_segment (&segment);
gst_matroska_demux_send_event (demux, event);
}
diff --git a/gst/matroska/matroska-demux.h b/gst/matroska/matroska-demux.h
index 65061c1d1..0a6312ea8 100644
--- a/gst/matroska/matroska-demux.h
+++ b/gst/matroska/matroska-demux.h
@@ -95,6 +95,9 @@ typedef struct _GstMatroskaDemux {
/* gap handling */
guint64 max_gap_time;
+
+ /* for non-finalized files, with invalid segment duration */
+ gboolean invalid_duration;
} GstMatroskaDemux;
typedef struct _GstMatroskaDemuxClass {
diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c
index f02c171a1..5fe25f957 100644
--- a/gst/matroska/matroska-mux.c
+++ b/gst/matroska/matroska-mux.c
@@ -2,6 +2,7 @@
* (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
* (c) 2005 Michal Benes <michal.benes@xeris.cz>
* (c) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * (c) 2011 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
*
* matroska-mux.c: matroska file/stream muxer
*
@@ -183,10 +184,14 @@ static GstStaticPadTemplate audiosink_templ =
);
static GstStaticPadTemplate subtitlesink_templ =
-GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
+ GST_STATIC_PAD_TEMPLATE ("subtitle_%d",
GST_PAD_SINK,
GST_PAD_REQUEST,
- GST_STATIC_CAPS ("subtitle/x-kate"));
+ GST_STATIC_CAPS ("subtitle/x-kate; "
+ "text/plain; application/x-ssa; application/x-ass; "
+ "application/x-usf; video/x-dvd-subpicture; "
+ "application/x-subtitle-unknown")
+ );
static GArray *used_uids;
G_LOCK_DEFINE_STATIC (used_uids);
@@ -199,8 +204,10 @@ G_DEFINE_TYPE_WITH_CODE (GstMatroskaMux, gst_matroska_mux, GST_TYPE_ELEMENT,
static void gst_matroska_mux_finalize (GObject * object);
/* Pads collected callback */
-static GstFlowReturn
-gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data);
+static GstFlowReturn gst_matroska_mux_handle_buffer (GstCollectPads2 * pads,
+ GstCollectData2 * data, GstBuffer * buf, gpointer user_data);
+static gboolean gst_matroska_mux_handle_sink_event (GstCollectPads2 * pads,
+ GstCollectData2 * data, GstEvent * event, gpointer user_data);
/* pad functions */
static gboolean gst_matroska_mux_handle_src_event (GstPad * pad,
@@ -415,10 +422,13 @@ gst_matroska_mux_init (GstMatroskaMux * mux)
gst_pad_set_event_function (mux->srcpad, gst_matroska_mux_handle_src_event);
gst_element_add_pad (GST_ELEMENT (mux), mux->srcpad);
- mux->collect = gst_collect_pads_new ();
- gst_collect_pads_set_function (mux->collect,
- (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_matroska_mux_collected),
- mux);
+ mux->collect = gst_collect_pads2_new ();
+ gst_collect_pads2_set_clip_function (mux->collect,
+ GST_DEBUG_FUNCPTR (gst_collect_pads2_clip_running_time), mux);
+ gst_collect_pads2_set_buffer_function (mux->collect,
+ GST_DEBUG_FUNCPTR (gst_matroska_mux_handle_buffer), mux);
+ gst_collect_pads2_set_event_function (mux->collect,
+ GST_DEBUG_FUNCPTR (gst_matroska_mux_handle_sink_event), mux);
mux->ebml_write = gst_ebml_write_new (mux->srcpad);
mux->doctype = GST_MATROSKA_DOCTYPE_MATROSKA;
@@ -535,12 +545,6 @@ gst_matroska_pad_reset (GstMatroskaPad * collect_pad, gboolean full)
collect_pad->track = NULL;
}
- /* free cached buffer */
- if (collect_pad->buffer != NULL) {
- gst_buffer_unref (collect_pad->buffer);
- collect_pad->buffer = NULL;
- }
-
if (!full && type != 0) {
GstMatroskaTrackContext *context;
@@ -568,7 +572,6 @@ gst_matroska_pad_reset (GstMatroskaPad * collect_pad, gboolean full)
/* TODO: check default values for the context */
context->flags = GST_MATROSKA_TRACK_ENABLED | GST_MATROSKA_TRACK_DEFAULT;
collect_pad->track = context;
- collect_pad->buffer = NULL;
collect_pad->duration = 0;
collect_pad->start_ts = GST_CLOCK_TIME_NONE;
collect_pad->end_ts = GST_CLOCK_TIME_NONE;
@@ -665,6 +668,44 @@ gst_matroska_mux_handle_src_event (GstPad * pad, GstObject * parent,
return gst_pad_event_default (pad, parent, event);
}
+static void
+gst_matroska_mux_build_vobsub_private (GstMatroskaTrackContext * context,
+ const guint * clut)
+{
+ gchar *clutv[17];
+ gchar *sclut;
+ gint i;
+ guint32 col;
+ gdouble y, u, v;
+ guint8 r, g, b;
+
+ /* produce comma-separated list in hex format */
+ for (i = 0; i < 16; ++i) {
+ col = clut[i];
+ /* replicate vobsub's slightly off RGB conversion calculation */
+ y = (((col >> 16) & 0xff) - 16) * 255 / 219;
+ u = ((col >> 8) & 0xff) - 128;
+ v = (col & 0xff) - 128;
+ r = CLAMP (1.0 * y + 1.4022 * u, 0, 255);
+ g = CLAMP (1.0 * y - 0.3456 * u - 0.7145 * v, 0, 255);
+ b = CLAMP (1.0 * y + 1.7710 * v, 0, 255);
+ clutv[i] = g_strdup_printf ("%02x%02x%02x", r, g, b);
+ }
+ clutv[i] = NULL;
+ sclut = g_strjoinv (",", clutv);
+
+ /* build codec private; only palette for now */
+ g_free (context->codec_priv);
+ context->codec_priv = (guint8 *) g_strdup_printf ("palette: %s", sclut);
+ /* include terminating 0 */
+ context->codec_priv_size = strlen ((gchar *) context->codec_priv) + 1;
+ g_free (sclut);
+ for (i = 0; i < 16; ++i) {
+ g_free (clutv[i]);
+ }
+}
+
+
/**
* gst_matroska_mux_handle_sink_event:
* @pad: Pad which received the event.
@@ -675,14 +716,21 @@ gst_matroska_mux_handle_src_event (GstPad * pad, GstObject * parent,
* Returns: #TRUE on success.
*/
static gboolean
-gst_matroska_mux_handle_sink_event (GstPad * pad, GstObject * parent,
- GstEvent * event)
+gst_matroska_mux_handle_sink_event (GstCollectPads2 * pads,
+ GstCollectData2 * data, GstEvent * event, gpointer user_data)
{
- GstMatroskaTrackContext *context;
GstMatroskaPad *collect_pad;
- GstMatroskaMux *mux = GST_MATROSKA_MUX (parent);
+ GstMatroskaTrackContext *context;
+ GstMatroskaMux *mux;
+ GstPad *pad;
GstTagList *list;
- gboolean ret = TRUE;
+ gboolean ret = FALSE;
+
+ mux = GST_MATROSKA_MUX (user_data);
+ collect_pad = (GstMatroskaPad *) data;
+ pad = data->pad;
+ context = collect_pad->track;
+ g_assert (context);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_CAPS:{
@@ -702,11 +750,6 @@ gst_matroska_mux_handle_sink_event (GstPad * pad, GstObject * parent,
GST_DEBUG_OBJECT (mux, "received tag event");
gst_event_parse_tag (event, &list);
- collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
- g_assert (collect_pad);
- context = collect_pad->track;
- g_assert (context);
-
/* Matroska wants ISO 639-2B code, taglist most likely contains 639-1 */
if (gst_tag_list_get_string (list, GST_TAG_LANGUAGE_CODE, &lang)) {
const gchar *lang_code;
@@ -735,7 +778,6 @@ gst_matroska_mux_handle_sink_event (GstPad * pad, GstObject * parent,
gst_event_parse_segment (event, &segment);
if (segment->format != GST_FORMAT_TIME) {
- ret = FALSE;
gst_event_unref (event);
event = NULL;
}
@@ -749,6 +791,31 @@ gst_matroska_mux_handle_sink_event (GstPad * pad, GstObject * parent,
gst_event_replace (&mux->force_key_unit_event, NULL);
mux->force_key_unit_event = event;
event = NULL;
+ } else if (gst_structure_has_name (structure, "application/x-gst-dvd") &&
+ !strcmp ("dvd-spu-clut-change",
+ gst_structure_get_string (structure, "event"))) {
+ gchar name[16];
+ gint i, value;
+ guint clut[16];
+
+ GST_DEBUG_OBJECT (pad, "New DVD colour table received");
+ if (context->type != GST_MATROSKA_TRACK_TYPE_SUBTITLE) {
+ GST_DEBUG_OBJECT (pad, "... discarding");
+ break;
+ }
+ /* first transform event data into table form */
+ for (i = 0; i < 16; i++) {
+ g_snprintf (name, sizeof (name), "clut%02d", i);
+ if (!gst_structure_get_int (structure, name, &value)) {
+ GST_ERROR_OBJECT (mux, "dvd-spu-clut-change event did not "
+ "contain %s field", name);
+ break;
+ }
+ clut[i] = value;
+ }
+
+ /* transform into private data for stream; text form */
+ gst_matroska_mux_build_vobsub_private (context, clut);
}
break;
}
@@ -756,13 +823,19 @@ gst_matroska_mux_handle_sink_event (GstPad * pad, GstObject * parent,
break;
}
- /* now GstCollectPads can take care of the rest, e.g. EOS */
- if (event)
- ret = mux->collect_event (pad, parent, event);
-
+ /* now GstCollectPads2 can take care of the rest, e.g. EOS */
return ret;
}
+static void
+gst_matroska_mux_set_codec_id (GstMatroskaTrackContext * context,
+ const char *id)
+{
+ g_assert (context && id);
+ if (context->codec_id)
+ g_free (context->codec_id);
+ context->codec_id = g_strdup (id);
+}
/**
* gst_matroska_mux_video_pad_setcaps:
@@ -872,12 +945,13 @@ skip_details:
/* find type */
if (!strcmp (mimetype, "video/x-raw")) {
const gchar *fstr;
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
fstr = gst_structure_get_string (structure, "format");
if (fstr && strlen (fstr) == 4)
videocontext->fourcc = GST_STR_FOURCC (fstr);
} else if (!strcmp (mimetype, "image/jpeg")) {
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MJPEG);
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_MJPEG);
} else if (!strcmp (mimetype, "video/x-xvid") /* MS/VfW compatibility cases */
||!strcmp (mimetype, "video/x-huffyuv")
|| !strcmp (mimetype, "video/x-divx")
@@ -970,11 +1044,13 @@ skip_details:
(guint8 *) bih + sizeof (gst_riff_strf_vids), -1);
}
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
context->codec_priv = (gpointer) bih;
context->codec_priv_size = size;
} else if (!strcmp (mimetype, "video/x-h264")) {
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AVC);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AVC);
if (context->codec_priv != NULL) {
g_free (context->codec_priv);
@@ -991,7 +1067,7 @@ skip_details:
} else if (!strcmp (mimetype, "video/x-theora")) {
const GValue *streamheader;
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_THEORA);
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_THEORA);
if (context->codec_priv != NULL) {
g_free (context->codec_priv);
@@ -1006,22 +1082,25 @@ skip_details:
goto refuse_caps;
}
} else if (!strcmp (mimetype, "video/x-dirac")) {
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_DIRAC);
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_DIRAC);
} else if (!strcmp (mimetype, "video/x-vp8")) {
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_VP8);
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_VIDEO_VP8);
} else if (!strcmp (mimetype, "video/mpeg")) {
gint mpegversion;
gst_structure_get_int (structure, "mpegversion", &mpegversion);
switch (mpegversion) {
case 1:
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MPEG1);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_VIDEO_MPEG1);
break;
case 2:
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MPEG2);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_VIDEO_MPEG2);
break;
case 4:
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_ASP);
break;
default:
goto refuse_caps;
@@ -1044,16 +1123,20 @@ skip_details:
gst_structure_get_int (structure, "rmversion", &rmversion);
switch (rmversion) {
case 1:
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO1);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO1);
break;
case 2:
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO2);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO2);
break;
case 3:
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO3);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO3);
break;
case 4:
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO4);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO4);
break;
default:
goto refuse_caps;
@@ -1551,13 +1634,16 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
switch (layer) {
case 1:
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1);
break;
case 2:
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2);
break;
case 3:
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L3);
break;
default:
goto refuse_caps;
@@ -1620,14 +1706,16 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
goto refuse_caps;
}
if (GST_AUDIO_INFO_IS_BIG_ENDIAN (&info))
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE);
else
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE);
break;
-
case GST_AUDIO_FORMAT_F32LE:
case GST_AUDIO_FORMAT_F64LE:
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT);
break;
default:
@@ -1636,11 +1724,10 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
}
audiocontext->bitdepth = GST_AUDIO_INFO_WIDTH (&info);
-
} else if (!strcmp (mimetype, "audio/x-vorbis")) {
const GValue *streamheader;
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_VORBIS);
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS);
if (context->codec_priv != NULL) {
g_free (context->codec_priv);
@@ -1657,7 +1744,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
} else if (!strcmp (mimetype, "audio/x-flac")) {
const GValue *streamheader;
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_FLAC);
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_FLAC);
if (context->codec_priv != NULL) {
g_free (context->codec_priv);
context->codec_priv = NULL;
@@ -1673,7 +1760,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
} else if (!strcmp (mimetype, "audio/x-speex")) {
const GValue *streamheader;
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_SPEEX);
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_SPEEX);
if (context->codec_priv != NULL) {
g_free (context->codec_priv);
context->codec_priv = NULL;
@@ -1687,11 +1774,11 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
goto refuse_caps;
}
} else if (!strcmp (mimetype, "audio/x-ac3")) {
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_AC3);
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_AC3);
} else if (!strcmp (mimetype, "audio/x-eac3")) {
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_EAC3);
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_EAC3);
} else if (!strcmp (mimetype, "audio/x-dts")) {
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_DTS);
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_DTS);
} else if (!strcmp (mimetype, "audio/x-tta")) {
gint width;
@@ -1700,7 +1787,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
gst_structure_get_int (structure, "width", &width);
audiocontext->bitdepth = width;
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_TTA);
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_TTA);
} else if (!strcmp (mimetype, "audio/x-pn-realaudio")) {
gint raversion;
@@ -1709,13 +1796,16 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
gst_structure_get_int (structure, "raversion", &raversion);
switch (raversion) {
case 1:
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4);
break;
case 2:
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_REAL_28_8);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_AUDIO_REAL_28_8);
break;
case 8:
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK);
break;
default:
goto refuse_caps;
@@ -1816,7 +1906,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
(guint8 *) codec_priv + WAVEFORMATEX_SIZE, -1);
}
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_ACM);
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_AUDIO_ACM);
context->codec_priv = (gpointer) codec_priv;
context->codec_priv_size = codec_priv_size;
}
@@ -1832,6 +1922,10 @@ refuse_caps:
}
}
+/* we probably don't have the data at start,
+ * so have to reserve (a maximum) space to write this at the end.
+ * bit spacy, but some formats can hold quite some */
+#define SUBTITLE_MAX_CODEC_PRIVATE 2048 /* must be > 128 */
/**
* gst_matroska_mux_subtitle_pad_setcaps:
@@ -1845,11 +1939,6 @@ refuse_caps:
static gboolean
gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
{
- /* FIXME:
- * Consider this as boilerplate code for now. There is
- * no single subtitle creation element in GStreamer,
- * neither do I know how subtitling works at all. */
-
/* There is now (at least) one such alement (kateenc), and I'm going
to handle it here and claim it works when it can be piped back
through GStreamer and VLC */
@@ -1860,6 +1949,10 @@ gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
GstMatroskaPad *collect_pad;
const gchar *mimetype;
GstStructure *structure;
+ const GValue *value = NULL;
+ GstBuffer *buf = NULL;
+ gchar *id = NULL;
+ gboolean ret = TRUE;
mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
@@ -1874,17 +1967,19 @@ gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
structure = gst_caps_get_structure (caps, 0);
mimetype = gst_structure_get_name (structure);
+ /* keep track of default set in request_pad */
+ id = context->codec_id;
+
/* general setup */
scontext->check_utf8 = 1;
scontext->invalid_utf8 = 0;
context->default_duration = 0;
- /* TODO: - other format than Kate */
-
if (!strcmp (mimetype, "subtitle/x-kate")) {
const GValue *streamheader;
- context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_SUBTITLE_KATE);
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_SUBTITLE_KATE);
if (context->codec_priv != NULL) {
g_free (context->codec_priv);
@@ -1896,12 +1991,64 @@ gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
if (!kate_streamheader_to_codecdata (streamheader, context)) {
GST_ELEMENT_ERROR (mux, STREAM, MUX, (NULL),
("kate stream headers missing or malformed"));
- return FALSE;
- }
- return TRUE;
+ ret = FALSE;
+ goto exit;
+ }
+ } else if (!strcmp (mimetype, "text/plain")) {
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_SUBTITLE_UTF8);
+ } else if (!strcmp (mimetype, "application/x-ssa")) {
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_SSA);
+ } else if (!strcmp (mimetype, "application/x-ass")) {
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_ASS);
+ } else if (!strcmp (mimetype, "application/x-usf")) {
+ gst_matroska_mux_set_codec_id (context, GST_MATROSKA_CODEC_ID_SUBTITLE_USF);
+ } else if (!strcmp (mimetype, "video/x-dvd-subpicture")) {
+ gst_matroska_mux_set_codec_id (context,
+ GST_MATROSKA_CODEC_ID_SUBTITLE_VOBSUB);
+ } else {
+ id = NULL;
+ ret = FALSE;
+ goto exit;
}
- return FALSE;
+ /* maybe some private data, e.g. vobsub */
+ value = gst_structure_get_value (structure, "codec_data");
+ if (value)
+ buf = gst_value_get_buffer (value);
+ if (buf != NULL) {
+ guint8 *priv_data = NULL, *priv_buffer_data;
+ gsize priv_data_size = 0;
+
+ priv_buffer_data =
+ gst_buffer_map (buf, &priv_data_size, NULL, GST_MAP_READ);
+ if (priv_data_size > SUBTITLE_MAX_CODEC_PRIVATE) {
+ GST_WARNING_OBJECT (mux, "pad %" GST_PTR_FORMAT " subtitle private data"
+ " exceeded maximum (%d); discarding", pad,
+ SUBTITLE_MAX_CODEC_PRIVATE);
+ gst_buffer_unmap (buf, priv_data, priv_data_size);
+ return TRUE;
+ }
+
+ if (context->codec_priv != NULL)
+ g_free (context->codec_priv);
+
+ priv_data = g_malloc0 (priv_data_size);
+ memcpy (priv_data, priv_buffer_data, priv_data_size);
+ context->codec_priv = priv_data;
+ context->codec_priv_size = priv_data_size;
+ gst_buffer_unmap (buf, priv_buffer_data, priv_data_size);
+ }
+
+ GST_DEBUG_OBJECT (pad, "codec_id %s, codec data size %u",
+ GST_STR_NULL (context->codec_id), context->codec_priv_size);
+
+exit:
+ /* free default if modified */
+ if (id)
+ g_free (id);
+
+ return ret;
}
@@ -1928,6 +2075,8 @@ gst_matroska_mux_request_new_pad (GstElement * element,
GstMatroskaCapsFunc capsfunc = NULL;
GstMatroskaTrackContext *context = NULL;
gint pad_id;
+ gboolean locked = TRUE;
+ gchar *id = NULL;
if (templ == gst_element_class_get_pad_template (klass, "audio_%u")) {
/* don't mix named and unnamed pads, if the pad already exists we fail when
@@ -1971,6 +2120,9 @@ gst_matroska_mux_request_new_pad (GstElement * element,
g_new0 (GstMatroskaTrackSubtitleContext, 1);
context->type = GST_MATROSKA_TRACK_TYPE_SUBTITLE;
context->name = g_strdup ("Subtitle");
+ /* setcaps may only provide proper one a lot later */
+ id = g_strdup ("S_SUB_UNKNOWN");
+ locked = FALSE;
} else {
GST_WARNING_OBJECT (mux, "This is not our template!");
return NULL;
@@ -1982,24 +2134,13 @@ gst_matroska_mux_request_new_pad (GstElement * element,
gst_matroskamux_pad_init (newpad);
collect_pad = (GstMatroskaPad *)
- gst_collect_pads_add_pad (mux->collect, GST_PAD (newpad),
- sizeof (GstMatroskaPad),
- (GstCollectDataDestroyNotify) gst_matroska_pad_free);
+ gst_collect_pads2_add_pad_full (mux->collect, GST_PAD (newpad),
+ sizeof (GstMatroskamuxPad),
+ (GstCollectData2DestroyNotify) gst_matroska_pad_free, locked);
collect_pad->track = context;
gst_matroska_pad_reset (collect_pad, FALSE);
-
- /* FIXME: hacked way to override/extend the event function of
- * GstCollectPads; because it sets its own event function giving the
- * element no access to events.
- * TODO GstCollectPads should really give its 'users' a clean chance to
- * properly handle events that are not meant for collectpads itself.
- * Perhaps a callback or so, though rejected (?) in #340060.
- * This would allow (clean) transcoding of info from demuxer/streams
- * to another muxer */
- mux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
- gst_pad_set_event_function (GST_PAD (newpad),
- GST_DEBUG_FUNCPTR (gst_matroska_mux_handle_sink_event));
+ collect_pad->track->codec_id = id;
collect_pad->capsfunc = capsfunc;
gst_pad_set_active (GST_PAD (newpad), TRUE);
@@ -2037,7 +2178,7 @@ gst_matroska_mux_release_pad (GstElement * element, GstPad * pad)
mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
for (walk = mux->collect->data; walk; walk = g_slist_next (walk)) {
- GstCollectData *cdata = (GstCollectData *) walk->data;
+ GstCollectData2 *cdata = (GstCollectData2 *) walk->data;
GstMatroskaPad *collect_pad = (GstMatroskaPad *) cdata;
if (cdata->pad == pad) {
@@ -2058,7 +2199,7 @@ gst_matroska_mux_release_pad (GstElement * element, GstPad * pad)
}
}
- gst_collect_pads_remove_pad (mux->collect, pad);
+ gst_collect_pads2_remove_pad (mux->collect, pad);
if (gst_element_remove_pad (element, pad))
mux->num_streams--;
}
@@ -2095,6 +2236,14 @@ gst_matroska_mux_track_header (GstMatroskaMux * mux,
context->language);
}
+ /* FIXME: until we have a nice way of getting the codecname
+ * out of the caps, I'm not going to enable this. Too much
+ * (useless, double, boring) work... */
+ /* TODO: Use value from tags if any */
+ /*gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_CODECNAME,
+ context->codec_name); */
+ gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TRACKNAME, context->name);
+
/* type-specific stuff */
switch (context->type) {
case GST_MATROSKA_TRACK_TYPE_VIDEO:{
@@ -2145,6 +2294,24 @@ gst_matroska_mux_track_header (GstMatroskaMux * mux,
break;
}
+ /* this is what we write for now and must be filled
+ * and remainder void'ed later on */
+#define SUBTITLE_DUMMY_SIZE (1 + 1 + 14 + 1 + 2 + SUBTITLE_MAX_CODEC_PRIVATE)
+
+ case GST_MATROSKA_TRACK_TYPE_SUBTITLE:{
+ gpointer buf;
+
+ context->pos = ebml->pos;
+ /* CodecID is mandatory ... */
+ gst_ebml_write_ascii (ebml, GST_MATROSKA_ID_CODECID, "S_SUB_UNKNOWN");
+ /* reserve space */
+ buf = g_malloc0 (SUBTITLE_MAX_CODEC_PRIVATE);
+ gst_ebml_write_binary (ebml, GST_EBML_ID_VOID, buf,
+ SUBTITLE_MAX_CODEC_PRIVATE);
+ g_free (buf);
+ /* real data has to be written at finish */
+ return;
+ }
default:
/* doesn't need type-specific data */
break;
@@ -2154,13 +2321,6 @@ gst_matroska_mux_track_header (GstMatroskaMux * mux,
if (context->codec_priv)
gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECPRIVATE,
context->codec_priv, context->codec_priv_size);
- /* FIXME: until we have a nice way of getting the codecname
- * out of the caps, I'm not going to enable this. Too much
- * (useless, double, boring) work... */
- /* TODO: Use value from tags if any */
- /*gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_CODECNAME,
- context->codec_name); */
- gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_TRACKNAME, context->name);
}
@@ -2230,7 +2390,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
if (tags != NULL && !gst_tag_list_is_empty (tags)) {
guint64 master_tags, master_tag;
- GST_DEBUG ("Writing tags");
+ GST_DEBUG_OBJECT (mux, "Writing tags");
/* TODO: maybe limit via the TARGETS id by looking at the source pad */
mux->tags_pos = ebml->pos;
@@ -2304,7 +2464,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKENTRY);
gst_matroska_mux_track_header (mux, collect_pad->track);
gst_ebml_write_master_finish (ebml, child);
- /* some remaing pad/track setup */
+ /* some remaining pad/track setup */
collect_pad->default_duration_scaled =
gst_util_uint64_scale (collect_pad->track->default_duration,
1, mux->time_scale);
@@ -2431,7 +2591,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
if (tags != NULL && !gst_tag_list_is_empty (tags)) {
guint64 master_tags, master_tag;
- GST_DEBUG ("Writing tags");
+ GST_DEBUG_OBJECT (mux, "Writing tags");
/* TODO: maybe limit via the TARGETS id by looking at the source pad */
mux->tags_pos = ebml->pos;
@@ -2479,16 +2639,23 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
gst_ebml_write_seek (ebml, my_pos);
}
- /* update duration */
- /* first get the overall duration */
- /* a released track may have left a duration in here */
+ /* loop tracks:
+ * - first get the overall duration
+ * (a released track may have left a duration in here)
+ * - write some track header data for subtitles
+ */
duration = mux->duration;
+ pos = ebml->pos;
for (collected = mux->collect->data; collected;
collected = g_slist_next (collected)) {
GstMatroskaPad *collect_pad;
GstClockTime min_duration; /* observed minimum duration */
+ GstMatroskaTrackContext *context;
+ gint voidleft = 0, fill = 0;
+ gpointer codec_id;
collect_pad = (GstMatroskaPad *) collected->data;
+ context = collect_pad->track;
GST_DEBUG_OBJECT (mux,
"Pad %" GST_PTR_FORMAT " start ts %" GST_TIME_FORMAT
@@ -2510,7 +2677,41 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
if (GST_CLOCK_TIME_IS_VALID (collect_pad->duration) &&
duration < collect_pad->duration)
duration = collect_pad->duration;
- }
+
+ if (context->type != GST_MATROSKA_TRACK_TYPE_SUBTITLE || !context->pos)
+ continue;
+
+ again:
+ /* write subtitle type and possible private data */
+ gst_ebml_write_seek (ebml, context->pos);
+ /* complex way to write ascii to account for extra filling */
+ codec_id = g_malloc0 (strlen (context->codec_id) + 1 + fill);
+ strcpy (codec_id, context->codec_id);
+ gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECID,
+ codec_id, strlen (context->codec_id) + 1 + fill);
+ g_free (codec_id);
+ if (context->codec_priv)
+ gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECPRIVATE,
+ context->codec_priv, context->codec_priv_size);
+ voidleft = SUBTITLE_DUMMY_SIZE - (ebml->pos - context->pos);
+ /* void'ify; sigh, variable sized length field */
+ if (voidleft == 1) {
+ fill = 1;
+ goto again;
+ } else if (voidleft && voidleft <= 128)
+ gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, voidleft - 2);
+ else if (voidleft >= 130)
+ gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, voidleft - 3);
+ else if (voidleft == 129) {
+ gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 64);
+ gst_ebml_write_buffer_header (ebml, GST_EBML_ID_VOID, 63);
+ }
+ }
+
+ /* seek back (optional, but do anyway) */
+ gst_ebml_write_seek (ebml, pos);
+
+ /* update duration */
if (duration != 0) {
GST_DEBUG_OBJECT (mux, "final total duration: %" GST_TIME_FORMAT,
GST_TIME_ARGS (duration));
@@ -2533,77 +2734,6 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
gst_ebml_write_master_finish (ebml, mux->segment_pos);
}
-
-/**
- * gst_matroska_mux_best_pad:
- * @mux: #GstMatroskaMux
- * @popped: True if at least one buffer was popped from #GstCollectPads
- *
- * Find a pad with the oldest data
- * (data from this pad should be written first).
- *
- * Returns: Selected pad.
- */
-static GstMatroskaPad *
-gst_matroska_mux_best_pad (GstMatroskaMux * mux, gboolean * popped)
-{
- GSList *collected;
- GstMatroskaPad *best = NULL;
-
- *popped = FALSE;
- for (collected = mux->collect->data; collected;
- collected = g_slist_next (collected)) {
- GstMatroskaPad *collect_pad;
-
- collect_pad = (GstMatroskaPad *) collected->data;
- /* fetch a new buffer if needed */
- if (collect_pad->buffer == NULL) {
- collect_pad->buffer = gst_collect_pads_pop (mux->collect,
- (GstCollectData *) collect_pad);
-
- if (collect_pad->buffer != NULL) {
- GstClockTime time;
-
- *popped = TRUE;
- /* convert to running time */
- time = GST_BUFFER_TIMESTAMP (collect_pad->buffer);
- /* invalid should pass */
- if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) {
- time = gst_segment_to_running_time (&collect_pad->collect.segment,
- GST_FORMAT_TIME, time);
- if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
- GST_DEBUG_OBJECT (mux, "clipping buffer on pad %s outside segment",
- GST_PAD_NAME (collect_pad->collect.pad));
- gst_buffer_unref (collect_pad->buffer);
- collect_pad->buffer = NULL;
- return NULL;
- } else {
- GST_LOG_OBJECT (mux, "buffer ts %" GST_TIME_FORMAT " -> %"
- GST_TIME_FORMAT " running time",
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (collect_pad->buffer)),
- GST_TIME_ARGS (time));
- collect_pad->buffer =
- gst_buffer_make_writable (collect_pad->buffer);
- GST_BUFFER_TIMESTAMP (collect_pad->buffer) = time;
- }
- }
- }
- }
-
- /* if we have a buffer check if it is better then the current best one */
- if (collect_pad->buffer != NULL) {
- if (best == NULL || !GST_BUFFER_TIMESTAMP_IS_VALID (collect_pad->buffer)
- || (GST_BUFFER_TIMESTAMP_IS_VALID (best->buffer)
- && GST_BUFFER_TIMESTAMP (collect_pad->buffer) <
- GST_BUFFER_TIMESTAMP (best->buffer))) {
- best = collect_pad;
- }
- }
- }
-
- return best;
-}
-
/**
* gst_matroska_mux_buffer_header:
* @track: Track context.
@@ -2749,10 +2879,11 @@ gst_matroska_mux_stop_streamheader (GstMatroskaMux * mux)
* Returns: Result of the gst_pad_push issued to write the data.
*/
static GstFlowReturn
-gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
+gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
+ GstBuffer * buf)
{
GstEbmlWrite *ebml = mux->ebml_write;
- GstBuffer *buf, *hdr;
+ GstBuffer *hdr;
guint64 blockgroup;
gboolean write_duration;
gint16 relative_timestamp;
@@ -2762,8 +2893,6 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
GstMatroskamuxPad *pad;
/* write data */
- buf = collect_pad->buffer;
- collect_pad->buffer = NULL;
pad = GST_MATROSKAMUX_PAD_CAST (collect_pad->collect.pad);
/* vorbis/theora headers are retrieved from caps and put in CodecPrivate */
@@ -2953,10 +3082,9 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
}
}
-
/**
- * gst_matroska_mux_collected:
- * @pads: #GstCollectPads
+ * gst_matroska_mux_handle_buffer:
+ * @pads: #GstCollectPads2
* @uuser_data: #GstMatroskaMux
*
* Collectpads callback.
@@ -2964,12 +3092,12 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
* Returns: #GstFlowReturn
*/
static GstFlowReturn
-gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
+gst_matroska_mux_handle_buffer (GstCollectPads2 * pads, GstCollectData2 * data,
+ GstBuffer * buf, gpointer user_data)
{
GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
GstEbmlWrite *ebml = mux->ebml_write;
GstMatroskaPad *best;
- gboolean popped;
GstFlowReturn ret = GST_FLOW_OK;
GST_DEBUG_OBJECT (mux, "Collected pads");
@@ -2988,53 +3116,53 @@ gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
mux->state = GST_MATROSKA_MUX_STATE_DATA;
}
- do {
- /* which stream to write from? */
- best = gst_matroska_mux_best_pad (mux, &popped);
+ /* provided with stream to write from */
+ best = (GstMatroskaPad *) data;
- /* if there is no best pad, we have reached EOS */
- if (best == NULL) {
- /* buffer popped, but none returned means it was clipped */
- if (popped)
- break;
- GST_DEBUG_OBJECT (mux, "No best pad finishing...");
- if (!mux->streamable) {
- gst_matroska_mux_finish (mux);
- } else {
- GST_DEBUG_OBJECT (mux, "... but streamable, nothing to finish");
- }
- gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
- ret = GST_FLOW_EOS;
- break;
+ /* if there is no best pad, we have reached EOS */
+ if (best == NULL) {
+ GST_DEBUG_OBJECT (mux, "No best pad finishing...");
+ if (!mux->streamable) {
+ gst_matroska_mux_finish (mux);
+ } else {
+ GST_DEBUG_OBJECT (mux, "... but streamable, nothing to finish");
}
- GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
- GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (best->buffer)),
- GST_TIME_ARGS (GST_BUFFER_DURATION (best->buffer)));
+ gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
+ ret = GST_FLOW_EOS;
+ goto exit;
+ }
- /* make note of first and last encountered timestamps, so we can calculate
- * the actual duration later when we send an updated header on eos */
- if (GST_BUFFER_TIMESTAMP_IS_VALID (best->buffer)) {
- GstClockTime start_ts = GST_BUFFER_TIMESTAMP (best->buffer);
- GstClockTime end_ts = start_ts;
+ /* if we have a best stream, should also have a buffer */
+ g_assert (buf);
- if (GST_BUFFER_DURATION_IS_VALID (best->buffer))
- end_ts += GST_BUFFER_DURATION (best->buffer);
- else if (best->track->default_duration)
- end_ts += best->track->default_duration;
+ GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
+ GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
+ GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
- if (!GST_CLOCK_TIME_IS_VALID (best->end_ts) || end_ts > best->end_ts)
- best->end_ts = end_ts;
+ /* make note of first and last encountered timestamps, so we can calculate
+ * the actual duration later when we send an updated header on eos */
+ if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
+ GstClockTime start_ts = GST_BUFFER_TIMESTAMP (buf);
+ GstClockTime end_ts = start_ts;
- if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE ||
- start_ts < best->start_ts))
- best->start_ts = start_ts;
- }
+ if (GST_BUFFER_DURATION_IS_VALID (buf))
+ end_ts += GST_BUFFER_DURATION (buf);
+ else if (best->track->default_duration)
+ end_ts += best->track->default_duration;
+
+ if (!GST_CLOCK_TIME_IS_VALID (best->end_ts) || end_ts > best->end_ts)
+ best->end_ts = end_ts;
+
+ if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE ||
+ start_ts < best->start_ts))
+ best->start_ts = start_ts;
+ }
- /* write one buffer */
- ret = gst_matroska_mux_write_data (mux, best);
- } while (ret == GST_FLOW_OK && !popped);
+ /* write one buffer */
+ ret = gst_matroska_mux_write_data (mux, best, buf);
+exit:
return ret;
}
@@ -3058,12 +3186,12 @@ gst_matroska_mux_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_NULL_TO_READY:
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
- gst_collect_pads_start (mux->collect);
+ gst_collect_pads2_start (mux->collect);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_collect_pads_stop (mux->collect);
+ gst_collect_pads2_stop (mux->collect);
break;
default:
break;
diff --git a/gst/matroska/matroska-mux.h b/gst/matroska/matroska-mux.h
index 4377f26b7..da9a3e7bf 100644
--- a/gst/matroska/matroska-mux.h
+++ b/gst/matroska/matroska-mux.h
@@ -24,7 +24,7 @@
#define __GST_MATROSKA_MUX_H__
#include <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
+#include <gst/base/gstcollectpads2.h>
#include "ebml-write.h"
#include "matroska-ids.h"
@@ -58,12 +58,10 @@ typedef gboolean (*GstMatroskaCapsFunc) (GstPad *pad, GstCaps *caps);
/* all information needed for one matroska stream */
typedef struct
{
- GstCollectData collect; /* we extend the CollectData */
+ GstCollectData2 collect; /* we extend the CollectData */
GstMatroskaCapsFunc capsfunc;
GstMatroskaTrackContext *track;
- GstBuffer *buffer; /* the queued buffer for this pad */
-
guint64 duration;
GstClockTime start_ts;
GstClockTime end_ts; /* last timestamp + (if available) duration */
@@ -79,8 +77,7 @@ typedef struct _GstMatroskaMux {
/* pads */
GstPad *srcpad;
- GstCollectPads *collect;
- GstPadEventFunction collect_event;
+ GstCollectPads2 *collect;
GstEbmlWrite *ebml_write;
guint num_streams,
diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c
index fe07e295a..0b45855df 100644
--- a/gst/matroska/matroska-read-common.c
+++ b/gst/matroska/matroska-read-common.c
@@ -999,6 +999,21 @@ gst_matroska_read_common_parse_index_cuetrack (GstMatroskaReadCommon * common,
DEBUG_ELEMENT_STOP (common, ebml, "CueTrackPositions", ret);
+ /* (e.g.) lavf typically creates entries without a block number,
+ * which is bogus and leads to contradictory information */
+ if (common->index->len) {
+ GstMatroskaIndex *last_idx;
+
+ last_idx = &g_array_index (common->index, GstMatroskaIndex,
+ common->index->len - 1);
+ if (last_idx->block == idx.block && last_idx->pos == idx.pos &&
+ last_idx->track == idx.track && idx.time > last_idx->time) {
+ GST_DEBUG_OBJECT (common, "Cue entry refers to same location, "
+ "but has different time than previous entry; discarding");
+ idx.track = 0;
+ }
+ }
+
if ((ret == GST_FLOW_OK || ret == GST_FLOW_EOS)
&& idx.pos != (guint64) - 1 && idx.track > 0) {
g_array_append_val (common->index, idx);
diff --git a/gst/multifile/gstmultifilesink.c b/gst/multifile/gstmultifilesink.c
index 50d1f976d..af192900f 100644
--- a/gst/multifile/gstmultifilesink.c
+++ b/gst/multifile/gstmultifilesink.c
@@ -655,12 +655,17 @@ write_error:
return GST_FLOW_ERROR;
}
stdio_write_error:
- {
- GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
- ("Error while writing to file."), (NULL));
- gst_buffer_unmap (buffer, data, size);
- return GST_FLOW_ERROR;
+ switch (errno) {
+ case ENOSPC:
+ GST_ELEMENT_ERROR (multifilesink, RESOURCE, NO_SPACE_LEFT,
+ ("Error while writing to file."), ("%s", g_strerror (errno)));
+ break;
+ default:
+ GST_ELEMENT_ERROR (multifilesink, RESOURCE, WRITE,
+ ("Error while writing to file."), ("%s", g_strerror (errno)));
}
+ gst_buffer_unmap (buffer, data, size);
+ return GST_FLOW_ERROR;
}
static gboolean
diff --git a/gst/multipart/multipartmux.c b/gst/multipart/multipartmux.c
index 73ddbbefd..475630485 100644
--- a/gst/multipart/multipartmux.c
+++ b/gst/multipart/multipartmux.c
@@ -84,7 +84,7 @@ static GstPad *gst_multipart_mux_request_new_pad (GstElement * element,
static GstStateChangeReturn gst_multipart_mux_change_state (GstElement *
element, GstStateChange transition);
-static GstFlowReturn gst_multipart_mux_collected (GstCollectPads * pads,
+static GstFlowReturn gst_multipart_mux_collected (GstCollectPads2 * pads,
GstMultipartMux * mux);
static void gst_multipart_mux_set_property (GObject * object, guint prop_id,
@@ -148,9 +148,9 @@ gst_multipart_mux_init (GstMultipartMux * multipart_mux)
multipart_mux->boundary = g_strdup (DEFAULT_BOUNDARY);
- multipart_mux->collect = gst_collect_pads_new ();
- gst_collect_pads_set_function (multipart_mux->collect,
- (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_multipart_mux_collected),
+ multipart_mux->collect = gst_collect_pads2_new ();
+ gst_collect_pads2_set_function (multipart_mux->collect,
+ (GstCollectPads2Function) GST_DEBUG_FUNCPTR (gst_multipart_mux_collected),
multipart_mux);
}
@@ -194,8 +194,8 @@ gst_multipart_mux_request_new_pad (GstElement * element,
GstMultipartPadData *multipartpad;
multipartpad = (GstMultipartPadData *)
- gst_collect_pads_add_pad (multipart_mux->collect, newpad,
- sizeof (GstMultipartPadData), NULL);
+ gst_collect_pads2_add_pad (multipart_mux->collect, newpad,
+ sizeof (GstMultipartPadData));
/* save a pointer to our data in the pad */
multipartpad->pad = newpad;
@@ -340,7 +340,7 @@ gst_multipart_mux_queue_pads (GstMultipartMux * mux)
/* try to make sure we have a buffer from each usable pad first */
walk = mux->collect->data;
while (walk) {
- GstCollectData *data = (GstCollectData *) walk->data;
+ GstCollectData2 *data = (GstCollectData2 *) walk->data;
GstMultipartPadData *pad = (GstMultipartPadData *) data;
walk = g_slist_next (walk);
@@ -349,7 +349,7 @@ gst_multipart_mux_queue_pads (GstMultipartMux * mux)
if (pad->buffer == NULL) {
GstBuffer *buf = NULL;
- buf = gst_collect_pads_pop (mux->collect, data);
+ buf = gst_collect_pads2_pop (mux->collect, data);
/* Store timestamp with segment_start and preroll */
if (buf && GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
@@ -383,7 +383,7 @@ gst_multipart_mux_queue_pads (GstMultipartMux * mux)
* 3) push both buffers on best pad, go to 1
*/
static GstFlowReturn
-gst_multipart_mux_collected (GstCollectPads * pads, GstMultipartMux * mux)
+gst_multipart_mux_collected (GstCollectPads2 * pads, GstMultipartMux * mux)
{
GstMultipartPadData *best;
GstFlowReturn ret = GST_FLOW_OK;
@@ -605,11 +605,11 @@ gst_multipart_mux_change_state (GstElement * element, GstStateChange transition)
multipart_mux->negotiated = FALSE;
multipart_mux->need_segment = TRUE;
GST_DEBUG_OBJECT (multipart_mux, "starting collect pads");
- gst_collect_pads_start (multipart_mux->collect);
+ gst_collect_pads2_start (multipart_mux->collect);
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
GST_DEBUG_OBJECT (multipart_mux, "stopping collect pads");
- gst_collect_pads_stop (multipart_mux->collect);
+ gst_collect_pads2_stop (multipart_mux->collect);
break;
default:
break;
diff --git a/gst/multipart/multipartmux.h b/gst/multipart/multipartmux.h
index d2711ac0e..4583b5098 100644
--- a/gst/multipart/multipartmux.h
+++ b/gst/multipart/multipartmux.h
@@ -23,7 +23,7 @@
#define __GST_MULTIPART_MUX__
#include <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
+#include <gst/base/gstcollectpads2.h>
#include <string.h>
@@ -42,7 +42,7 @@ typedef struct _GstMultipartMuxClass GstMultipartMuxClass;
/* all information needed for one multipart stream */
typedef struct
{
- GstCollectData collect; /* we extend the CollectData */
+ GstCollectData2 collect; /* we extend the CollectData2 */
GstBuffer *buffer; /* the queued buffer for this pad */
GstClockTime timestamp; /* its timestamp, converted to running_time so that we can
@@ -64,7 +64,7 @@ struct _GstMultipartMux
GstPad *srcpad;
/* sinkpads */
- GstCollectPads *collect;
+ GstCollectPads2 *collect;
gint numpads;
diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c
index 2575b224d..615fa3c41 100644
--- a/gst/rtpmanager/gstrtpbin.c
+++ b/gst/rtpmanager/gstrtpbin.c
@@ -129,6 +129,8 @@
#include "gstrtpsession.h"
#include "gstrtpjitterbuffer.h"
+#include <gst/glib-compat-private.h>
+
GST_DEBUG_CATEGORY_STATIC (gst_rtp_bin_debug);
#define GST_CAT_DEFAULT gst_rtp_bin_debug
diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c
index 0472f2c8e..e6ef09447 100644
--- a/gst/rtpmanager/gstrtpjitterbuffer.c
+++ b/gst/rtpmanager/gstrtpjitterbuffer.c
@@ -67,6 +67,8 @@
#include "rtpjitterbuffer.h"
#include "rtpstats.h"
+#include <gst/glib-compat-private.h>
+
GST_DEBUG_CATEGORY (rtpjitterbuffer_debug);
#define GST_CAT_DEFAULT (rtpjitterbuffer_debug)
diff --git a/gst/rtpmanager/gstrtpsession.c b/gst/rtpmanager/gstrtpsession.c
index bb330ddd9..a5df3273b 100644
--- a/gst/rtpmanager/gstrtpsession.c
+++ b/gst/rtpmanager/gstrtpsession.c
@@ -114,6 +114,8 @@
#include <gst/rtp/gstrtpbuffer.h>
+#include <gst/glib-compat-private.h>
+
#include "gstrtpbin-marshal.h"
#include "gstrtpsession.h"
#include "rtpsession.h"
@@ -908,8 +910,13 @@ start_rtcp_thread (GstRtpSession * rtpsession)
g_thread_join (rtpsession->priv->thread);
/* only create a new thread if the old one was stopped. Otherwise we can
* just reuse the currently running one. */
+#if !GLIB_CHECK_VERSION (2, 31, 0)
rtpsession->priv->thread =
g_thread_create ((GThreadFunc) rtcp_thread, rtpsession, TRUE, &error);
+#else
+ rtpsession->priv->thread = g_thread_try_new ("rtpsession-rtcp-thread",
+ (GThreadFunc) rtcp_thread, rtpsession, &error);
+#endif
rtpsession->priv->thread_stopped = FALSE;
}
GST_RTP_SESSION_UNLOCK (rtpsession);
diff --git a/gst/rtpmanager/gstrtpssrcdemux.c b/gst/rtpmanager/gstrtpssrcdemux.c
index 2737c6d89..8a350ba65 100644
--- a/gst/rtpmanager/gstrtpssrcdemux.c
+++ b/gst/rtpmanager/gstrtpssrcdemux.c
@@ -44,6 +44,10 @@
#include "config.h"
#endif
+/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
#include <string.h>
#include <gst/rtp/gstrtpbuffer.h>
#include <gst/rtp/gstrtcpbuffer.h>
diff --git a/gst/rtpmanager/rtpsession.c b/gst/rtpmanager/rtpsession.c
index a73654657..aca25fe7a 100644
--- a/gst/rtpmanager/rtpsession.c
+++ b/gst/rtpmanager/rtpsession.c
@@ -22,6 +22,8 @@
#include <gst/rtp/gstrtpbuffer.h>
#include <gst/rtp/gstrtcpbuffer.h>
+#include <gst/glib-compat-private.h>
+
#include "gstrtpbin-marshal.h"
#include "rtpsession.h"
diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c
index 2694fc665..bbdbf7d44 100644
--- a/gst/rtsp/gstrtspsrc.c
+++ b/gst/rtsp/gstrtspsrc.c
@@ -81,6 +81,10 @@
#include "config.h"
#endif
+/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
diff --git a/gst/smpte/gstsmpte.c b/gst/smpte/gstsmpte.c
index a830e6a52..beb979fc6 100644
--- a/gst/smpte/gstsmpte.c
+++ b/gst/smpte/gstsmpte.c
@@ -152,7 +152,7 @@ static void gst_smpte_base_init (GstSMPTEClass * klass);
static void gst_smpte_init (GstSMPTE * smpte);
static void gst_smpte_finalize (GstSMPTE * smpte);
-static GstFlowReturn gst_smpte_collected (GstCollectPads * pads,
+static GstFlowReturn gst_smpte_collected (GstCollectPads2 * pads,
GstSMPTE * smpte);
static void gst_smpte_set_property (GObject * object, guint prop_id,
@@ -360,15 +360,15 @@ gst_smpte_init (GstSMPTE * smpte)
gst_pad_new_from_static_template (&gst_smpte_src_template, "src");
gst_element_add_pad (GST_ELEMENT (smpte), smpte->srcpad);
- smpte->collect = gst_collect_pads_new ();
- gst_collect_pads_set_function (smpte->collect,
- (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_smpte_collected), smpte);
- gst_collect_pads_start (smpte->collect);
+ smpte->collect = gst_collect_pads2_new ();
+ gst_collect_pads2_set_function (smpte->collect,
+ (GstCollectPads2Function) GST_DEBUG_FUNCPTR (gst_smpte_collected), smpte);
+ gst_collect_pads2_start (smpte->collect);
- gst_collect_pads_add_pad (smpte->collect, smpte->sinkpad1,
- sizeof (GstCollectData), NULL);
- gst_collect_pads_add_pad (smpte->collect, smpte->sinkpad2,
- sizeof (GstCollectData), NULL);
+ gst_collect_pads2_add_pad (smpte->collect, smpte->sinkpad1,
+ sizeof (GstCollectData2));
+ gst_collect_pads2_add_pad (smpte->collect, smpte->sinkpad2,
+ sizeof (GstCollectData2));
smpte->fps = DEFAULT_PROP_FPS;
smpte->type = DEFAULT_PROP_TYPE;
@@ -441,7 +441,7 @@ gst_smpte_blend_i420 (guint8 * in1, guint8 * in2, guint8 * out, GstMask * mask,
}
static GstFlowReturn
-gst_smpte_collected (GstCollectPads * pads, GstSMPTE * smpte)
+gst_smpte_collected (GstCollectPads2 * pads, GstSMPTE * smpte)
{
GstBuffer *outbuf;
GstClockTime ts;
@@ -458,14 +458,14 @@ gst_smpte_collected (GstCollectPads * pads, GstSMPTE * smpte)
smpte->fps_denom, smpte->fps_num);
for (collected = pads->data; collected; collected = g_slist_next (collected)) {
- GstCollectData *data;
+ GstCollectData2 *data;
- data = (GstCollectData *) collected->data;
+ data = (GstCollectData2 *) collected->data;
if (data->pad == smpte->sinkpad1)
- in1 = gst_collect_pads_pop (pads, data);
+ in1 = gst_collect_pads2_pop (pads, data);
else if (data->pad == smpte->sinkpad2)
- in2 = gst_collect_pads_pop (pads, data);
+ in2 = gst_collect_pads2_pop (pads, data);
}
if (in1 == NULL) {
@@ -623,11 +623,11 @@ gst_smpte_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_READY_TO_PAUSED:
gst_smpte_reset (smpte);
GST_LOG_OBJECT (smpte, "starting collectpads");
- gst_collect_pads_start (smpte->collect);
+ gst_collect_pads2_start (smpte->collect);
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
GST_LOG_OBJECT (smpte, "stopping collectpads");
- gst_collect_pads_stop (smpte->collect);
+ gst_collect_pads2_stop (smpte->collect);
break;
default:
break;
diff --git a/gst/smpte/gstsmpte.h b/gst/smpte/gstsmpte.h
index dc6bc6d8a..ac138f4e7 100644
--- a/gst/smpte/gstsmpte.h
+++ b/gst/smpte/gstsmpte.h
@@ -22,7 +22,7 @@
#define __GST_SMPTE_H__
#include <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
+#include <gst/base/gstcollectpads2.h>
G_BEGIN_DECLS
@@ -49,7 +49,7 @@ struct _GstSMPTE {
GstPad *srcpad,
*sinkpad1,
*sinkpad2;
- GstCollectPads *collect;
+ GstCollectPads2 *collect;
/* properties */
gint type;
diff --git a/gst/udp/gstmultiudpsink.c b/gst/udp/gstmultiudpsink.c
index a302465bd..970b4aef0 100644
--- a/gst/udp/gstmultiudpsink.c
+++ b/gst/udp/gstmultiudpsink.c
@@ -41,6 +41,8 @@
#include <errno.h>
#include <string.h>
+#include "gst/glib-compat-private.h"
+
GST_DEBUG_CATEGORY_STATIC (multiudpsink_debug);
#define GST_CAT_DEFAULT (multiudpsink_debug)
diff --git a/gst/udp/gstudpsrc.c b/gst/udp/gstudpsrc.c
index 9169d6b13..d9d45e1d8 100644
--- a/gst/udp/gstudpsrc.c
+++ b/gst/udp/gstudpsrc.c
@@ -471,12 +471,21 @@ retry:
IOCTL_SOCKET (udpsrc->sock.fd, FIONREAD, &readsize)) < 0))
goto ioctl_failed;
- /* if we get here and there is nothing to read from the socket, the select got
- * woken up by activity on the socket but it was not a read. We know someone
- * will also do something with the socket so that we don't go into an infinite
- * loop in the select(). */
+ /* If we get here and the readsize is zero, then either select was woken up
+ * by activity that is not a read, or a poll error occurred, or a UDP packet
+ * was received that has no data. Since we cannot identify which case it is,
+ * we handle all of them. This could possibly lead to a UDP packet getting
+ * lost, but since UDP is not reliable, we can accept this. */
if (G_UNLIKELY (!readsize)) {
+ /* try to read a packet (and it will be ignored),
+ * in case a packet with no data arrived */
+ slen = sizeof (sa);
+ recvfrom (udpsrc->sock.fd, (char *) &slen, 0, 0, &sa.sa, &slen);
+
+ /* clear any error, in case a poll error occurred */
clear_error (udpsrc);
+
+ /* poll again */
goto retry;
}
diff --git a/gst/videocrop/gstaspectratiocrop.c b/gst/videocrop/gstaspectratiocrop.c
index eb0ece2bf..1be97fa79 100644
--- a/gst/videocrop/gstaspectratiocrop.c
+++ b/gst/videocrop/gstaspectratiocrop.c
@@ -43,6 +43,8 @@
#include "gstaspectratiocrop.h"
+#include "gst/glib-compat-private.h"
+
GST_DEBUG_CATEGORY_STATIC (aspect_ratio_crop_debug);
#define GST_CAT_DEFAULT aspect_ratio_crop_debug
diff --git a/gst/videomixer/videomixer2.c b/gst/videomixer/videomixer2.c
index e72031d5f..b8d419ae9 100644
--- a/gst/videomixer/videomixer2.c
+++ b/gst/videomixer/videomixer2.c
@@ -86,6 +86,10 @@
#include "config.h"
#endif
+/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
#include <string.h>
#include "videomixer2.h"
diff --git a/gst/wavparse/gstwavparse.c b/gst/wavparse/gstwavparse.c
index e494b2fd4..1306a9a26 100644
--- a/gst/wavparse/gstwavparse.c
+++ b/gst/wavparse/gstwavparse.c
@@ -49,6 +49,11 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+
+/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
+ * with newer GLib versions (>= 2.31.0) */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
#include <string.h>
#include <math.h>
@@ -85,6 +90,19 @@ static void gst_wavparse_loop (GstPad * pad);
static gboolean gst_wavparse_srcpad_event (GstPad * pad, GstObject * parent,
GstEvent * event);
+static void gst_wavparse_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_wavparse_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+#define DEFAULT_IGNORE_LENGTH FALSE
+
+enum
+{
+ PROP_0,
+ PROP_IGNORE_LENGTH,
+};
+
static GstStaticPadTemplate sink_template_factory =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
@@ -113,6 +131,27 @@ gst_wavparse_class_init (GstWavParseClass * klass)
object_class->dispose = gst_wavparse_dispose;
+ object_class->set_property = gst_wavparse_set_property;
+ object_class->get_property = gst_wavparse_get_property;
+
+ /**
+ * GstWavParse:ignore-length
+ *
+ * This selects whether the length found in a data chunk
+ * should be ignored. This may be useful for streamed audio
+ * where the length is unknown until the end of streaming,
+ * and various software/hardware just puts some random value
+ * in there and hopes it doesn't break too much.
+ *
+ * Since: 0.10.36
+ */
+ g_object_class_install_property (object_class, PROP_IGNORE_LENGTH,
+ g_param_spec_boolean ("ignore-length",
+ "Ignore length",
+ "Ignore length from the Wave header",
+ DEFAULT_IGNORE_LENGTH, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
+ );
+
gstelement_class->change_state = gst_wavparse_change_state;
gstelement_class->send_event = gst_wavparse_send_event;
@@ -212,37 +251,6 @@ gst_wavparse_init (GstWavParse * wavparse)
gst_element_add_pad (GST_ELEMENT_CAST (wavparse), wavparse->srcpad);
}
-/* Compute (value * nom) % denom, avoiding overflow. This can be used
- * to perform ceiling or rounding division together with
- * gst_util_uint64_scale[_int]. */
-#define uint64_scale_modulo(val, nom, denom) \
- ((val % denom) * (nom % denom) % denom)
-
-/* Like gst_util_uint64_scale, but performs ceiling division. */
-static guint64
-uint64_ceiling_scale_int (guint64 val, gint num, gint denom)
-{
- guint64 result = gst_util_uint64_scale_int (val, num, denom);
-
- if (uint64_scale_modulo (val, num, denom) == 0)
- return result;
- else
- return result + 1;
-}
-
-/* Like gst_util_uint64_scale, but performs ceiling division. */
-static guint64
-uint64_ceiling_scale (guint64 val, guint64 num, guint64 denom)
-{
- guint64 result = gst_util_uint64_scale (val, num, denom);
-
- if (uint64_scale_modulo (val, num, denom) == 0)
- return result;
- else
- return result + 1;
-}
-
-
/* FIXME: why is that not in use? */
#if 0
static void
@@ -531,7 +539,7 @@ gst_wavparse_fmt (GstWavParse * wav)
gst_element_add_pad (GST_ELEMENT_CAST (wav), wav->srcpad);
gst_element_no_more_pads (GST_ELEMENT_CAST (wav));
- GST_DEBUG ("frequency %d, channels %d", wav->rate, wav->channels);
+ GST_DEBUG ("frequency %u, channels %u", wav->rate, wav->channels);
return TRUE;
@@ -572,8 +580,8 @@ gst_wavparse_other (GstWavParse * wav)
GST_WARNING_OBJECT (wav, "could not peek head");
return FALSE;
}
- GST_DEBUG_OBJECT (wav, "got tag (%08x) %4.4s, length %d", tag,
- (gchar *) & tag, length);
+ GST_DEBUG_OBJECT (wav, "got tag (%08x) %4.4s, length %u", tag,
+ (const gchar *) &tag, length);
switch (tag) {
case GST_RIFF_TAG_LIST:
@@ -724,12 +732,12 @@ gst_wavparse_time_to_bytepos (GstWavParse * wav, gint64 ts, gint64 * bytepos)
}
if (wav->bps > 0) {
- *bytepos = uint64_ceiling_scale (ts, (guint64) wav->bps, GST_SECOND);
+ *bytepos = gst_util_uint64_scale_ceil (ts, (guint64) wav->bps, GST_SECOND);
return TRUE;
} else if (wav->fact) {
guint64 bps =
gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact);
- *bytepos = uint64_ceiling_scale (ts, bps, GST_SECOND);
+ *bytepos = gst_util_uint64_scale_ceil (ts, bps, GST_SECOND);
return TRUE;
}
@@ -1008,7 +1016,7 @@ gst_wavparse_peek_chunk_info (GstWavParse * wav, guint32 * tag, guint32 * size)
*size = GST_READ_UINT32_LE (data + 4);
gst_adapter_unmap (wav->adapter);
- GST_DEBUG ("Next chunk size is %d bytes, type %" GST_FOURCC_FORMAT, *size,
+ GST_DEBUG ("Next chunk size is %u bytes, type %" GST_FOURCC_FORMAT, *size,
GST_FOURCC_ARGS (*tag));
return TRUE;
@@ -1038,7 +1046,7 @@ gst_wavparse_peek_chunk (GstWavParse * wav, guint32 * tag, guint32 * size)
* so we throw poor man's exception, which can be caught if caller really
* wants to handle 0 size chunk */
if (!(*size) || (*size) >= (1 << 30)) {
- GST_INFO ("Invalid/unexpected chunk size %d for tag %" GST_FOURCC_FORMAT,
+ GST_INFO ("Invalid/unexpected chunk size %u for tag %" GST_FOURCC_FORMAT,
*size, GST_FOURCC_ARGS (*tag));
/* chain should give up */
wav->abort_buffering = TRUE;
@@ -1073,12 +1081,14 @@ gst_wavparse_calculate_duration (GstWavParse * wav)
if (wav->bps > 0) {
GST_INFO_OBJECT (wav, "Got datasize %" G_GUINT64_FORMAT, wav->datasize);
wav->duration =
- uint64_ceiling_scale (wav->datasize, GST_SECOND, (guint64) wav->bps);
+ gst_util_uint64_scale_ceil (wav->datasize, GST_SECOND,
+ (guint64) wav->bps);
GST_INFO_OBJECT (wav, "Got duration (bps) %" GST_TIME_FORMAT,
GST_TIME_ARGS (wav->duration));
return TRUE;
} else if (wav->fact) {
- wav->duration = uint64_ceiling_scale_int (GST_SECOND, wav->fact, wav->rate);
+ wav->duration =
+ gst_util_uint64_scale_int_ceil (GST_SECOND, wav->fact, wav->rate);
GST_INFO_OBJECT (wav, "Got duration (fact) %" GST_TIME_FORMAT,
GST_TIME_ARGS (wav->duration));
return TRUE;
@@ -1211,12 +1221,12 @@ gst_wavparse_stream_headers (GstWavParse * wav)
{
/* Note: workaround for mp2/mp3 embedded in wav, that relies on the
* bitrate inside the mpeg stream */
- GST_INFO ("resetting bps from %d to 0 for mp2/3", wav->av_bps);
+ GST_INFO ("resetting bps from %u to 0 for mp2/3", wav->av_bps);
wav->bps = 0;
break;
}
case GST_RIFF_WAVE_FORMAT_PCM:
- if (wav->blockalign > wav->channels * (guint) ceil (wav->depth / 8.0))
+ if (wav->blockalign > wav->channels * ((wav->depth + 7) / 8))
goto invalid_blockalign;
/* fall through */
default:
@@ -1298,7 +1308,11 @@ gst_wavparse_stream_headers (GstWavParse * wav)
*/
switch (tag) {
case GST_RIFF_TAG_data:{
- GST_DEBUG_OBJECT (wav, "Got 'data' TAG, size : %d", size);
+ GST_DEBUG_OBJECT (wav, "Got 'data' TAG, size : %u", size);
+ if (wav->ignore_length) {
+ GST_DEBUG_OBJECT (wav, "Ignoring length");
+ size = 0;
+ }
if (wav->streaming) {
gst_adapter_flush (wav->adapter, 8);
gotdata = TRUE;
@@ -1323,7 +1337,7 @@ gst_wavparse_stream_headers (GstWavParse * wav)
/* We will continue parsing tags 'till end */
wav->offset += size;
}
- GST_DEBUG_OBJECT (wav, "datasize = %d", size);
+ GST_DEBUG_OBJECT (wav, "datasize = %u", size);
break;
}
case GST_RIFF_TAG_fact:{
@@ -1337,7 +1351,7 @@ gst_wavparse_stream_headers (GstWavParse * wav)
/* need more data */
goto exit;
}
- GST_DEBUG_OBJECT (wav, "need %d, available %d; ignoring chunk",
+ GST_DEBUG_OBJECT (wav, "need %u, available %u; ignoring chunk",
data_size, size);
break;
}
@@ -1385,7 +1399,7 @@ gst_wavparse_stream_headers (GstWavParse * wav)
/* need more data */
goto exit;
}
- GST_DEBUG_OBJECT (wav, "need %d, available %d; ignoring chunk",
+ GST_DEBUG_OBJECT (wav, "need %u, available %u; ignoring chunk",
data_size, size);
break;
}
@@ -1520,18 +1534,20 @@ gst_wavparse_stream_headers (GstWavParse * wav)
wav->bps =
(guint32) gst_util_uint64_scale ((guint64) wav->rate, wav->datasize,
(guint64) wav->fact);
- GST_INFO_OBJECT (wav, "calculated bps : %d, enabling VBR", wav->bps);
+ GST_INFO_OBJECT (wav, "calculated bps : %u, enabling VBR", wav->bps);
#endif
wav->vbr = TRUE;
}
if (gst_wavparse_calculate_duration (wav)) {
gst_segment_init (&wav->segment, GST_FORMAT_TIME);
- wav->segment.duration = wav->duration;
+ if (!wav->ignore_length)
+ wav->segment.duration = wav->duration;
} else {
/* no bitrate, let downstream peer do the math, we'll feed it bytes. */
gst_segment_init (&wav->segment, GST_FORMAT_BYTES);
- wav->segment.duration = wav->datasize;
+ if (!wav->ignore_length)
+ wav->segment.duration = wav->datasize;
}
/* now we have all the info to perform a pending seek if any, if no
@@ -1558,7 +1574,7 @@ gst_wavparse_stream_headers (GstWavParse * wav)
if (wav->blockalign > 0)
wav->max_buf_size -= (wav->max_buf_size % wav->blockalign);
- GST_DEBUG_OBJECT (wav, "max buffer size %d", wav->max_buf_size);
+ GST_DEBUG_OBJECT (wav, "max buffer size %u", wav->max_buf_size);
return GST_FLOW_OK;
@@ -1607,7 +1623,7 @@ invalid_blockalign:
{
GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
("Stream claims blockalign = %u, which is more than %u - invalid data",
- wav->blockalign, wav->channels * (guint) ceil (wav->depth / 8.0)));
+ wav->blockalign, wav->channels * ((wav->depth + 7) / 8)));
goto fail;
}
invalid_bps:
@@ -1626,7 +1642,7 @@ no_bytes_per_sample:
unknown_format:
{
GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL),
- ("No caps found for format 0x%x, %d channels, %d Hz",
+ ("No caps found for format 0x%x, %u channels, %u Hz",
wav->format, wav->channels, wav->rate));
goto fail;
}
@@ -1818,13 +1834,13 @@ iterate_adapter:
if (G_UNLIKELY (extra)) {
extra = wav->bytes_per_sample - extra;
if (extra <= avail) {
- GST_DEBUG_OBJECT (wav, "flushing %d bytes to sample boundary", extra);
+ GST_DEBUG_OBJECT (wav, "flushing %u bytes to sample boundary", extra);
gst_adapter_flush (wav->adapter, extra);
wav->offset += extra;
wav->dataleft -= extra;
goto iterate_adapter;
} else {
- GST_DEBUG_OBJECT (wav, "flushing %d bytes", avail);
+ GST_DEBUG_OBJECT (wav, "flushing %u bytes", avail);
gst_adapter_clear (wav->adapter);
wav->offset += avail;
wav->dataleft -= avail;
@@ -1833,7 +1849,7 @@ iterate_adapter:
}
if (avail < desired) {
- GST_LOG_OBJECT (wav, "Got only %d bytes of data from the sinkpad", avail);
+ GST_LOG_OBJECT (wav, "Got only %u bytes of data from the sinkpad", avail);
return GST_FLOW_OK;
}
@@ -1885,9 +1901,10 @@ iterate_adapter:
if (wav->bps > 0) {
/* and timestamps if we have a bitrate, be careful for overflows */
- timestamp = uint64_ceiling_scale (pos, GST_SECOND, (guint64) wav->bps);
+ timestamp =
+ gst_util_uint64_scale_ceil (pos, GST_SECOND, (guint64) wav->bps);
next_timestamp =
- uint64_ceiling_scale (nextpos, GST_SECOND, (guint64) wav->bps);
+ gst_util_uint64_scale_ceil (nextpos, GST_SECOND, (guint64) wav->bps);
duration = next_timestamp - timestamp;
/* update current running segment position */
@@ -1897,8 +1914,8 @@ iterate_adapter:
guint64 bps =
gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact);
/* and timestamps if we have a bitrate, be careful for overflows */
- timestamp = uint64_ceiling_scale (pos, GST_SECOND, bps);
- next_timestamp = uint64_ceiling_scale (nextpos, GST_SECOND, bps);
+ timestamp = gst_util_uint64_scale_ceil (pos, GST_SECOND, bps);
+ next_timestamp = gst_util_uint64_scale_ceil (nextpos, GST_SECOND, bps);
duration = next_timestamp - timestamp;
} else {
/* no bitrate, all we know is that the first sample has timestamp 0, all
@@ -2191,10 +2208,12 @@ gst_wavparse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
if (bps) {
if (start >= 0)
start =
- uint64_ceiling_scale (start, GST_SECOND, (guint64) wav->bps);
+ gst_util_uint64_scale_ceil (start, GST_SECOND,
+ (guint64) wav->bps);
if (stop >= 0)
stop =
- uint64_ceiling_scale (stop, GST_SECOND, (guint64) wav->bps);
+ gst_util_uint64_scale_ceil (stop, GST_SECOND,
+ (guint64) wav->bps);
}
}
} else {
@@ -2319,13 +2338,14 @@ gst_wavparse_pad_convert (GstPad * pad,
"src=%" G_GINT64_FORMAT ", offset=%" G_GINT64_FORMAT, src_value,
wavparse->offset);
if (wavparse->bps > 0)
- *dest_value = uint64_ceiling_scale (src_value, GST_SECOND,
+ *dest_value = gst_util_uint64_scale_ceil (src_value, GST_SECOND,
(guint64) wavparse->bps);
else if (wavparse->fact) {
- guint64 bps = uint64_ceiling_scale_int (wavparse->datasize,
+ guint64 bps = gst_util_uint64_scale_int_ceil (wavparse->datasize,
wavparse->rate, wavparse->fact);
- *dest_value = uint64_ceiling_scale_int (src_value, GST_SECOND, bps);
+ *dest_value =
+ gst_util_uint64_scale_int_ceil (src_value, GST_SECOND, bps);
} else {
res = FALSE;
}
@@ -2438,6 +2458,11 @@ gst_wavparse_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
gint64 duration = 0;
GstFormat format;
+ if (wav->ignore_length) {
+ res = FALSE;
+ break;
+ }
+
gst_query_parse_duration (query, &format, NULL);
switch (format) {
@@ -2626,6 +2651,43 @@ gst_wavparse_change_state (GstElement * element, GstStateChange transition)
return ret;
}
+static void
+gst_wavparse_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstWavParse *self;
+
+ g_return_if_fail (GST_IS_WAVPARSE (object));
+ self = GST_WAVPARSE (object);
+
+ switch (prop_id) {
+ case PROP_IGNORE_LENGTH:
+ self->ignore_length = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
+ }
+
+}
+
+static void
+gst_wavparse_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstWavParse *self;
+
+ g_return_if_fail (GST_IS_WAVPARSE (object));
+ self = GST_WAVPARSE (object);
+
+ switch (prop_id) {
+ case PROP_IGNORE_LENGTH:
+ g_value_set_boolean (value, self->ignore_length);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
+ }
+}
+
static gboolean
plugin_init (GstPlugin * plugin)
{
diff --git a/gst/wavparse/gstwavparse.h b/gst/wavparse/gstwavparse.h
index 54d0a0fd5..82838e4cb 100644
--- a/gst/wavparse/gstwavparse.h
+++ b/gst/wavparse/gstwavparse.h
@@ -116,6 +116,8 @@ struct _GstWavParse {
gboolean first;
/* discont after seek */
gboolean discont;
+
+ gboolean ignore_length;
};
struct _GstWavParseClass {
diff --git a/po/LINGUAS b/po/LINGUAS
index 44f55d97e..73d8b85b2 100644
--- a/po/LINGUAS
+++ b/po/LINGUAS
@@ -1 +1 @@
-af az bg ca cs da de el en_GB es eu fi fr gl hu id it ja lt lv mt nb nl or pl pt_BR ro ru sk sl sq sr sv tr uk vi zh_CN zh_HK zh_TW
+af az bg ca cs da de el en_GB eo es eu fi fr gl hu id it ja lt lv mt nb nl or pl pt_BR ro ru sk sl sq sr sv tr uk vi zh_CN zh_HK zh_TW
diff --git a/po/eo.po b/po/eo.po
new file mode 100644
index 000000000..73f84a393
--- /dev/null
+++ b/po/eo.po
@@ -0,0 +1,832 @@
+# Esperanto translation for gst-plugins-good.
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# This file is distributed under the same license as the gst-plugins-good package.
+# Kristjan SCHMIDT <kristjan.schmidt@googlemail.com>, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gst-plugins-good 0.10.28.2\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
+"POT-Creation-Date: 2011-04-16 16:25+0100\n"
+"PO-Revision-Date: 2011-06-04 21:48+0100\n"
+"Last-Translator: Kristjan SCHMIDT <kristjan.schmidt@googlemail.com>\n"
+"Language-Team: Esperanto <translation-team-eo@lists.sourceforge.net>\n"
+"Language: eo\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ext/esd/esdsink.c:253 ext/esd/esdsink.c:358
+msgid "Could not establish connection to sound server"
+msgstr ""
+
+#: ext/esd/esdsink.c:260
+msgid "Failed to query sound server capabilities"
+msgstr ""
+
+#. TRANSLATORS: 'song title' by 'artist name'
+#: ext/pulse/pulsesink.c:2686
+#, c-format
+msgid "'%s' by '%s'"
+msgstr "'%s' de '%s'"
+
+#: ext/flac/gstflacdec.c:1117 ext/libpng/gstpngdec.c:349
+#: ext/libpng/gstpngdec.c:360 ext/libpng/gstpngdec.c:559
+#: ext/wavpack/gstwavpackparse.c:1170 gst/avi/gstavidemux.c:5203
+msgid "Internal data stream error."
+msgstr "Interna datumflu-eraro."
+
+#: ext/jpeg/gstjpegdec.c:286
+msgid "Failed to decode JPEG image"
+msgstr ""
+
+#: ext/shout2/gstshout2.c:578
+msgid "Could not connect to server"
+msgstr "Ne eblis konekti al servilo"
+
+#: ext/soup/gstsouphttpsrc.c:871
+msgid "Server does not support seeking."
+msgstr ""
+
+#: ext/soup/gstsouphttpsrc.c:1078
+msgid "Could not resolve server name."
+msgstr ""
+
+#: ext/soup/gstsouphttpsrc.c:1084
+msgid "Could not establish connection to server."
+msgstr ""
+
+#: ext/soup/gstsouphttpsrc.c:1089
+msgid "Secure connection setup failed."
+msgstr ""
+
+#: ext/soup/gstsouphttpsrc.c:1094
+msgid "A network error occured, or the server closed the connection unexpectedly."
+msgstr ""
+
+#: ext/soup/gstsouphttpsrc.c:1100
+msgid "Server sent bad data."
+msgstr ""
+
+#: ext/soup/gstsouphttpsrc.c:1249
+msgid "No URL set."
+msgstr ""
+
+#: gst/avi/gstavimux.c:1810
+msgid "No or invalid input audio, AVI stream will be corrupt."
+msgstr ""
+
+#: gst/quicktime/qtdemux.c:519 gst/quicktime/qtdemux.c:523
+msgid "This file contains no playable streams."
+msgstr ""
+
+#: gst/quicktime/qtdemux.c:558 gst/quicktime/qtdemux.c:4009
+#: gst/quicktime/qtdemux.c:4071 gst/quicktime/qtdemux.c:4219
+msgid "This file is invalid and cannot be played."
+msgstr ""
+
+#: gst/quicktime/qtdemux.c:2439 gst/quicktime/qtdemux.c:2515
+#: gst/quicktime/qtdemux.c:2558 gst/quicktime/qtdemux.c:4798
+#: gst/quicktime/qtdemux.c:4805 gst/quicktime/qtdemux.c:5391
+#: gst/quicktime/qtdemux.c:5817 gst/quicktime/qtdemux.c:5824
+#: gst/quicktime/qtdemux.c:7305
+msgid "This file is corrupt and cannot be played."
+msgstr ""
+
+#: gst/quicktime/qtdemux.c:2647
+msgid "Invalid atom size."
+msgstr ""
+
+#: gst/quicktime/qtdemux.c:2716
+msgid "This file is incomplete and cannot be played."
+msgstr ""
+
+#: gst/quicktime/qtdemux.c:4994
+msgid "The video in this file might not play correctly."
+msgstr ""
+
+#: gst/quicktime/qtdemux.c:7334
+#, c-format
+msgid "This file contains too many streams. Only playing first %d"
+msgstr ""
+
+#: gst/rtsp/gstrtspsrc.c:5187
+msgid "No supported stream was found. You might need to install a GStreamer RTSP extension plugin for Real media streams."
+msgstr ""
+
+#: gst/rtsp/gstrtspsrc.c:5192
+msgid "No supported stream was found. You might need to allow more transport protocols or may otherwise be missing the right GStreamer RTSP extension plugin."
+msgstr ""
+
+#: gst/wavparse/gstwavparse.c:2103
+msgid "Internal data flow error."
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:98 sys/oss4/oss4-mixer.c:722
+#: sys/sunaudio/gstsunaudiomixertrack.c:69
+msgid "Volume"
+msgstr "Laŭteco"
+
+#: sys/oss/gstossmixertrack.c:99 sys/oss4/oss4-mixer.c:735
+msgid "Bass"
+msgstr "Baso"
+
+#: sys/oss/gstossmixertrack.c:100 sys/oss4/oss4-mixer.c:736
+msgid "Treble"
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:101
+msgid "Synth"
+msgstr "Sintezilo"
+
+#: sys/oss/gstossmixertrack.c:102 sys/oss4/oss4-mixer.c:750
+msgid "PCM"
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:103
+msgid "Speaker"
+msgstr "Parolilo"
+
+#: sys/oss/gstossmixertrack.c:104
+msgid "Line-in"
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:105 sys/oss4/oss4-mixer.c:741
+msgid "Microphone"
+msgstr "Mikrofono"
+
+#: sys/oss/gstossmixertrack.c:106
+msgid "CD"
+msgstr "KD"
+
+#: sys/oss/gstossmixertrack.c:107
+msgid "Mixer"
+msgstr "Miksilo"
+
+#: sys/oss/gstossmixertrack.c:108
+msgid "PCM-2"
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:109
+msgid "Record"
+msgstr "Registri"
+
+#: sys/oss/gstossmixertrack.c:110
+msgid "In-gain"
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:111
+msgid "Out-gain"
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:112
+msgid "Line-1"
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:113
+msgid "Line-2"
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:114
+msgid "Line-3"
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:115
+msgid "Digital-1"
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:116
+msgid "Digital-2"
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:117
+msgid "Digital-3"
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:118
+msgid "Phone-in"
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:119
+msgid "Phone-out"
+msgstr ""
+
+#: sys/oss/gstossmixertrack.c:120
+msgid "Video"
+msgstr "Video"
+
+#: sys/oss/gstossmixertrack.c:121
+msgid "Radio"
+msgstr "Radio"
+
+#: sys/oss/gstossmixertrack.c:122 sys/oss4/oss4-mixer.c:764
+#: sys/sunaudio/gstsunaudiomixertrack.c:71
+msgid "Monitor"
+msgstr "Ekrano"
+
+#: sys/oss/gstosssink.c:399 sys/oss4/oss4-sink.c:494
+#: sys/oss4/oss4-source.c:361
+msgid "Could not open audio device for playback. Device is being used by another application."
+msgstr "Ne eblis malfermi la sonaparaton por reproduktado. Ĝi estas uzate de alia aplikaĵo."
+
+#: sys/oss/gstosssink.c:406 sys/oss4/oss4-sink.c:504
+#: sys/oss4/oss4-source.c:371
+msgid "Could not open audio device for playback. You don't have permission to open the device."
+msgstr ""
+
+#: sys/oss/gstosssink.c:414 sys/oss4/oss4-sink.c:515
+#: sys/oss4/oss4-source.c:382
+msgid "Could not open audio device for playback."
+msgstr "Ne eblis malfermi la sonaparaton por reproduktado."
+
+#: sys/oss/gstosssrc.c:370
+msgid "Could not open audio device for recording. You don't have permission to open the device."
+msgstr ""
+
+#: sys/oss/gstosssrc.c:378
+msgid "Could not open audio device for recording."
+msgstr "Ne eblis malfermi sonaparaton por registrado."
+
+#: sys/oss4/oss4-mixer.c:302
+msgid "Could not open audio device for mixer control handling."
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:316
+msgid "Could not open audio device for mixer control handling. This version of the Open Sound System is not supported by this element."
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:723
+msgid "Master"
+msgstr "Ĉefe"
+
+#: sys/oss4/oss4-mixer.c:724
+msgid "Front"
+msgstr "Antaŭe"
+
+#: sys/oss4/oss4-mixer.c:725
+msgid "Rear"
+msgstr "Malantaŭe"
+
+#: sys/oss4/oss4-mixer.c:726
+msgid "Headphones"
+msgstr "Kaptelefono"
+
+#: sys/oss4/oss4-mixer.c:727
+msgid "Center"
+msgstr "Centre"
+
+#: sys/oss4/oss4-mixer.c:728
+msgid "LFE"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:729
+msgid "Surround"
+msgstr "Ĉirkaŭe"
+
+#: sys/oss4/oss4-mixer.c:730
+msgid "Side"
+msgstr "Flanke"
+
+#: sys/oss4/oss4-mixer.c:731 sys/sunaudio/gstsunaudiomixertrack.c:72
+msgid "Built-in Speaker"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:732 sys/sunaudio/gstsunaudiomixertrack.c:76
+msgid "AUX 1 Out"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:733 sys/sunaudio/gstsunaudiomixertrack.c:77
+msgid "AUX 2 Out"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:734
+msgid "AUX Out"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:737
+msgid "3D Depth"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:738
+msgid "3D Center"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:739
+msgid "3D Enhance"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:740
+msgid "Telephone"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:742 sys/sunaudio/gstsunaudiomixertrack.c:74
+msgid "Line Out"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:743 sys/oss4/oss4-mixer.c:744
+msgid "Line In"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:745
+msgid "Internal CD"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:746
+msgid "Video In"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:747
+msgid "AUX 1 In"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:748
+msgid "AUX 2 In"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:749
+msgid "AUX In"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:751 sys/oss4/oss4-mixer.c:752
+msgid "Record Gain"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:753
+msgid "Output Gain"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:754
+msgid "Microphone Boost"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:755
+msgid "Loopback"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:756
+msgid "Diagnostic"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:757
+msgid "Bass Boost"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:758
+msgid "Playback Ports"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:759
+msgid "Input"
+msgstr "Enigo"
+
+#: sys/oss4/oss4-mixer.c:760 sys/oss4/oss4-mixer.c:761
+msgid "Record Source"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:762
+msgid "Monitor Source"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:763
+msgid "Keyboard Beep"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:765
+msgid "Simulate Stereo"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:766 sys/oss4/oss4-mixer.c:786
+msgid "Stereo"
+msgstr "Dukanale"
+
+#: sys/oss4/oss4-mixer.c:767
+msgid "Surround Sound"
+msgstr "Ĉirkaŭa sono"
+
+#: sys/oss4/oss4-mixer.c:768
+msgid "Microphone Gain"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:769
+msgid "Speaker Source"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:770
+msgid "Microphone Source"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:771
+msgid "Jack"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:772
+msgid "Center / LFE"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:773
+msgid "Stereo Mix"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:774
+msgid "Mono Mix"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:775
+msgid "Input Mix"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:776
+msgid "SPDIF In"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:777 sys/sunaudio/gstsunaudiomixertrack.c:75
+msgid "SPDIF Out"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:778
+msgid "Microphone 1"
+msgstr "Mikrofono 1"
+
+#: sys/oss4/oss4-mixer.c:779
+msgid "Microphone 2"
+msgstr "Mikrofono 2"
+
+#: sys/oss4/oss4-mixer.c:780
+msgid "Digital Out"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:781
+msgid "Digital In"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:782
+msgid "HDMI"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:783
+msgid "Modem"
+msgstr "Modemo"
+
+#: sys/oss4/oss4-mixer.c:784
+msgid "Handset"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:785
+msgid "Other"
+msgstr "Alia"
+
+#: sys/oss4/oss4-mixer.c:787
+msgid "None"
+msgstr "Neniu"
+
+#: sys/oss4/oss4-mixer.c:788
+msgid "On"
+msgstr "Enŝaltite"
+
+#: sys/oss4/oss4-mixer.c:789
+msgid "Off"
+msgstr "Elŝaltite"
+
+#: sys/oss4/oss4-mixer.c:790
+msgid "Mute"
+msgstr "Silentigi"
+
+#: sys/oss4/oss4-mixer.c:791
+msgid "Fast"
+msgstr "Rapide"
+
+#. TRANSLATORS: "Very Low" is a quality setting here
+#: sys/oss4/oss4-mixer.c:793
+msgid "Very Low"
+msgstr "Tre malalte"
+
+#. TRANSLATORS: "Low" is a quality setting here
+#: sys/oss4/oss4-mixer.c:795
+msgid "Low"
+msgstr "Malalte"
+
+#. TRANSLATORS: "Medium" is a quality setting here
+#: sys/oss4/oss4-mixer.c:797
+msgid "Medium"
+msgstr "Meze"
+
+#. TRANSLATORS: "High" is a quality setting here
+#: sys/oss4/oss4-mixer.c:799
+msgid "High"
+msgstr "Alte"
+
+#. TRANSLATORS: "Very High" is a quality setting here
+#: sys/oss4/oss4-mixer.c:801 sys/oss4/oss4-mixer.c:802
+msgid "Very High"
+msgstr "Tre alte"
+
+#. TRANSLATORS: "Production" is a quality setting here
+#: sys/oss4/oss4-mixer.c:804
+msgid "Production"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:805
+msgid "Front Panel Microphone"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:806
+msgid "Front Panel Line In"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:807
+msgid "Front Panel Headphones"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:808
+msgid "Front Panel Line Out"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:809
+msgid "Green Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:810
+msgid "Pink Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:811
+msgid "Blue Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:812
+msgid "White Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:813
+msgid "Black Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:814
+msgid "Gray Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:815
+msgid "Orange Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:816
+msgid "Red Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:817
+msgid "Yellow Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:818
+msgid "Green Front Panel Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:819
+msgid "Pink Front Panel Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:820
+msgid "Blue Front Panel Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:821
+msgid "White Front Panel Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:822
+msgid "Black Front Panel Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:823
+msgid "Gray Front Panel Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:824
+msgid "Orange Front Panel Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:825
+msgid "Red Front Panel Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:826
+msgid "Yellow Front Panel Connector"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:827
+msgid "Spread Output"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:828
+msgid "Downmix"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:872
+msgid "Virtual Mixer Input"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:874
+msgid "Virtual Mixer Output"
+msgstr ""
+
+#: sys/oss4/oss4-mixer.c:876
+msgid "Virtual Mixer Channels"
+msgstr ""
+
+#. TRANSLATORS: name + number of a volume mixer control
+#: sys/oss4/oss4-mixer.c:927
+#, c-format
+msgid "%s %d Function"
+msgstr "%s %d funkcio"
+
+#. TRANSLATORS: name of a volume mixer control
+#: sys/oss4/oss4-mixer.c:934
+#, c-format
+msgid "%s Function"
+msgstr "%s funcio"
+
+#: sys/oss4/oss4-sink.c:524 sys/oss4/oss4-source.c:392
+msgid "Could not open audio device for playback. This version of the Open Sound System is not supported by this element."
+msgstr ""
+
+#: sys/oss4/oss4-sink.c:640
+msgid "Playback is not supported by this audio device."
+msgstr ""
+
+#: sys/oss4/oss4-sink.c:647
+msgid "Audio playback error."
+msgstr ""
+
+#: sys/oss4/oss4-source.c:514
+msgid "Recording is not supported by this audio device."
+msgstr ""
+
+#: sys/oss4/oss4-source.c:521
+msgid "Error recording from audio device."
+msgstr ""
+
+#: sys/sunaudio/gstsunaudiomixertrack.c:70
+msgid "Gain"
+msgstr ""
+
+#: sys/sunaudio/gstsunaudiomixertrack.c:73
+msgid "Headphone"
+msgstr ""
+
+#: sys/v4l2/gstv4l2src.c:887
+#, c-format
+msgid "Error reading %d bytes from device '%s'."
+msgstr ""
+
+#: sys/v4l2/gstv4l2src.c:913
+#, c-format
+msgid "Got unexpected frame size of %u instead of %u."
+msgstr ""
+
+#: sys/v4l2/gstv4l2src.c:931
+#, c-format
+msgid "Error reading %d bytes on device '%s'."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:99
+#, c-format
+msgid "Error getting capabilities for device '%s': It isn't a v4l2 driver. Check if it is a v4l1 driver."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:139
+#, c-format
+msgid "Failed to query attributes of input %d in device %s"
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:169
+#, c-format
+msgid "Failed to get setting of tuner %d on device '%s'."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:213
+#, c-format
+msgid "Failed to query norm on device '%s'."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:264 sys/v4l2/v4l2_calls.c:347
+#, c-format
+msgid "Failed getting controls attributes on device '%s'."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:492
+#, c-format
+msgid "Cannot identify device '%s'."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:499
+#, c-format
+msgid "This isn't a device '%s'."
+msgstr "Tio ne estas '%s'-aparato."
+
+#: sys/v4l2/v4l2_calls.c:506
+#, c-format
+msgid "Could not open device '%s' for reading and writing."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:513
+#, c-format
+msgid "Device '%s' is not a capture device."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:522
+#, c-format
+msgid "Device '%s' is not a output device."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:622
+#, c-format
+msgid "Failed to set norm for device '%s'."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:660
+#, c-format
+msgid "Failed to get current tuner frequency for device '%s'."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:702
+#, c-format
+msgid "Failed to set current tuner frequency for device '%s' to %lu Hz."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:736
+#, c-format
+msgid "Failed to get signal strength for device '%s'."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:772
+#, c-format
+msgid "Failed to get value for control %d on device '%s'."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:807
+#, c-format
+msgid "Failed to set value %d for control %d on device '%s'."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:839
+#, c-format
+msgid "Failed to get current input on device '%s'. May be it is a radio device"
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:864
+#, c-format
+msgid "Failed to set input %d on device %s."
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:896
+#, c-format
+msgid "Failed to get current output on device '%s'. May be it is a radio device"
+msgstr ""
+
+#: sys/v4l2/v4l2_calls.c:921
+#, c-format
+msgid "Failed to set output %d on device %s."
+msgstr ""
+
+#: sys/v4l2/v4l2src_calls.c:81
+#, c-format
+msgid "Could not enqueue buffers in device '%s'."
+msgstr ""
+
+#: sys/v4l2/v4l2src_calls.c:197
+#, c-format
+msgid "Failed trying to get video frames from device '%s'."
+msgstr ""
+
+#: sys/v4l2/v4l2src_calls.c:199
+#, c-format
+msgid "Failed after %d tries. device %s. system error: %s"
+msgstr ""
+
+#: sys/v4l2/v4l2src_calls.c:239
+#, c-format
+msgid "Could not get parameters on device '%s'"
+msgstr ""
+
+#: sys/v4l2/v4l2src_calls.c:267
+msgid "Video input device did not accept new frame rate setting."
+msgstr ""
+
+#: sys/v4l2/v4l2src_calls.c:339
+#, c-format
+msgid "Could not map buffers from device '%s'"
+msgstr ""
+
+#: sys/v4l2/v4l2src_calls.c:347
+#, c-format
+msgid "The driver of device '%s' does not support any known capture method."
+msgstr ""
+
+#: sys/ximage/gstximagesrc.c:719
+msgid "Changing resolution at runtime is not yet supported."
+msgstr ""
+
+#: sys/ximage/gstximagesrc.c:733
+msgid "Cannot operate without a clock"
+msgstr ""
diff --git a/sys/Makefile.am b/sys/Makefile.am
index ab08d046d..7ccd9e77a 100644
--- a/sys/Makefile.am
+++ b/sys/Makefile.am
@@ -23,6 +23,12 @@ else
DIRECTSOUND_DIR=
endif
+if USE_WAVEFORM
+WAVEFORM_DIR=waveform
+else
+WAVEFORM_DIR=
+endif
+
if USE_SUNAUDIO
SUNAUDIO_DIR=sunaudio
else
@@ -77,7 +83,7 @@ else
XIMAGE_DIR=
endif
-SUBDIRS=$(DIRECTSOUND_DIR) $(OSS_DIR) $(OSS4_DIR) $(OSX_AUDIO_DIR) $(OSX_VIDEO_DIR) $(SUNAUDIO_DIR) $(V4L2_DIR) $(XIMAGE_DIR)
+SUBDIRS=$(DIRECTSOUND_DIR) $(WAVEFORM_DIR) $(OSS_DIR) $(OSS4_DIR) $(OSX_AUDIO_DIR) $(OSX_VIDEO_DIR) $(SUNAUDIO_DIR) $(V4L2_DIR) $(XIMAGE_DIR)
DIST_SUBDIRS=directsound oss oss4 osxaudio osxvideo sunaudio v4l2 waveform ximage
diff --git a/sys/oss4/oss4-mixer.c b/sys/oss4/oss4-mixer.c
index e190987d6..e384452ec 100644
--- a/sys/oss4/oss4-mixer.c
+++ b/sys/oss4/oss4-mixer.c
@@ -54,6 +54,7 @@
#include <gst/interfaces/mixer.h>
#include <gst/gst-i18n-plugin.h>
+#include "gst/glib-compat-private.h"
#include <glib/gprintf.h>
@@ -541,8 +542,13 @@ gst_oss4_mixer_start_watch_task (GstOss4Mixer * mixer)
mixer->watch_cond = g_cond_new ();
mixer->watch_shutdown = FALSE;
+#if !GLIB_CHECK_VERSION (2, 31, 0)
mixer->watch_thread = g_thread_create (gst_oss4_mixer_watch_thread,
gst_object_ref (mixer), TRUE, &err);
+#else
+ mixer->watch_thread = g_thread_try_new ("oss4-mixer-thread",
+ gst_oss4_mixer_watch_thread, gst_object_ref (mixer), &err);
+#endif
if (mixer->watch_thread == NULL) {
GST_ERROR_OBJECT (mixer, "Could not create watch thread: %s", err->message);
diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 6b9074522..d25d7ae69 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -40,6 +40,7 @@
#include "gstv4l2sink.h"
#include "v4l2_calls.h"
#include "gst/gst-i18n-plugin.h"
+#include <gst/glib-compat-private.h>
/* videodev2.h is not versioned and we can't easily check for the presence
* of enum values at compile time, but the V4L2_CAP_VIDEO_OUTPUT_OVERLAY define
diff --git a/sys/v4l2/gstv4l2videooverlay.c b/sys/v4l2/gstv4l2videooverlay.c
index 3f28fdcd8..6ac15cdf4 100644
--- a/sys/v4l2/gstv4l2videooverlay.c
+++ b/sys/v4l2/gstv4l2videooverlay.c
@@ -39,6 +39,7 @@
#include "v4l2_calls.h"
#include "gst/gst-i18n-plugin.h"
+#include <gst/glib-compat-private.h>
struct _GstV4l2Xv
{
diff --git a/sys/waveform/Makefile.am b/sys/waveform/Makefile.am
index a9562a818..9a9fac3d7 100644
--- a/sys/waveform/Makefile.am
+++ b/sys/waveform/Makefile.am
@@ -1,19 +1,15 @@
plugin_LTLIBRARIES = libgstwaveformsink.la
-# FIXME: Replace DIRECTSOUND CFLAGS+LIBS with waveform related ones and fix
-# the configure.ac + sys/Makefile.am to get this stuff building in MingW
-# For now, it's just disted for use in the VS builds.
-
libgstwaveformsink_la_SOURCES = gstwaveformsink.c gstwaveformplugin.c
libgstwaveformsink_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \
- $(GST_PLUGINS_BASE_CFLAGS) $(DIRECTSOUND_CFLAGS)
+ $(GST_PLUGINS_BASE_CFLAGS)
libgstwaveformsink_la_LIBADD = \
$(GST_PLUGINS_BASE_LIBS) \
-lgstaudio-$(GST_MAJORMINOR) -lgstinterfaces-$(GST_MAJORMINOR) \
$(GST_BASE_LIBS) \
$(GST_LIBS) \
- $(DIRECTSOUND_LIBS)
-libgstwaveformsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(DIRECTSOUND_LDFLAGS)
+ -lwinmm
+libgstwaveformsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstwaveformsink_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstwaveformsink.h
diff --git a/sys/waveform/gstwaveformsink.c b/sys/waveform/gstwaveformsink.c
index 36542c182..e4b7016bb 100644
--- a/sys/waveform/gstwaveformsink.c
+++ b/sys/waveform/gstwaveformsink.c
@@ -49,10 +49,6 @@
GST_DEBUG_CATEGORY_STATIC (waveformsink_debug);
-static void gst_waveform_sink_base_init (gpointer g_class);
-static void gst_waveform_sink_class_init (GstWaveFormSinkClass * klass);
-static void gst_waveform_sink_init (GstWaveFormSink * wfsink,
- GstWaveFormSinkClass * g_class);
static void gst_waveform_sink_finalise (GObject * object);
static void gst_waveform_sink_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec);
@@ -154,7 +150,7 @@ static void
gst_waveform_sink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
- GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (object);
+ /* GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (object); */
switch (prop_id) {
default:
@@ -167,7 +163,7 @@ static void
gst_waveform_sink_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
- GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (object);
+ /* GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (object); */
switch (prop_id) {
default:
@@ -348,7 +344,7 @@ gst_waveform_sink_getcaps (GstBaseSink * bsink)
static gboolean
gst_waveform_sink_open (GstAudioSink * asink)
{
- GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink);
+ /* GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink); */
/* nothing to do here as the device needs to be opened with the format we will use */
@@ -448,7 +444,7 @@ gst_waveform_sink_unprepare (GstAudioSink * asink)
static gboolean
gst_waveform_sink_close (GstAudioSink * asink)
{
- GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink);
+ /* GstWaveFormSink *wfsink = GST_WAVEFORM_SINK (asink); */
return TRUE;
}
diff --git a/sys/ximage/gstximagesrc.c b/sys/ximage/gstximagesrc.c
index 91e3f1dbe..41559c5d5 100644
--- a/sys/ximage/gstximagesrc.c
+++ b/sys/ximage/gstximagesrc.c
@@ -49,6 +49,8 @@
#include <gst/gst.h>
#include <gst/gst-i18n-plugin.h>
+#include "gst/glib-compat-private.h"
+
GST_DEBUG_CATEGORY_STATIC (gst_debug_ximage_src);
#define GST_CAT_DEFAULT gst_debug_ximage_src
diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am
index 426e6196b..ec2bbb499 100644
--- a/tests/check/Makefile.am
+++ b/tests/check/Makefile.am
@@ -147,6 +147,7 @@ check_PROGRAMS = \
elements/shapewipe \
elements/spectrum \
elements/udpsink \
+ elements/udpsrc \
elements/videocrop \
elements/videofilter \
elements/y4menc \
@@ -296,6 +297,9 @@ elements_sunaudio_LDADD = \
$(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-@GST_MAJORMINOR@ \
$(LDADD)
+elements_udpsrc_CFLAGS = $(AM_CFLAGS) $(GIO_CFLAGS)
+elements_udpsrc_LDADD = $(LDADD) $(GIO_LIBS)
+
elements_videocrop_LDADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) $(LDADD)
elements_videocrop_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS)
diff --git a/tests/check/elements/.gitignore b/tests/check/elements/.gitignore
index c868fc81e..1e2c8b2e4 100644
--- a/tests/check/elements/.gitignore
+++ b/tests/check/elements/.gitignore
@@ -53,6 +53,7 @@ souphttpsrc
spectrum
sunaudio
udpsink
+udpsrc
videocrop
videofilter
wavpackdec
diff --git a/tests/check/elements/qtmux.c b/tests/check/elements/qtmux.c
index 5ceb3d15b..84614a265 100644
--- a/tests/check/elements/qtmux.c
+++ b/tests/check/elements/qtmux.c
@@ -28,6 +28,8 @@
#include <unistd.h>
#endif
+#include <glib/gstdio.h>
+
#include <gst/check/gstcheck.h>
#include <gst/pbutils/encoding-profile.h>
@@ -830,7 +832,12 @@ test_average_bitrate_custom (const gchar * elementname,
(guint) gst_util_uint64_scale_round ((guint64) total_bytes,
(guint64) 8 * GST_SECOND, (guint64) total_duration);
fail_unless (bitrate == expected);
+ gst_tag_list_free (taglist);
}
+
+ /* delete file */
+ g_unlink (location);
+ g_free (location);
}
GST_START_TEST (test_average_bitrate)
diff --git a/tests/check/elements/rgvolume.c b/tests/check/elements/rgvolume.c
index 50dab6a5b..93a336ca2 100644
--- a/tests/check/elements/rgvolume.c
+++ b/tests/check/elements/rgvolume.c
@@ -49,6 +49,8 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
GST_STATIC_CAPS (RG_VOLUME_CAPS_TEMPLATE_STRING)
);
+static GstBuffer *test_buffer_new (gfloat value);
+
/* gstcheck sets up a chain function that appends buffers to a global list.
* This is our equivalent of that for event handling. */
static gboolean
@@ -79,6 +81,37 @@ setup_rgvolume (void)
}
static void
+send_newsegment_and_empty_buffer (void)
+{
+ GstBuffer *buf;
+ GstEvent *ev;
+ GstSegment segment;
+
+ fail_unless (g_list_length (events) == 0);
+
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+ ev = gst_event_new_segment (&segment);
+ fail_unless (gst_pad_push_event (mysrcpad, ev),
+ "Pushing newsegment event failed");
+
+ buf = test_buffer_new (0.0);
+ GST_BUFFER_SIZE (buf) = 0;
+ GST_BUFFER_DURATION (buf) = 0;
+ GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET (buf);
+ fail_unless (gst_pad_push (mysrcpad, buf) == GST_FLOW_OK);
+
+ fail_unless (g_list_length (events) == 1);
+ fail_unless (events->data == ev);
+ gst_mini_object_unref ((GstMiniObject *) events->data);
+ events = g_list_remove (events, ev);
+
+ fail_unless (g_list_length (buffers) == 1);
+ fail_unless (buffers->data == buf);
+ gst_mini_object_unref ((GstMiniObject *) buffers->data);
+ buffers = g_list_remove (buffers, buf);
+}
+
+static void
cleanup_rgvolume (GstElement * element)
{
GST_DEBUG ("cleanup_rgvolume");
@@ -292,6 +325,8 @@ GST_START_TEST (test_events)
set_playing_state (element);
+ send_newsegment_and_empty_buffer ();
+
tag_list = gst_tag_list_new_empty ();
gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
GST_TAG_TRACK_GAIN, +4.95, GST_TAG_TRACK_PEAK, 0.59463,
@@ -340,6 +375,8 @@ GST_START_TEST (test_simple)
"pre-amp", -6.00, "fallback-gain", +1.23, NULL);
set_playing_state (element);
+ send_newsegment_and_empty_buffer ();
+
tag_list = gst_tag_list_new_empty ();
gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
GST_TAG_TRACK_GAIN, -3.45, GST_TAG_TRACK_PEAK, 1.0,
@@ -380,6 +417,8 @@ GST_START_TEST (test_fallback_gain)
"pre-amp", -6.00, "fallback-gain", -3.00, NULL);
set_playing_state (element);
+ send_newsegment_and_empty_buffer ();
+
tag_list = gst_tag_list_new_empty ();
gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
GST_TAG_TRACK_GAIN, +3.5, GST_TAG_TRACK_PEAK, 1.0,
@@ -423,6 +462,8 @@ GST_START_TEST (test_fallback_track)
"pre-amp", -6.00, "fallback-gain", +1.23, NULL);
set_playing_state (element);
+ send_newsegment_and_empty_buffer ();
+
tag_list = gst_tag_list_new_empty ();
gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
GST_TAG_TRACK_GAIN, +2.11, GST_TAG_TRACK_PEAK, 1.0, NULL);
@@ -448,6 +489,8 @@ GST_START_TEST (test_fallback_album)
"pre-amp", -6.00, "fallback-gain", +1.23, NULL);
set_playing_state (element);
+ send_newsegment_and_empty_buffer ();
+
tag_list = gst_tag_list_new_empty ();
gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
GST_TAG_ALBUM_GAIN, +3.73, GST_TAG_ALBUM_PEAK, 1.0, NULL);
@@ -470,6 +513,8 @@ GST_START_TEST (test_headroom)
"pre-amp", +0.00, "fallback-gain", +1.23, NULL);
set_playing_state (element);
+ send_newsegment_and_empty_buffer ();
+
tag_list = gst_tag_list_new_empty ();
gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
GST_TAG_TRACK_GAIN, +3.50, GST_TAG_TRACK_PEAK, 1.0, NULL);
@@ -512,6 +557,8 @@ GST_START_TEST (test_reference_level)
"headroom", +0.00, "pre-amp", +0.00, "fallback-gain", +1.23, NULL);
set_playing_state (element);
+ send_newsegment_and_empty_buffer ();
+
tag_list = gst_tag_list_new_empty ();
gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE,
GST_TAG_TRACK_GAIN, 0.00, GST_TAG_TRACK_PEAK, 0.2,
diff --git a/tests/check/elements/souphttpsrc.c b/tests/check/elements/souphttpsrc.c
index 6a7e85244..a21ab8ff6 100644
--- a/tests/check/elements/souphttpsrc.c
+++ b/tests/check/elements/souphttpsrc.c
@@ -23,6 +23,8 @@
# include "config.h"
#endif
+#include <stdlib.h>
+
#include <glib.h>
#include <glib/gprintf.h>
#include <libsoup/soup-address.h>
@@ -444,8 +446,11 @@ souphttpsrc_suite (void)
TCase *tc_chain, *tc_internet;
g_type_init ();
+
+#if !GLIB_CHECK_VERSION (2, 31, 0)
if (!g_thread_supported ())
g_thread_init (NULL);
+#endif
s = suite_create ("souphttpsrc");
tc_chain = tcase_create ("general");
@@ -453,7 +458,7 @@ souphttpsrc_suite (void)
suite_add_tcase (s, tc_chain);
run_server (&http_port, &https_port);
- g_atexit (stop_server);
+ atexit (stop_server);
tcase_add_test (tc_chain, test_first_buffer_has_offset);
tcase_add_test (tc_chain, test_redirect_yes);
tcase_add_test (tc_chain, test_redirect_no);
diff --git a/tests/check/elements/udpsrc.c b/tests/check/elements/udpsrc.c
new file mode 100644
index 000000000..d84334a3e
--- /dev/null
+++ b/tests/check/elements/udpsrc.c
@@ -0,0 +1,120 @@
+/* GStreamer UDP source unit tests
+ * Copyright (C) 2011 Tim-Philipp Müller <tim centricular net>
+ *
+ * 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.
+ */
+#include <gst/check/gstcheck.h>
+#include <gio/gio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+GST_START_TEST (test_udpsrc_empty_packet)
+{
+ GstElement *udpsrc;
+ GSocket *socket;
+ GstPad *sinkpad;
+ int port = 0;
+
+ udpsrc = gst_check_setup_element ("udpsrc");
+ fail_unless (udpsrc != NULL);
+ g_object_set (udpsrc, "port", 0, NULL);
+
+ sinkpad = gst_check_setup_sink_pad_by_name (udpsrc, &sinktemplate, "src");
+ fail_unless (sinkpad != NULL);
+ gst_pad_set_active (sinkpad, TRUE);
+
+ gst_element_set_state (udpsrc, GST_STATE_PLAYING);
+ g_object_get (udpsrc, "port", &port, NULL);
+ GST_INFO ("udpsrc port = %d", port);
+
+ socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
+ G_SOCKET_PROTOCOL_UDP, NULL);
+
+ if (socket != NULL) {
+ GSocketAddress *sa;
+ GInetAddress *ia;
+ gchar *s;
+
+ ia = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4);
+ s = g_inet_address_to_string (ia);
+ GST_LOG ("inet address %s", s);
+ g_free (s);
+ sa = g_inet_socket_address_new (ia, port);
+
+ if (g_socket_send_to (socket, sa, "HeLL0", 0, NULL, NULL) == 0) {
+ GST_INFO ("sent 0 bytes");
+ if (g_socket_send_to (socket, sa, "HeLL0", 6, NULL, NULL) == 6) {
+ GstBuffer *buf;
+ guint len;
+
+ GST_INFO ("sent 6 bytes");
+
+ g_usleep (G_USEC_PER_SEC / 2);
+
+ len = g_list_length (buffers);
+ GST_INFO ("%u buffers", len);
+ fail_unless (len == 1 || len == 2);
+
+ /* last buffer should be our HeLL0 string */
+ buf = GST_BUFFER (g_list_nth_data (buffers, len - 1));
+ fail_unless_equals_int (GST_BUFFER_SIZE (buf), 6);
+ fail_unless_equals_string ((gchar *) GST_BUFFER_DATA (buf), "HeLL0");
+
+ /* if there's another buffer, it should be 0 bytes */
+ if (len == 2) {
+ buf = GST_BUFFER (g_list_nth_data (buffers, 0));
+ fail_unless_equals_int (GST_BUFFER_SIZE (buf), 0);
+ }
+ } else {
+ GST_WARNING ("send_to(6 bytes) failed");
+ }
+ } else {
+ GST_WARNING ("send_to(0 bytes) failed");
+ }
+
+ g_object_unref (sa);
+ g_object_unref (ia);
+ } else {
+ GST_WARNING ("Could not create IPv4 UDP socket for unit test");
+ }
+
+ gst_element_set_state (udpsrc, GST_STATE_NULL);
+
+ gst_check_teardown_pad_by_name (udpsrc, "src");
+ gst_check_teardown_element (udpsrc);
+
+ g_object_unref (socket);
+}
+
+GST_END_TEST;
+
+static Suite *
+udpsrc_suite (void)
+{
+ Suite *s = suite_create ("udpsrc");
+ TCase *tc_chain = tcase_create ("udpsrc");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_udpsrc_empty_packet);
+ return s;
+}
+
+GST_CHECK_MAIN (udpsrc)
diff --git a/tests/files/Makefile.am b/tests/files/Makefile.am
index a0a282937..ae08e1a0f 100644
--- a/tests/files/Makefile.am
+++ b/tests/files/Makefile.am
@@ -7,6 +7,7 @@ EXTRA_DIST = \
id3-577468-unsynced-tag.tag \
id3-588148-unsynced-v24.tag \
pcm16sine.flv \
+ pinknoise-vorbis.mkv \
test-cert.pem \
test-key.pem
diff --git a/tests/icles/equalizer-test.c b/tests/icles/equalizer-test.c
index e8126fad3..fc6d5273e 100644
--- a/tests/icles/equalizer-test.c
+++ b/tests/icles/equalizer-test.c
@@ -179,8 +179,10 @@ main (int argc, char **argv)
GstPad *eq_sinkpad;
gchar *uri;
+#if !GLIB_CHECK_VERSION (2, 31, 0)
if (!g_thread_supported ())
g_thread_init (NULL);
+#endif
/* command line option parsing */
ctx = g_option_context_new ("FILENAME");
diff --git a/tests/icles/gdkpixbufsink-test.c b/tests/icles/gdkpixbufsink-test.c
index c334326e0..8ada8614b 100644
--- a/tests/icles/gdkpixbufsink-test.c
+++ b/tests/icles/gdkpixbufsink-test.c
@@ -330,8 +330,10 @@ main (int argc, char **argv)
GOptionContext *ctx;
GError *opt_err = NULL;
+#if !GLIB_CHECK_VERSION (2, 31, 0)
if (!g_thread_supported ())
g_thread_init (NULL);
+#endif
gtk_init (&argc, &argv);
diff --git a/tests/icles/test-oss4.c b/tests/icles/test-oss4.c
index f15875d7b..233e891fd 100644
--- a/tests/icles/test-oss4.c
+++ b/tests/icles/test-oss4.c
@@ -233,8 +233,10 @@ main (int argc, char **argv)
GOptionContext *ctx;
GError *err = NULL;
+#if !GLIB_CHECK_VERSION (2, 31, 0)
if (!g_thread_supported ())
g_thread_init (NULL);
+#endif
ctx = g_option_context_new ("");
g_option_context_add_main_entries (ctx, options, NULL);
diff --git a/tests/icles/v4l2src-test.c b/tests/icles/v4l2src-test.c
index 02d005dca..5020c5e7f 100644
--- a/tests/icles/v4l2src-test.c
+++ b/tests/icles/v4l2src-test.c
@@ -491,7 +491,13 @@ main (int argc, char *argv[])
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
loop = g_main_loop_new (NULL, FALSE);
- if (!(input_thread = g_thread_create (read_user, source, TRUE, NULL))) {
+#if !GLIB_CHECK_VERSION (2, 31, 0)
+ input_thread = g_thread_create (read_user, source, TRUE, NULL);
+#else
+ input_thread = g_thread_try_new ("v4l2src-test", read_user, source, NULL);
+#endif
+
+ if (input_thread == NULL) {
fprintf (stderr, "error: g_thread_create return NULL");
return -1;
}
diff --git a/tests/icles/videocrop-test.c b/tests/icles/videocrop-test.c
index 0106e6d41..de8963b3f 100644
--- a/tests/icles/videocrop-test.c
+++ b/tests/icles/videocrop-test.c
@@ -193,8 +193,10 @@ main (int argc, char **argv)
GstCaps *filter_caps = NULL;
GList *caps_list, *l;
+#if !GLIB_CHECK_VERSION (2, 31, 0)
if (!g_thread_supported ())
g_thread_init (NULL);
+#endif
/* command line option parsing */
ctx = g_option_context_new ("");