From a8afe5f5b387fe1585525e58eafcf31f7d17c5f6 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 1 Oct 2004 08:42:56 +0000 Subject: [PATCH] ext/dvdread/dvdreadsrc.c: Fix. Don't do one big huge loop around the whole DVD, that will cache all data and thus eat... Original commit message from CVS: * ext/dvdread/dvdreadsrc.c: (dvdreadsrc_class_init), (dvdreadsrc_init), (dvdreadsrc_dispose), (dvdreadsrc_set_property), (dvdreadsrc_get_property), (_open), (_seek), (_read), (dvdreadsrc_get), (dvdreadsrc_open_file), (dvdreadsrc_change_state): Fix. Don't do one big huge loop around the whole DVD, that will cache all data and thus eat sizeof(dvd) (several GB) before we see something. * gst-libs/gst/riff/riff-read.c: (gst_riff_read_seek): Actually NULL'ify event after using it. * gst/matroska/ebml-read.c: (gst_ebml_read_use_event), (gst_ebml_read_handle_event), (gst_ebml_read_element_id), (gst_ebml_read_element_length), (gst_ebml_read_element_data), (gst_ebml_read_seek), (gst_ebml_read_skip): Handle events. * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_base_init), (gst_dvd_demux_init), (gst_dvd_demux_get_audio_stream), (gst_dvd_demux_get_subpicture_stream), (gst_dvd_demux_plugin_init): Fix timing (this will probably break if I seek using menus, but I didn't get there yet). VOBs and normal DVDs should now work. Add a mpeg2-only pad with high rank so this get autoplugged for MPEG-2 movies. * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_base_init), (gst_mpeg_demux_class_init), (gst_mpeg_demux_init), (gst_mpeg_demux_new_output_pad), (gst_mpeg_demux_get_video_stream), (gst_mpeg_demux_get_audio_stream), (gst_mpeg_demux_get_private_stream), (gst_mpeg_demux_parse_packet), (gst_mpeg_demux_parse_pes), (gst_mpeg_demux_plugin_init): Use this as second rank for MPEG-1 and MPEG-2. Still use this for MPEG-1 but use dvddemux for MPEG-2. * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_class_init), (gst_mpeg_parse_init), (gst_mpeg_parse_new_pad), (gst_mpeg_parse_parse_packhead): Timing. Only add pad template if it exists. Add sink template from class and not from ourselves. This means we will always use the correct sink template even if it is not the one defined in this file. --- ChangeLog | 40 ++++++++++++ gst/matroska/ebml-read.c | 127 ++++++++++++++++++++++++--------------- 2 files changed, 117 insertions(+), 50 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9ba7d02e56..7e15ebf322 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,43 @@ +2004-10-01 Ronald S. Bultje + + * ext/dvdread/dvdreadsrc.c: (dvdreadsrc_class_init), + (dvdreadsrc_init), (dvdreadsrc_dispose), (dvdreadsrc_set_property), + (dvdreadsrc_get_property), (_open), (_seek), (_read), + (dvdreadsrc_get), (dvdreadsrc_open_file), + (dvdreadsrc_change_state): + Fix. Don't do one big huge loop around the whole DVD, that will + cache all data and thus eat sizeof(dvd) (several GB) before we + see something. + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_seek): + Actually NULL'ify event after using it. + * gst/matroska/ebml-read.c: (gst_ebml_read_use_event), + (gst_ebml_read_handle_event), (gst_ebml_read_element_id), + (gst_ebml_read_element_length), (gst_ebml_read_element_data), + (gst_ebml_read_seek), (gst_ebml_read_skip): + Handle events. + * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_base_init), + (gst_dvd_demux_init), (gst_dvd_demux_get_audio_stream), + (gst_dvd_demux_get_subpicture_stream), (gst_dvd_demux_plugin_init): + Fix timing (this will probably break if I seek using menus, but + I didn't get there yet). VOBs and normal DVDs should now work. + Add a mpeg2-only pad with high rank so this get autoplugged for + MPEG-2 movies. + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_base_init), + (gst_mpeg_demux_class_init), (gst_mpeg_demux_init), + (gst_mpeg_demux_new_output_pad), (gst_mpeg_demux_get_video_stream), + (gst_mpeg_demux_get_audio_stream), + (gst_mpeg_demux_get_private_stream), (gst_mpeg_demux_parse_packet), + (gst_mpeg_demux_parse_pes), (gst_mpeg_demux_plugin_init): + Use this as second rank for MPEG-1 and MPEG-2. Still use this for + MPEG-1 but use dvddemux for MPEG-2. + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_class_init), + (gst_mpeg_parse_init), (gst_mpeg_parse_new_pad), + (gst_mpeg_parse_parse_packhead): + Timing. Only add pad template if it exists. Add sink template from + class and not from ourselves. This means we will always use the + correct sink template even if it is not the one defined in this + file. + 2004-09-29 Wim Taymans * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_packet), diff --git a/gst/matroska/ebml-read.c b/gst/matroska/ebml-read.c index 6face5ad22..0ec5aac343 100644 --- a/gst/matroska/ebml-read.c +++ b/gst/matroska/ebml-read.c @@ -114,6 +114,64 @@ gst_ebml_read_change_state (GstElement * element) return GST_STATE_SUCCESS; } +/* + * 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_ebml_read_use_event (GstEbmlRead * ebml, GstEvent * event) +{ + if (!event) { + GST_ELEMENT_ERROR (ebml, RESOURCE, READ, (NULL), (NULL)); + return FALSE; + } + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + gst_pad_event_default (ebml->sinkpad, event); + return FALSE; + + case GST_EVENT_INTERRUPT: + gst_event_unref (event); + return FALSE; + + case GST_EVENT_DISCONTINUOUS: + GST_WARNING_OBJECT (ebml, "Unexected discont - might lose sync"); + gst_pad_event_default (ebml->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 (ebml->sinkpad, event); + return FALSE; + } + + /* happy */ + g_assert_not_reached (); + return FALSE; +} + +static gboolean +gst_ebml_read_handle_event (GstEbmlRead * ebml) +{ + GstEvent *event = NULL; + guint32 remaining; + + gst_bytestream_get_status (ebml->bs, &remaining, &event); + + return gst_ebml_read_use_event (ebml, event); +} + /* * Return: the amount of levels in the hierarchy that the * current element lies higher than the previous one. @@ -155,25 +213,8 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up) guint32 total; while (gst_bytestream_peek_bytes (ebml->bs, &data, 1) != 1) { - GstEvent *event = NULL; - guint32 remaining; - - /* Here, we might encounter EOS */ - gst_bytestream_get_status (ebml->bs, &remaining, &event); - if (event && GST_IS_EVENT (event)) { - gboolean eos = (GST_EVENT_TYPE (event) == GST_EVENT_EOS); - - gst_pad_event_default (ebml->sinkpad, event); - if (eos) - return FALSE; - } else { - guint64 pos = gst_bytestream_tell (ebml->bs); - - gst_event_unref (event); - GST_ELEMENT_ERROR (ebml, RESOURCE, READ, (NULL), - ("Read error at position %llu (0x%llx)", pos, pos)); + if (!gst_ebml_read_handle_event (ebml)) return -1; - } } total = data[0]; while (read <= 4 && !(total & len_mask)) { @@ -189,12 +230,9 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up) return -1; } - if (gst_bytestream_peek_bytes (ebml->bs, &data, read) != read) { - guint64 pos = gst_bytestream_tell (ebml->bs); - - GST_ELEMENT_ERROR (ebml, RESOURCE, READ, (NULL), - ("Read error at position %llu (0x%llx)", pos, pos)); - return -1; + while (gst_bytestream_peek_bytes (ebml->bs, &data, read) != read) { + if (!gst_ebml_read_handle_event (ebml)) + return -1; } while (n < read) total = (total << 8) | data[n++]; @@ -220,12 +258,9 @@ gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length) gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0; guint64 total; - if (gst_bytestream_peek_bytes (ebml->bs, &data, 1) != 1) { - guint64 pos = gst_bytestream_tell (ebml->bs); - - GST_ELEMENT_ERROR (ebml, RESOURCE, READ, (NULL), - ("Read error at position %llu (0x%llx)", pos, pos)); - return -1; + while (gst_bytestream_peek_bytes (ebml->bs, &data, 1) != 1) { + if (!gst_ebml_read_handle_event (ebml)) + return -1; } total = data[0]; while (read <= 8 && !(total & len_mask)) { @@ -243,12 +278,9 @@ gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length) if ((total &= (len_mask - 1)) == len_mask - 1) num_ffs++; - if (gst_bytestream_peek_bytes (ebml->bs, &data, read) != read) { - guint64 pos = gst_bytestream_tell (ebml->bs); - - GST_ELEMENT_ERROR (ebml, RESOURCE, READ, (NULL), - ("Read error at position %llu (0x%llx)", pos, pos)); - return -1; + while (gst_bytestream_peek_bytes (ebml->bs, &data, read) != read) { + if (!gst_ebml_read_handle_event (ebml)) + return -1; } while (n < read) { if (data[n] == 0xff) @@ -276,13 +308,8 @@ gst_ebml_read_element_data (GstEbmlRead * ebml, guint64 length) GstBuffer *buf = NULL; if (gst_bytestream_peek (ebml->bs, &buf, length) != length) { - guint64 pos = gst_bytestream_tell (ebml->bs); - - GST_ELEMENT_ERROR (ebml, RESOURCE, READ, (NULL), - ("Read error at position %llu (0x%llx)", pos, pos)); - if (buf) - gst_buffer_unref (buf); - return NULL; + if (!gst_ebml_read_handle_event (ebml)) + return NULL; } gst_bytestream_flush_fast (ebml->bs, length); @@ -323,8 +350,10 @@ gst_ebml_read_seek (GstEbmlRead * ebml, guint64 offset) /* first, flush remaining buffers */ gst_bytestream_get_status (ebml->bs, &remaining, &event); if (event) { - g_warning ("Unexpected event before seek"); - gst_event_unref (event); + GST_WARNING ("Unexpected event before seek"); + if (!gst_ebml_read_use_event (ebml, event)) + return NULL; + event = NULL; } if (remaining) gst_bytestream_flush_fast (ebml->bs, remaining); @@ -350,10 +379,7 @@ gst_ebml_read_seek (GstEbmlRead * ebml, 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 (ebml->sinkpad, event); - if (type == GST_EVENT_EOS || type == GST_EVENT_INTERRUPT) + if (!gst_ebml_read_use_event (ebml, event)) return NULL; event = NULL; } @@ -386,7 +412,8 @@ gst_ebml_read_skip (GstEbmlRead * ebml) gst_bytestream_get_status (ebml->bs, &remaining, &event); if (event) { g_warning ("Unexpected event before skip"); - gst_event_unref (event); + if (!gst_ebml_read_use_event (ebml, event)) + return FALSE; } if (remaining >= length)