diff options
author | Wim Taymans <wim.taymans@collabora.co.uk> | 2009-09-22 18:18:20 +0200 |
---|---|---|
committer | Wim Taymans <wim@metal.(none)> | 2009-09-28 22:16:55 +0200 |
commit | 8aa38308527301b48803823cb9c4db0404ac9cb5 (patch) | |
tree | 213a044fbfe96e7fb86d3cc18ee17ea4a18f0364 | |
parent | 3338f91cfeb1bc2fc109766f15d1fe19e2475216 (diff) |
avi: fix reverse playback
-rw-r--r-- | gst/avi/gstavidemux.c | 86 |
1 files changed, 55 insertions, 31 deletions
diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c index c6ee30bec..94917c59d 100644 --- a/gst/avi/gstavidemux.c +++ b/gst/avi/gstavidemux.c | |||
@@ -3303,7 +3303,7 @@ skipping_done: | |||
3303 | gst_event_unref (avi->seek_event); | 3303 | gst_event_unref (avi->seek_event); |
3304 | avi->seek_event = gst_event_new_new_segment | 3304 | avi->seek_event = gst_event_new_new_segment |
3305 | (FALSE, avi->segment.rate, GST_FORMAT_TIME, | 3305 | (FALSE, avi->segment.rate, GST_FORMAT_TIME, |
3306 | avi->segment.start, stop, avi->segment.start); | 3306 | avi->segment.start, stop, avi->segment.time); |
3307 | 3307 | ||
3308 | /* at this point we know all the streams and we can signal the no more | 3308 | /* at this point we know all the streams and we can signal the no more |
3309 | * pads signal */ | 3309 | * pads signal */ |
@@ -3602,7 +3602,7 @@ skipping_done: | |||
3602 | gst_event_unref (avi->seek_event); | 3602 | gst_event_unref (avi->seek_event); |
3603 | avi->seek_event = gst_event_new_new_segment | 3603 | avi->seek_event = gst_event_new_new_segment |
3604 | (FALSE, avi->segment.rate, GST_FORMAT_TIME, | 3604 | (FALSE, avi->segment.rate, GST_FORMAT_TIME, |
3605 | avi->segment.start, stop, avi->segment.start); | 3605 | avi->segment.start, stop, avi->segment.time); |
3606 | 3606 | ||
3607 | stamp = gst_util_get_timestamp () - stamp; | 3607 | stamp = gst_util_get_timestamp () - stamp; |
3608 | GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "pulling header %" GST_TIME_FORMAT, | 3608 | GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "pulling header %" GST_TIME_FORMAT, |
@@ -3769,9 +3769,11 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment) | |||
3769 | GST_TIME_ARGS (seek_time)); | 3769 | GST_TIME_ARGS (seek_time)); |
3770 | } | 3770 | } |
3771 | 3771 | ||
3772 | /* the seek time is also the last_stop and stream time */ | 3772 | /* the seek time is also the last_stop and stream time when going |
3773 | * forwards */ | ||
3773 | segment->last_stop = seek_time; | 3774 | segment->last_stop = seek_time; |
3774 | segment->time = seek_time; | 3775 | if (segment->rate > 0.0) |
3776 | segment->time = seek_time; | ||
3775 | 3777 | ||
3776 | /* now set DISCONT and align the other streams */ | 3778 | /* now set DISCONT and align the other streams */ |
3777 | for (i = 0; i < avi->num_streams; i++) { | 3779 | for (i = 0; i < avi->num_streams; i++) { |
@@ -3809,6 +3811,7 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event) | |||
3809 | gboolean flush; | 3811 | gboolean flush; |
3810 | gboolean update; | 3812 | gboolean update; |
3811 | GstSegment seeksegment = { 0, }; | 3813 | GstSegment seeksegment = { 0, }; |
3814 | gint i; | ||
3812 | 3815 | ||
3813 | if (event) { | 3816 | if (event) { |
3814 | GST_DEBUG_OBJECT (avi, "doing seek with event"); | 3817 | GST_DEBUG_OBJECT (avi, "doing seek with event"); |
@@ -3845,14 +3848,14 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event) | |||
3845 | flush = flags & GST_SEEK_FLAG_FLUSH; | 3848 | flush = flags & GST_SEEK_FLAG_FLUSH; |
3846 | 3849 | ||
3847 | if (flush) { | 3850 | if (flush) { |
3848 | GstEvent *event = gst_event_new_flush_start (); | 3851 | GstEvent *fevent = gst_event_new_flush_start (); |
3849 | 3852 | ||
3850 | /* for a flushing seek, we send a flush_start on all pads. This will | 3853 | /* for a flushing seek, we send a flush_start on all pads. This will |
3851 | * eventually stop streaming with a WRONG_STATE. We can thus eventually | 3854 | * eventually stop streaming with a WRONG_STATE. We can thus eventually |
3852 | * take the STREAM_LOCK. */ | 3855 | * take the STREAM_LOCK. */ |
3853 | GST_DEBUG_OBJECT (avi, "sending flush start"); | 3856 | GST_DEBUG_OBJECT (avi, "sending flush start"); |
3854 | gst_avi_demux_push_event (avi, gst_event_ref (event)); | 3857 | gst_avi_demux_push_event (avi, gst_event_ref (fevent)); |
3855 | gst_pad_push_event (avi->sinkpad, event); | 3858 | gst_pad_push_event (avi->sinkpad, fevent); |
3856 | } else { | 3859 | } else { |
3857 | /* a non-flushing seek, we PAUSE the task so that we can take the | 3860 | /* a non-flushing seek, we PAUSE the task so that we can take the |
3858 | * STREAM_LOCK */ | 3861 | * STREAM_LOCK */ |
@@ -3878,12 +3881,11 @@ gst_avi_demux_handle_seek (GstAviDemux * avi, GstPad * pad, GstEvent * event) | |||
3878 | gst_avi_demux_do_seek (avi, &seeksegment); | 3881 | gst_avi_demux_do_seek (avi, &seeksegment); |
3879 | 3882 | ||
3880 | if (flush) { | 3883 | if (flush) { |
3881 | GstEvent *event = gst_event_new_flush_stop (); | 3884 | GstEvent *fevent = gst_event_new_flush_stop (); |
3882 | gint i; | ||
3883 | 3885 | ||
3884 | GST_DEBUG_OBJECT (avi, "sending flush stop"); | 3886 | GST_DEBUG_OBJECT (avi, "sending flush stop"); |
3885 | gst_avi_demux_push_event (avi, gst_event_ref (event)); | 3887 | gst_avi_demux_push_event (avi, gst_event_ref (fevent)); |
3886 | gst_pad_push_event (avi->sinkpad, event); | 3888 | gst_pad_push_event (avi->sinkpad, fevent); |
3887 | 3889 | ||
3888 | /* reset the last flow and mark discont, FLUSH is always DISCONT */ | 3890 | /* reset the last flow and mark discont, FLUSH is always DISCONT */ |
3889 | for (i = 0; i < avi->num_streams; i++) { | 3891 | for (i = 0; i < avi->num_streams; i++) { |
@@ -4103,8 +4105,6 @@ gst_avi_demux_advance (GstAviDemux * avi, GstAviStream * stream, | |||
4103 | gst_avi_demux_get_buffer_info (avi, stream, new_entry, | 4105 | gst_avi_demux_get_buffer_info (avi, stream, new_entry, |
4104 | NULL, &stream->current_ts_end, NULL, &stream->current_offset_end); | 4106 | NULL, &stream->current_ts_end, NULL, &stream->current_offset_end); |
4105 | } else { | 4107 | } else { |
4106 | GST_DEBUG_OBJECT (avi, "DISCONT move from %u to %u", old_entry, | ||
4107 | new_entry); | ||
4108 | /* we moved DISCONT, full update */ | 4108 | /* we moved DISCONT, full update */ |
4109 | gst_avi_demux_get_buffer_info (avi, stream, new_entry, | 4109 | gst_avi_demux_get_buffer_info (avi, stream, new_entry, |
4110 | &stream->current_timestamp, &stream->current_ts_end, | 4110 | &stream->current_timestamp, &stream->current_ts_end, |
@@ -4112,6 +4112,12 @@ gst_avi_demux_advance (GstAviDemux * avi, GstAviStream * stream, | |||
4112 | /* and MARK discont for this stream */ | 4112 | /* and MARK discont for this stream */ |
4113 | stream->last_flow = GST_FLOW_OK; | 4113 | stream->last_flow = GST_FLOW_OK; |
4114 | stream->discont = TRUE; | 4114 | stream->discont = TRUE; |
4115 | GST_DEBUG_OBJECT (avi, "Moved from %u to %u, ts %" GST_TIME_FORMAT | ||
4116 | ", ts_end %" GST_TIME_FORMAT ", off %" G_GUINT64_FORMAT | ||
4117 | ", off_end %" G_GUINT64_FORMAT, old_entry, new_entry, | ||
4118 | GST_TIME_ARGS (stream->current_timestamp), | ||
4119 | GST_TIME_ARGS (stream->current_ts_end), stream->current_offset, | ||
4120 | stream->current_offset_end); | ||
4115 | } | 4121 | } |
4116 | } | 4122 | } |
4117 | return ret; | 4123 | return ret; |
@@ -4126,12 +4132,45 @@ eos: | |||
4126 | } | 4132 | } |
4127 | } | 4133 | } |
4128 | 4134 | ||
4135 | /* find the stream with the lowest current position when going forwards or with | ||
4136 | * the highest position when going backwards, this is the stream | ||
4137 | * we should push from next */ | ||
4138 | static gint | ||
4139 | gst_avi_demux_find_next (GstAviDemux * avi, gfloat rate) | ||
4140 | { | ||
4141 | guint64 min_time, max_time; | ||
4142 | guint stream_num, i; | ||
4143 | |||
4144 | max_time = 0; | ||
4145 | min_time = G_MAXUINT64; | ||
4146 | stream_num = -1; | ||
4147 | |||
4148 | for (i = 0; i < avi->num_streams; i++) { | ||
4149 | guint64 position; | ||
4150 | GstAviStream *stream; | ||
4151 | |||
4152 | stream = &avi->stream[i]; | ||
4153 | position = stream->current_timestamp; | ||
4154 | |||
4155 | /* position of -1 is EOS */ | ||
4156 | if (position != -1) { | ||
4157 | if (rate > 0.0 && position < min_time) { | ||
4158 | min_time = position; | ||
4159 | stream_num = i; | ||
4160 | } else if (rate < 0.0 && position >= max_time) { | ||
4161 | max_time = position; | ||
4162 | stream_num = i; | ||
4163 | } | ||
4164 | } | ||
4165 | } | ||
4166 | return stream_num; | ||
4167 | } | ||
4168 | |||
4129 | static GstFlowReturn | 4169 | static GstFlowReturn |
4130 | gst_avi_demux_loop_data (GstAviDemux * avi) | 4170 | gst_avi_demux_loop_data (GstAviDemux * avi) |
4131 | { | 4171 | { |
4132 | GstFlowReturn ret = GST_FLOW_OK; | 4172 | GstFlowReturn ret = GST_FLOW_OK; |
4133 | guint stream_num, i; | 4173 | guint stream_num; |
4134 | guint64 min_time; | ||
4135 | GstAviStream *stream; | 4174 | GstAviStream *stream; |
4136 | gboolean processed = FALSE; | 4175 | gboolean processed = FALSE; |
4137 | GstBuffer *buf; | 4176 | GstBuffer *buf; |
@@ -4142,22 +4181,7 @@ gst_avi_demux_loop_data (GstAviDemux * avi) | |||
4142 | GstAviIndexEntry *entry; | 4181 | GstAviIndexEntry *entry; |
4143 | 4182 | ||
4144 | do { | 4183 | do { |
4145 | min_time = G_MAXUINT64; | 4184 | stream_num = gst_avi_demux_find_next (avi, avi->segment.rate); |
4146 | /* first find the stream with the lowest current position, this is the one | ||
4147 | * we should push from next */ | ||
4148 | stream_num = -1; | ||
4149 | for (i = 0; i < avi->num_streams; i++) { | ||
4150 | guint64 position; | ||
4151 | |||
4152 | stream = &avi->stream[i]; | ||
4153 | position = stream->current_timestamp; | ||
4154 | |||
4155 | /* position of -1 is EOS */ | ||
4156 | if (position != -1 && position < min_time) { | ||
4157 | min_time = position; | ||
4158 | stream_num = i; | ||
4159 | } | ||
4160 | } | ||
4161 | 4185 | ||
4162 | /* all are EOS */ | 4186 | /* all are EOS */ |
4163 | if (G_UNLIKELY (stream_num == -1)) { | 4187 | if (G_UNLIKELY (stream_num == -1)) { |