wavparse: add a ignore-length property

This allows playing broken streams which write an incorrect
length in their data chunks (such as, at least, one streaming
camera).

https://bugzilla.gnome.org/show_bug.cgi?id=665911
This commit is contained in:
Vincent Penquerc'h 2011-12-12 16:49:19 +00:00
parent 42310421b3
commit 734e352b73
2 changed files with 86 additions and 2 deletions

View file

@ -87,6 +87,19 @@ static gboolean gst_wavparse_sink_event (GstPad * pad, GstEvent * event);
static void gst_wavparse_loop (GstPad * pad);
static gboolean gst_wavparse_srcpad_event (GstPad * pad, 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 ("wavparse_sink",
GST_PAD_SINK,
@ -134,6 +147,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;
}
@ -1348,6 +1382,10 @@ gst_wavparse_stream_headers (GstWavParse * wav)
switch (tag) {
case GST_RIFF_TAG_data:{
GST_DEBUG_OBJECT (wav, "Got 'data' TAG, size : %d", size);
if (wav->ignore_length) {
GST_DEBUG_OBJECT (wav, "Ignoring length");
size = 0;
}
if (wav->streaming) {
gst_adapter_flush (wav->adapter, 8);
gotdata = TRUE;
@ -1566,10 +1604,12 @@ gst_wavparse_stream_headers (GstWavParse * wav)
if (gst_wavparse_calculate_duration (wav)) {
gst_segment_init (&wav->segment, GST_FORMAT_TIME);
if (!wav->ignore_length)
gst_segment_set_duration (&wav->segment, GST_FORMAT_TIME, wav->duration);
} else {
/* no bitrate, let downstream peer do the math, we'll feed it bytes. */
gst_segment_init (&wav->segment, GST_FORMAT_BYTES);
if (!wav->ignore_length)
gst_segment_set_duration (&wav->segment, GST_FORMAT_BYTES, wav->datasize);
}
@ -2489,6 +2529,11 @@ gst_wavparse_pad_query (GstPad * pad, GstQuery * query)
gint64 duration = 0;
GstFormat format;
if (wav->ignore_length) {
res = FALSE;
break;
}
gst_query_parse_duration (query, &format, NULL);
switch (format) {
@ -2657,6 +2702,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)
{

View file

@ -118,6 +118,8 @@ struct _GstWavParse {
gboolean first;
/* discont after seek */
gboolean discont;
gboolean ignore_length;
};
struct _GstWavParseClass {