diff options
-rw-r--r-- | ChangeLog | 6 | ||||
m--------- | common | 0 | ||||
-rw-r--r-- | gst/avi/gstavidemux.c | 84 |
3 files changed, 66 insertions, 24 deletions
@@ -1,3 +1,9 @@ +2008-06-05 Thijs Vermeir <thijsvermeir@gmail.com> + + * gst/avi/gstavidemux.c: + Catch UNEXPECTED when downstream has reached end of + segment in reverse mode. + 2008-06-04 Thijs Vermeir <thijsvermeir@gmail.com> * gst/avi/gstavidemux.c: diff --git a/common b/common -Subproject 130fa8f739ff09aedb520c33239f53d06cfe9bd +Subproject 68fb019d4044b9878aef4ca223fc13c19ffc7d0 diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c index d9a1b229..b72e5354 100644 --- a/gst/avi/gstavidemux.c +++ b/gst/avi/gstavidemux.c @@ -140,7 +140,8 @@ gst_avi_demux_base_init (GstAviDemuxClass * klass) "Demultiplex an avi file into audio and video", "Erik Walthinsen <omega@cse.ogi.edu>\n" "Wim Taymans <wim.taymans@chello.be>\n" - "Ronald Bultje <rbultje@ronald.bitfreak.net>"); + "Ronald Bultje <rbultje@ronald.bitfreak.net>\n" + "Thijs Vermeir <thijsvermeir@gmail.com>"); GstElementClass *element_class = GST_ELEMENT_CLASS (klass); GstPadTemplate *videosrctempl, *audiosrctempl, *subsrctempl; GstCaps *audcaps, *vidcaps, *subcaps; @@ -1693,7 +1694,7 @@ gst_avi_demux_parse_index (GstAviDemux * avi, stream->total_frames++; stream->idx_duration = next_ts; - GST_DEBUG_OBJECT (avi, + GST_LOG_OBJECT (avi, "Adding index entry %d (%6u), flags %02x, stream %d, size %u " ", offset %" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT, @@ -2403,7 +2404,7 @@ gst_avi_demux_massage_index (GstAviDemux * avi, num_per_stream[entry->stream_nr]++; #endif - GST_DEBUG ("Sorted index entry %3d for stream %d of size %6u" + GST_LOG_OBJECT (avi, "Sorted index entry %3d for stream %d of size %6u" " at offset %7" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT " dur %" GST_TIME_FORMAT, avi->index_entries[i].index_nr, entry->stream_nr, entry->size, @@ -3448,6 +3449,38 @@ done: } /* + * prepare the avi element for a reverse jump to a prev keyframe + * this function will return the start entry. if the function returns + * NULL there was no prev keyframe. + */ +static gst_avi_index_entry * +gst_avi_demux_step_reverse (GstAviDemux * avi) +{ + gst_avi_index_entry *entry; + gint i; + + avi->reverse_stop_index = avi->reverse_start_index; + entry = + gst_avi_demux_index_prev (avi, 0, avi->reverse_stop_index, + GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME); + if (!entry) { + GST_DEBUG_OBJECT (avi, "no valid index entry found index %d", + avi->reverse_stop_index); + return NULL; + } + avi->current_entry = avi->reverse_start_index = entry->index_nr; + GST_DEBUG_OBJECT (avi, + "reverse playback jump: start idx (%d) and stop idx (%d)", + avi->reverse_start_index, avi->reverse_stop_index); + gst_segment_set_last_stop (&avi->segment, GST_FORMAT_TIME, entry->ts); + for (i = 0; i < avi->num_streams; i++) { + avi->stream[i].last_flow = GST_FLOW_OK; + avi->stream[i].discont = TRUE; + } + return entry; +} + +/* * Read data from one index entry */ static GstFlowReturn @@ -3458,7 +3491,6 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi) avi_stream_context *stream; gst_avi_index_entry *entry; GstBuffer *buf; - gint i; do { /* see if we are at the end */ @@ -3478,24 +3510,9 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi) if (avi->index_entries[avi->reverse_start_index].ts < avi->segment.start) goto eos_reverse_segment; - avi->reverse_stop_index = avi->reverse_start_index; - entry = - gst_avi_demux_index_prev (avi, 0, avi->reverse_stop_index, - GST_AVI_INDEX_ENTRY_FLAG_KEYFRAME); - if (!entry) { - GST_DEBUG_OBJECT (avi, "no valid index entry found index %d", - avi->reverse_stop_index); + if (!(entry = gst_avi_demux_step_reverse (avi))) goto eos; - } - avi->current_entry = avi->reverse_start_index = entry->index_nr; - GST_DEBUG_OBJECT (avi, - "reverse playback jump: start idx (%d) and stop idx (%d)", - avi->reverse_start_index, avi->reverse_stop_index); - gst_segment_set_last_stop (&avi->segment, GST_FORMAT_TIME, entry->ts); - for (i = 0; i < avi->num_streams; i++) { - avi->stream[i].last_flow = GST_FLOW_OK; - avi->stream[i].discont = TRUE; - } + avi->current_entry++; } @@ -3574,15 +3591,34 @@ gst_avi_demux_process_next_entry (GstAviDemux * avi) res = gst_pad_push (stream->pad, buf); - /* combine flows */ - res = gst_avi_demux_combine_flows (avi, stream, res); - /* mark as processed, we increment the frame and byte counters then * leave the while loop and return the GstFlowReturn */ processed = TRUE; GST_DEBUG_OBJECT (avi, "Processed buffer %d: %s", entry->index_nr, gst_flow_get_name (res)); + if (avi->segment.rate < 0 + && entry->ts > avi->segment.stop && res == GST_FLOW_UNEXPECTED) { + /* In reverse playback we can get a GST_FLOW_UNEXPECTED when + * we are at the end of the segment, so we just need to jump + * back to the previous section. + */ + GST_DEBUG_OBJECT (avi, "downstream has reached end of segment"); + + if (!(entry = gst_avi_demux_step_reverse (avi))) + goto eos; + + res = GST_FLOW_OK; + + stream->current_frame = entry->frames_before; + stream->current_byte = entry->bytes_before; + + continue; + } + + /* combine flows */ + res = gst_avi_demux_combine_flows (avi, stream, res); + next: stream->current_frame = entry->frames_before + 1; stream->current_byte = entry->bytes_before + entry->size; |