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; diff --git a/gst/flx/gstflxdec.c b/gst/flx/gstflxdec.c index b269496258..3323ca0a02 100644 --- a/gst/flx/gstflxdec.c +++ b/gst/flx/gstflxdec.c @@ -28,6 +28,9 @@ #define JIFFIE (GST_SECOND/70) +GST_DEBUG_CATEGORY_STATIC (flxdec_debug); +#define GST_CAT_DEFAULT flxdec_debug + /* flx element information */ static GstElementDetails flxdec_details = { "FLX Decoder", @@ -133,6 +136,8 @@ gst_flxdec_class_init (GstFlxDecClass * klass) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + GST_DEBUG_CATEGORY_INIT (flxdec_debug, "flxdec", 0, "FLX video decoder"); + gobject_class->set_property = gst_flxdec_set_property; gobject_class->get_property = gst_flxdec_get_property; @@ -206,9 +211,8 @@ flx_decode_chunks (GstFlxDec * flxdec, gulong count, gchar * data, gchar * dest) break; default: - g_print ("GstFlxDec: Unimplented chunk type: 0x%02x size: %d\n", + GST_WARNING ("Unimplented chunk type: 0x%02x size: %d - skipping", hdr->id, hdr->size); - g_print ("GstFlxDec: Skipping...\n"); data += rndalign (hdr->size) - FlxFrameChunkSize; break; } @@ -228,7 +232,7 @@ flx_decode_color (GstFlxDec * flxdec, guchar * data, guchar * dest, gint scale) data += 2; indx = 0; - g_print ("GstFlxDec: cmap packs: %d\n", packs); + GST_LOG ("GstFlxDec: cmap packs: %d", packs); while (packs--) { /* color map index + skip count */ indx += *data++; @@ -238,7 +242,7 @@ flx_decode_color (GstFlxDec * flxdec, guchar * data, guchar * dest, gint scale) if (count == 0) count = 256; - g_print ("GstFlxDec: cmap count: %d (indx: %d)\n", count, indx); + GST_LOG ("GstFlxDec: cmap count: %d (indx: %d)\n", count, indx); flx_set_palette_vector (flxdec->converter, indx, count, data, scale); data += (count * 3); @@ -449,7 +453,7 @@ gst_flxdec_loop (GstElement * element) databuf = flx_get_data (flxdec, FlxHeaderSize); if (!databuf) { - g_print ("empty buffer\n"); + GST_LOG ("empty buffer"); return; } @@ -470,12 +474,12 @@ gst_flxdec_loop (GstElement * element) } - g_print ("GstFlxDec: size : %d\n", flxh->size); - g_print ("GstFlxDec: frames : %d\n", flxh->frames); - g_print ("GstFlxDec: width : %d\n", flxh->width); - g_print ("GstFlxDec: height : %d\n", flxh->height); - g_print ("GstFlxDec: depth : %d\n", flxh->depth); - g_print ("GstFlxDec: speed : %d\n", flxh->speed); + GST_LOG ("size : %d\n", flxh->size); + GST_LOG ("frames : %d\n", flxh->frames); + GST_LOG ("width : %d\n", flxh->width); + GST_LOG ("height : %d\n", flxh->height); + GST_LOG ("depth : %d\n", flxh->depth); + GST_LOG ("speed : %d\n", flxh->speed); flxdec->next_time = 0; @@ -496,10 +500,10 @@ gst_flxdec_loop (GstElement * element) flx_colorspace_converter_new (flxh->width, flxh->height); if (flxh->type == FLX_MAGICHDR_FLC || flxh->type == FLX_MAGICHDR_FLX) { - g_print ("GstFlxDec: (FLC) aspect_dx : %d\n", flxh->aspect_dx); - g_print ("GstFlxDec: (FLC) aspect_dy : %d\n", flxh->aspect_dy); - g_print ("GstFlxDec: (FLC) oframe1 : 0x%08x\n", flxh->oframe1); - g_print ("GstFlxDec: (FLC) oframe2 : 0x%08x\n", flxh->oframe2); + GST_LOG ("(FLC) aspect_dx : %d\n", flxh->aspect_dx); + GST_LOG ("(FLC) aspect_dy : %d\n", flxh->aspect_dy); + GST_LOG ("(FLC) oframe1 : 0x%08x\n", flxh->oframe1); + GST_LOG ("(FLC) oframe2 : 0x%08x\n", flxh->oframe2); } flxdec->size = (flxh->width * flxh->height); diff --git a/gst/modplug/gstmodplug.cc b/gst/modplug/gstmodplug.cc index 8e8b6efd3b..c5a2fa82e8 100644 --- a/gst/modplug/gstmodplug.cc +++ b/gst/modplug/gstmodplug.cc @@ -346,15 +346,19 @@ gst_modplug_src_query (GstPad * pad, GstQueryType type, break; case GST_QUERY_POSITION: switch (*format) { - default: + case GST_FORMAT_TIME: tmp = ((float) (modplug->mSoundFile->GetSongTime () * modplug->mSoundFile->GetCurrentPos ()) / (float) modplug->mSoundFile->GetMaxPosition ()); *value = (gint64) (tmp * GST_SECOND); break; + default: + res = FALSE; + break; } default: + res = FALSE; break; }