summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2009-09-22 18:18:20 +0200
committerWim Taymans <wim@metal.(none)>2009-09-28 22:16:55 +0200
commit8aa38308527301b48803823cb9c4db0404ac9cb5 (patch)
tree213a044fbfe96e7fb86d3cc18ee17ea4a18f0364
parent3338f91cfeb1bc2fc109766f15d1fe19e2475216 (diff)
avi: fix reverse playback
-rw-r--r--gst/avi/gstavidemux.c86
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 */
4138static gint
4139gst_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
4129static GstFlowReturn 4169static GstFlowReturn
4130gst_avi_demux_loop_data (GstAviDemux * avi) 4170gst_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)) {