diff --git a/ChangeLog b/ChangeLog index 75b76db660..a38fdd0495 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,48 @@ +2004-09-29 Ronald S. Bultje + + * ext/flac/gstflacdec.c: (gst_flacdec_src_query): + Only return true if we actually filled something in. Prevents + player applications from showing a random length for flac files. + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_class_init), + (gst_riff_read_use_event), (gst_riff_read_handle_event), + (gst_riff_read_seek), (gst_riff_read_skip), (gst_riff_read_strh), + (gst_riff_read_strf_vids_with_data), + (gst_riff_read_strf_auds_with_data), (gst_riff_read_strf_iavs): + OK, ok, so I implemented event handling. Apparently it's normal + that we receive random events at random points without asking + for it. + * gst/avi/gstavidemux.c: (gst_avi_demux_reset), + (gst_avi_demux_src_convert), (gst_avi_demux_handle_src_query), + (gst_avi_demux_handle_src_event), (gst_avi_demux_stream_index), + (gst_avi_demux_sync), (gst_avi_demux_stream_scan), + (gst_avi_demux_massage_index), (gst_avi_demux_stream_header), + (gst_avi_demux_handle_seek), (gst_avi_demux_process_next_entry), + (gst_avi_demux_stream_data), (gst_avi_demux_loop): + * gst/avi/gstavidemux.h: + Implement non-lineair chunk handling and subchunk processing. + The first solves playback of AVI files where the audio and video + data of individual buffers that we read are not synchronized. + This should not happen according to the wonderful AVI specs, but + of course it does happen in reality. It is also a prerequisite for + the second. Subchunk processing allows us to cut chunks in small + pieces and process each of these pieces separately. This is + required because I've seen several AVI files with incredibly large + audio chunks, even some files with only one audio chunk for the + whole file. This allows for proper playback including seeking. + This patch is supposed to fix all AVI A/V sync issues. + * gst/flx/gstflxdec.c: (gst_flxdec_class_init), + (flx_decode_chunks), (flx_decode_color), (gst_flxdec_loop): + Work. + * gst/modplug/gstmodplug.cc: + Proper return value setting for the query() function. + * gst/playback/gstplaybasebin.c: (setup_source): + Being in non-playing state (after, e.g., EOS) is not necessarily + a bad thing. Allow for that. This fixes playback of short files. + They don't actually playback fully now, because the clock already + runs. This means that small files (<500kB) with a small length + (<2sec) will still not or barely play. Other files, such as mod + or flx, will work correctly, however. + 2004-09-28 Wim Taymans * ext/speex/gstspeex.c: (plugin_init): diff --git a/gst-libs/gst/riff/riff-read.c b/gst-libs/gst/riff/riff-read.c index d81f6ada7f..a400c7aa78 100644 --- a/gst-libs/gst/riff/riff-read.c +++ b/gst-libs/gst/riff/riff-read.c @@ -29,6 +29,9 @@ #include "riff-ids.h" #include "riff-read.h" +GST_DEBUG_CATEGORY_STATIC (riffread_debug); +#define GST_CAT_DEFAULT riffread_debug + enum { ARG_0, @@ -76,6 +79,9 @@ gst_riff_read_class_init (GstRiffReadClass * klass) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + GST_DEBUG_CATEGORY_INIT (riffread_debug, "riffread", + 0, "RIFF stream helper class"); + gstelement_class->change_state = gst_riff_read_change_state; } @@ -145,6 +151,64 @@ gst_riff_read_element_level_up (GstRiffRead * riff) return num; } +/* + * Event handler. Basic: + * - EOS: end-of-file, stop processing, forward EOS. + * - Interrupt: stop processing. + * - Discont: shouldn't be handled here but in the seek handler. Error. + * - Flush: ignore, since we check for flush flags manually. Don't forward. + * - Others: warn, ignore. + * Return value indicates whether to continue processing. + */ + +static gboolean +gst_riff_read_use_event (GstRiffRead * riff, GstEvent * event) +{ + if (!event) { + GST_ELEMENT_ERROR (riff, RESOURCE, READ, (NULL), (NULL)); + return FALSE; + } + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + gst_pad_event_default (riff->sinkpad, event); + return FALSE; + + case GST_EVENT_INTERRUPT: + gst_event_unref (event); + return FALSE; + + case GST_EVENT_DISCONTINUOUS: + GST_WARNING_OBJECT (riff, "Unexected discont - might lose sync"); + gst_pad_event_default (riff->sinkpad, event); + return TRUE; + + case GST_EVENT_FLUSH: + gst_event_unref (event); + return TRUE; + + default: + GST_WARNING ("don't know how to handle event %d", GST_EVENT_TYPE (event)); + gst_pad_event_default (riff->sinkpad, event); + return FALSE; + } + + /* happy */ + g_assert_not_reached (); + return FALSE; +} + +static gboolean +gst_riff_read_handle_event (GstRiffRead * riff) +{ + GstEvent *event = NULL; + guint32 remaining; + + gst_bytestream_get_status (riff->bs, &remaining, &event); + + return gst_riff_read_use_event (riff, event); +} + /* * Read the next tag plus length (may be NULL). Return * TRUE on success or FALSE on failure. @@ -174,21 +238,8 @@ gst_riff_peek_head (GstRiffRead * riff, /* read */ while (gst_bytestream_peek_bytes (riff->bs, &data, 8) != 8) { - GstEvent *event = NULL; - guint32 remaining; - - /* Here, we might encounter EOS */ - gst_bytestream_get_status (riff->bs, &remaining, &event); - if (event && GST_IS_EVENT (event)) { - gboolean eos = (GST_EVENT_TYPE (event) == GST_EVENT_EOS); - - gst_pad_event_default (riff->sinkpad, event); - if (eos) - return FALSE; - } else { - GST_ELEMENT_ERROR (riff, RESOURCE, READ, (NULL), (NULL)); + if (!gst_riff_read_handle_event (riff)) return FALSE; - } } /* parse tag + length (if wanted) */ @@ -215,33 +266,10 @@ gst_riff_read_element_data (GstRiffRead * riff, guint length, guint * got_bytes) guint32 got; while ((got = gst_bytestream_peek (riff->bs, &buf, length)) != length) { - /*GST_ELEMENT_ERROR (riff, RESOURCE, READ, (NULL), (NULL)); */ - GstEvent *event = NULL; - guint32 remaining; - - gst_bytestream_get_status (riff->bs, &remaining, &event); - if (event && GST_IS_EVENT (event)) { - gst_pad_event_default (riff->sinkpad, event); - if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { - - if (buf) - gst_buffer_unref (buf); - - if (got_bytes) - *got_bytes = got; - - return NULL; - } - } else { - GST_ELEMENT_ERROR (riff, RESOURCE, READ, (NULL), (NULL)); - if (buf) - gst_buffer_unref (buf); - - if (got_bytes) - *got_bytes = got; - + if (buf) + gst_buffer_unref (buf); + if (!gst_riff_read_handle_event (riff)) return NULL; - } } /* we need 16-bit alignment */ @@ -275,7 +303,9 @@ gst_riff_read_seek (GstRiffRead * riff, guint64 offset) /* first, flush remaining buffers */ gst_bytestream_get_status (riff->bs, &remaining, &event); if (event) { - g_warning ("Unexpected event before seek"); + GST_WARNING ("Unexpected event before seek"); + if (!gst_riff_read_use_event (riff, event)) + return NULL; } if (remaining) @@ -301,10 +331,7 @@ gst_riff_read_seek (GstRiffRead * riff, guint64 offset) GST_WARNING ("No discontinuity event after seek - seek failed"); break; } else if (GST_EVENT_TYPE (event) != GST_EVENT_DISCONTINUOUS) { - GstEventType type = GST_EVENT_TYPE (event); - - gst_pad_event_default (riff->sinkpad, event); - if (type == GST_EVENT_EOS || type == GST_EVENT_INTERRUPT) + if (!gst_riff_read_use_event (riff, event)) return NULL; event = NULL; } @@ -361,7 +388,7 @@ gboolean gst_riff_read_skip (GstRiffRead * riff) { guint32 tag, length; - GstEvent *event; + GstEvent *event = NULL; guint32 remaining; if (!gst_riff_peek_head (riff, &tag, &length, NULL)) @@ -376,12 +403,9 @@ gst_riff_read_skip (GstRiffRead * riff) /* see if we have that much data available */ gst_bytestream_get_status (riff->bs, &remaining, &event); - if (event && GST_IS_EVENT (event)) { - gboolean eos = (GST_EVENT_TYPE (event) == GST_EVENT_EOS); - - g_warning ("Unexpected event in skip"); - gst_pad_event_default (riff->sinkpad, event); - if (eos) + if (event) { + GST_WARNING ("Unexpected event in skip"); + if (!gst_riff_read_use_event (riff, event)) return FALSE; } @@ -458,7 +482,7 @@ gst_riff_read_strh (GstRiffRead * riff, gst_riff_strh ** header) return FALSE; } if (GST_BUFFER_SIZE (buf) < sizeof (gst_riff_strh)) { - g_warning ("Too small strh (%d available, %d needed)", + GST_WARNING ("Too small strh (%d available, %d needed)", GST_BUFFER_SIZE (buf), (int) sizeof (gst_riff_strh)); gst_buffer_unref (buf); return FALSE; @@ -526,7 +550,7 @@ gst_riff_read_strf_vids_with_data (GstRiffRead * riff, return FALSE; } if (GST_BUFFER_SIZE (buf) < sizeof (gst_riff_strf_vids)) { - g_warning ("Too small strf_vids (%d available, %d needed)", + GST_WARNING ("Too small strf_vids (%d available, %d needed)", GST_BUFFER_SIZE (buf), (int) sizeof (gst_riff_strf_vids)); gst_buffer_unref (buf); return FALSE; @@ -620,7 +644,7 @@ gst_riff_read_strf_auds_with_data (GstRiffRead * riff, return FALSE; } if (GST_BUFFER_SIZE (buf) < sizeof (gst_riff_strf_auds)) { - g_warning ("Too small strf_auds (%d available, %d needed)", + GST_WARNING ("Too small strf_auds (%d available, %d needed)", GST_BUFFER_SIZE (buf), (int) sizeof (gst_riff_strf_auds)); gst_buffer_unref (buf); return FALSE; @@ -702,7 +726,7 @@ gst_riff_read_strf_iavs (GstRiffRead * riff, gst_riff_strf_iavs ** header) return FALSE; } if (GST_BUFFER_SIZE (buf) < sizeof (gst_riff_strf_iavs)) { - g_warning ("Too small strf_iavs (%d available, %d needed)", + GST_WARNING ("Too small strf_iavs (%d available, %d needed)", GST_BUFFER_SIZE (buf), (int) sizeof (gst_riff_strf_iavs)); gst_buffer_unref (buf); return FALSE;