+2004-09-29 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+
+ * 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 <wim@fluendo.com>
* ext/speex/gstspeex.c: (plugin_init):
#include "riff-ids.h"
#include "riff-read.h"
+GST_DEBUG_CATEGORY_STATIC (riffread_debug);
+#define GST_CAT_DEFAULT riffread_debug
+
enum
{
ARG_0,
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;
}
}
/*
+ * 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.
*/
/* 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) */
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 */
/* 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)
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;
}
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))
/* 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;
}
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;
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;
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;
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;