summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2009-09-22 14:44:42 +0200
committerWim Taymans <wim@metal.(none)>2009-09-28 22:16:48 +0200
commitc199b1d039c1f8673829d6465b08de7a537658ca (patch)
tree474caa5ce387998ddb238f08e2494b8b8b10676e
parent0d70fe30a8fad452627e2f6c9402bacc4506bc39 (diff)
avi: more cleanups
Remove some duplicate counters. Be smarter when updateing the current the timestamp and offset in the stream because we can reuse previously calculated values when simply go forward one step. Correctly set metadata on outgoing buffers.
-rw-r--r--gst/avi/gstavidemux.c243
-rw-r--r--gst/avi/gstavidemux.h12
2 files changed, 155 insertions, 100 deletions
diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c
index 7a1f96a85..42d5ce5d1 100644
--- a/gst/avi/gstavidemux.c
+++ b/gst/avi/gstavidemux.c
@@ -448,37 +448,37 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
448 gint64 pos = 0; 448 gint64 pos = 0;
449 449
450 GST_DEBUG ("pos query for stream %d: frames %d, bytes %" G_GUINT64_FORMAT, 450 GST_DEBUG ("pos query for stream %d: frames %d, bytes %" G_GUINT64_FORMAT,
451 stream->num, stream->current_frame, stream->current_byte); 451 stream->num, stream->current_entry, stream->current_total);
452 452
453 if (stream->strh->type == GST_RIFF_FCC_auds) { 453 if (stream->strh->type == GST_RIFF_FCC_auds) {
454 if (stream->is_vbr) { 454 if (stream->is_vbr) {
455 /* VBR */ 455 /* VBR */
456 pos = gst_util_uint64_scale ((gint64) stream->current_frame * 456 pos = gst_util_uint64_scale ((gint64) stream->current_entry *
457 stream->strh->scale, GST_SECOND, (guint64) stream->strh->rate); 457 stream->strh->scale, GST_SECOND, (guint64) stream->strh->rate);
458 GST_DEBUG_OBJECT (avi, "VBR convert frame %u, time %" 458 GST_DEBUG_OBJECT (avi, "VBR convert frame %u, time %"
459 GST_TIME_FORMAT, stream->current_frame, GST_TIME_ARGS (pos)); 459 GST_TIME_FORMAT, stream->current_entry, GST_TIME_ARGS (pos));
460 } else if (stream->strf.auds->av_bps != 0) { 460 } else if (stream->strf.auds->av_bps != 0) {
461 /* CBR */ 461 /* CBR */
462 pos = gst_util_uint64_scale (stream->current_byte, GST_SECOND, 462 pos = gst_util_uint64_scale (stream->current_total, GST_SECOND,
463 (guint64) stream->strf.auds->av_bps); 463 (guint64) stream->strf.auds->av_bps);
464 GST_DEBUG_OBJECT (avi, 464 GST_DEBUG_OBJECT (avi,
465 "CBR convert bytes %" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT, 465 "CBR convert bytes %" G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT,
466 stream->current_byte, GST_TIME_ARGS (pos)); 466 stream->current_total, GST_TIME_ARGS (pos));
467 } else if (stream->idx_n != 0 && stream->total_bytes != 0) { 467 } else if (stream->idx_n != 0 && stream->total_bytes != 0) {
468 /* calculate timestamps based on percentage of length */ 468 /* calculate timestamps based on percentage of length */
469 guint64 xlen = avi->avih->us_frame * 469 guint64 xlen = avi->avih->us_frame *
470 avi->avih->tot_frames * GST_USECOND; 470 avi->avih->tot_frames * GST_USECOND;
471 471
472 if (stream->is_vbr) { 472 if (stream->is_vbr) {
473 pos = gst_util_uint64_scale (xlen, stream->current_frame, 473 pos = gst_util_uint64_scale (xlen, stream->current_entry,
474 stream->idx_n); 474 stream->idx_n);
475 GST_DEBUG_OBJECT (avi, "VBR perc convert frame %u, time %" 475 GST_DEBUG_OBJECT (avi, "VBR perc convert frame %u, time %"
476 GST_TIME_FORMAT, stream->current_frame, GST_TIME_ARGS (pos)); 476 GST_TIME_FORMAT, stream->current_entry, GST_TIME_ARGS (pos));
477 } else { 477 } else {
478 pos = gst_util_uint64_scale (xlen, stream->current_byte, 478 pos = gst_util_uint64_scale (xlen, stream->current_total,
479 stream->total_bytes); 479 stream->total_bytes);
480 GST_DEBUG_OBJECT (avi, "CBR perc convert bytes %" G_GUINT64_FORMAT 480 GST_DEBUG_OBJECT (avi, "CBR perc convert bytes %" G_GUINT64_FORMAT
481 ", time %" GST_TIME_FORMAT, stream->current_byte, 481 ", time %" GST_TIME_FORMAT, stream->current_total,
482 GST_TIME_ARGS (pos)); 482 GST_TIME_ARGS (pos));
483 } 483 }
484 } else { 484 } else {
@@ -487,10 +487,10 @@ gst_avi_demux_handle_src_query (GstPad * pad, GstQuery * query)
487 } 487 }
488 } else { 488 } else {
489 if (stream->strh->rate != 0) { 489 if (stream->strh->rate != 0) {
490 pos = gst_util_uint64_scale ((guint64) stream->current_frame * 490 pos = gst_util_uint64_scale ((guint64) stream->current_entry *
491 stream->strh->scale, GST_SECOND, (guint64) stream->strh->rate); 491 stream->strh->scale, GST_SECOND, (guint64) stream->strh->rate);
492 } else { 492 } else {
493 pos = stream->current_frame * avi->avih->us_frame * GST_USECOND; 493 pos = stream->current_entry * avi->avih->us_frame * GST_USECOND;
494 } 494 }
495 } 495 }
496 if (res) { 496 if (res) {
@@ -1755,8 +1755,8 @@ gst_avi_demux_parse_stream (GstAviDemux * avi, GstBuffer * buf)
1755 stream->total_bytes = 0; 1755 stream->total_bytes = 0;
1756 stream->idx_n = 0; 1756 stream->idx_n = 0;
1757 stream->total_blocks = 0; 1757 stream->total_blocks = 0;
1758 stream->current_frame = 0; 1758 stream->current_entry = 0;
1759 stream->current_byte = 0; 1759 stream->current_total = 0;
1760 gst_pad_set_element_private (pad, stream); 1760 gst_pad_set_element_private (pad, stream);
1761 avi->num_streams++; 1761 avi->num_streams++;
1762 gst_pad_set_caps (pad, caps); 1762 gst_pad_set_caps (pad, caps);
@@ -1975,55 +1975,61 @@ gst_avi_demux_index_for_time (GstAviDemux * avi,
1975 index = entry - stream->index; 1975 index = entry - stream->index;
1976 GST_LOG_OBJECT (avi, "found at %u", index); 1976 GST_LOG_OBJECT (avi, "found at %u", index);
1977 } 1977 }
1978 } else {
1979 GST_LOG_OBJECT (avi, "converted time to index %u", index);
1978 } 1980 }
1979 1981
1980 return index; 1982 return index;
1981} 1983}
1982 1984
1983static void 1985static void
1984gst_avi_demux_get_entry_info (GstAviDemux * avi, GstAviStream * stream, 1986gst_avi_demux_get_buffer_info (GstAviDemux * avi, GstAviStream * stream,
1985 guint entry_n, GstClockTime * timestamp, GstClockTime * duration, 1987 guint entry_n, GstClockTime * timestamp, GstClockTime * ts_end,
1986 guint64 * offset, guint64 * size, gboolean * keyframe) 1988 guint64 * offset, guint64 * offset_end)
1987{ 1989{
1988 GstAviIndexEntry *entry; 1990 GstAviIndexEntry *entry;
1989 GstClockTime next_ts = 0, ts = 0;
1990 1991
1991 entry = &stream->index[entry_n]; 1992 entry = &stream->index[entry_n];
1992 1993
1993 if (stream->is_vbr) { 1994 if (stream->is_vbr) {
1994 /* VBR stream next timestamp */ 1995 /* VBR stream next timestamp */
1995 if (stream->strh->type == GST_RIFF_FCC_auds) { 1996 if (stream->strh->type == GST_RIFF_FCC_auds) {
1996 if (timestamp || duration) 1997 if (timestamp)
1997 ts = avi_stream_convert_frames_to_time_unchecked (stream, entry->total); 1998 *timestamp =
1998 if (duration) 1999 avi_stream_convert_frames_to_time_unchecked (stream, entry->total);
1999 next_ts = avi_stream_convert_frames_to_time_unchecked (stream, 2000 if (ts_end)
2001 *ts_end = avi_stream_convert_frames_to_time_unchecked (stream,
2000 entry->total + entry->size); 2002 entry->total + entry->size);
2001 } else { 2003 } else {
2002 if (timestamp || duration) 2004 if (timestamp)
2003 ts = avi_stream_convert_frames_to_time_unchecked (stream, entry_n); 2005 *timestamp =
2004 if (duration) 2006 avi_stream_convert_frames_to_time_unchecked (stream, entry_n);
2005 next_ts = avi_stream_convert_frames_to_time_unchecked (stream, 2007 if (ts_end)
2008 *ts_end = avi_stream_convert_frames_to_time_unchecked (stream,
2006 entry_n + 1); 2009 entry_n + 1);
2007 } 2010 }
2008 } else { 2011 } else {
2009 /* constant rate stream */ 2012 /* constant rate stream */
2010 if (timestamp || duration) 2013 if (timestamp)
2011 ts = avi_stream_convert_bytes_to_time_unchecked (stream, entry->total); 2014 *timestamp =
2012 if (duration) 2015 avi_stream_convert_bytes_to_time_unchecked (stream, entry->total);
2013 next_ts = avi_stream_convert_bytes_to_time_unchecked (stream, 2016 if (ts_end)
2017 *ts_end = avi_stream_convert_bytes_to_time_unchecked (stream,
2014 entry->total + entry->size); 2018 entry->total + entry->size);
2015 } 2019 }
2016 if (timestamp) 2020 if (stream->strh->type == GST_RIFF_FCC_vids) {
2017 *timestamp = ts; 2021 /* video offsets are the frame number */
2018 if (duration) 2022 if (offset)
2019 *duration = next_ts - ts; 2023 *offset = entry_n;
2020 2024 if (offset_end)
2021 if (offset) 2025 *offset_end = entry_n + 1;
2022 *offset = entry->offset; 2026 } else {
2023 if (size) 2027 /* no offsets for audio */
2024 *size = entry->size; 2028 if (offset)
2025 if (keyframe) 2029 *offset = -1;
2026 *keyframe = ENTRY_IS_KEYFRAME (entry); 2030 if (offset_end)
2031 *offset_end = -1;
2032 }
2027} 2033}
2028 2034
2029 2035
@@ -3853,7 +3859,7 @@ pull_range_failed:
3853 } 3859 }
3854} 3860}
3855 3861
3856/* move a stream to an offset */ 3862/* move a stream to @index */
3857static void 3863static void
3858gst_avi_demux_move_stream (GstAviDemux * avi, GstAviStream * stream, 3864gst_avi_demux_move_stream (GstAviDemux * avi, GstAviStream * stream,
3859 GstSegment * segment, guint index) 3865 GstSegment * segment, guint index)
@@ -3868,6 +3874,8 @@ gst_avi_demux_move_stream (GstAviDemux * avi, GstAviStream * stream,
3868 * are enough decoded frames to fill the segment. */ 3874 * are enough decoded frames to fill the segment. */
3869 next_key = gst_avi_demux_index_next (avi, stream, index, TRUE); 3875 next_key = gst_avi_demux_index_next (avi, stream, index, TRUE);
3870 3876
3877 /* FIXME, we go back to 0, we should look at segment.start. We will however
3878 * stop earlier when the see the timestamp < segment.start */
3871 stream->start_entry = 0; 3879 stream->start_entry = 0;
3872 stream->step_entry = index; 3880 stream->step_entry = index;
3873 stream->current_entry = index; 3881 stream->current_entry = index;
@@ -3881,9 +3889,23 @@ gst_avi_demux_move_stream (GstAviDemux * avi, GstAviStream * stream,
3881 stream->stop_entry = gst_avi_demux_index_last (avi, stream); 3889 stream->stop_entry = gst_avi_demux_index_last (avi, stream);
3882 } 3890 }
3883 if (stream->current_entry != index) { 3891 if (stream->current_entry != index) {
3892 GST_DEBUG_OBJECT (avi, "Move DISCONT from %u to %u",
3893 stream->current_entry, index);
3884 stream->current_entry = index; 3894 stream->current_entry = index;
3885 stream->discont = TRUE; 3895 stream->discont = TRUE;
3886 } 3896 }
3897
3898 /* update the buffer info */
3899 gst_avi_demux_get_buffer_info (avi, stream, index,
3900 &stream->current_timestamp, &stream->current_ts_end,
3901 &stream->current_offset, &stream->current_offset_end);
3902
3903 GST_DEBUG_OBJECT (avi, "Moved to %u, ts %" GST_TIME_FORMAT
3904 ", ts_end %" GST_TIME_FORMAT ", off %" G_GUINT64_FORMAT
3905 ", off_end %" G_GUINT64_FORMAT, index,
3906 GST_TIME_ARGS (stream->current_timestamp),
3907 GST_TIME_ARGS (stream->current_ts_end), stream->current_offset,
3908 stream->current_offset_end);
3887} 3909}
3888 3910
3889/* 3911/*
@@ -3897,26 +3919,23 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment)
3897 guint i, index; 3919 guint i, index;
3898 GstAviStream *stream; 3920 GstAviStream *stream;
3899 GstClockTime timestamp, duration; 3921 GstClockTime timestamp, duration;
3900 gboolean kentry;
3901 3922
3902 seek_time = segment->last_stop; 3923 seek_time = segment->last_stop;
3903 keyframe = !!(segment->flags & GST_SEEK_FLAG_KEY_UNIT); 3924 keyframe = !!(segment->flags & GST_SEEK_FLAG_KEY_UNIT);
3904 3925
3926 GST_DEBUG_OBJECT (avi, "seek to: %" GST_TIME_FORMAT
3927 " keyframe seeking:%d", GST_TIME_ARGS (seek_time), keyframe);
3928
3905 /* FIXME, this code assumes the main stream with keyframes is stream 0, 3929 /* FIXME, this code assumes the main stream with keyframes is stream 0,
3906 * which is mostly correct... */ 3930 * which is mostly correct... */
3907 stream = &avi->stream[0]; 3931 stream = &avi->stream[0];
3908 3932
3909 /* get the entry index for the requested position */ 3933 /* get the entry index for the requested position */
3910 index = gst_avi_demux_index_for_time (avi, stream, seek_time); 3934 index = gst_avi_demux_index_for_time (avi, stream, seek_time);
3911
3912 /* take a look at the entry info */
3913 gst_avi_demux_get_entry_info (avi, stream, index,
3914 NULL, NULL, NULL, NULL, &kentry);
3915
3916 GST_DEBUG_OBJECT (avi, "Got entry %u", index); 3935 GST_DEBUG_OBJECT (avi, "Got entry %u", index);
3917 3936
3918 /* check if we are already on a keyframe */ 3937 /* check if we are already on a keyframe */
3919 if (!kentry) { 3938 if (!ENTRY_IS_KEYFRAME (&stream->index[index])) {
3920 GST_DEBUG_OBJECT (avi, "not keyframe, searching back"); 3939 GST_DEBUG_OBJECT (avi, "not keyframe, searching back");
3921 /* now go to the previous keyframe, this is where we should start 3940 /* now go to the previous keyframe, this is where we should start
3922 * decoding from. */ 3941 * decoding from. */
@@ -3925,8 +3944,8 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment)
3925 } 3944 }
3926 3945
3927 /* take a look at the final entry */ 3946 /* take a look at the final entry */
3928 gst_avi_demux_get_entry_info (avi, stream, index, 3947 gst_avi_demux_get_buffer_info (avi, stream, index,
3929 &timestamp, &duration, NULL, NULL, NULL); 3948 &timestamp, &duration, NULL, NULL);
3930 3949
3931 GST_DEBUG_OBJECT (avi, 3950 GST_DEBUG_OBJECT (avi,
3932 "Got keyframe entry %d [ts:%" GST_TIME_FORMAT 3951 "Got keyframe entry %d [ts:%" GST_TIME_FORMAT
@@ -3939,7 +3958,11 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment)
3939 seek_time = timestamp; 3958 seek_time = timestamp;
3940 } 3959 }
3941 3960
3942 /* move the main stream */ 3961 /* the seek time is also the last_stop and stream time */
3962 segment->last_stop = seek_time;
3963 segment->time = seek_time;
3964
3965 /* move the main stream to this position */
3943 gst_avi_demux_move_stream (avi, stream, segment, index); 3966 gst_avi_demux_move_stream (avi, stream, segment, index);
3944 3967
3945 /* now set DISCONT and align the other streams */ 3968 /* now set DISCONT and align the other streams */
@@ -3953,20 +3976,13 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment)
3953 /* get the entry index for the requested position */ 3976 /* get the entry index for the requested position */
3954 index = gst_avi_demux_index_for_time (avi, ostream, seek_time); 3977 index = gst_avi_demux_index_for_time (avi, ostream, seek_time);
3955 3978
3956 gst_avi_demux_get_entry_info (avi, ostream, index, 3979 if (!ENTRY_IS_KEYFRAME (&ostream->index[index]))
3957 NULL, NULL, NULL, NULL, &kentry);
3958 if (!kentry) {
3959 index = gst_avi_demux_index_prev (avi, ostream, index, TRUE); 3980 index = gst_avi_demux_index_prev (avi, ostream, index, TRUE);
3960 } 3981
3961 gst_avi_demux_move_stream (avi, ostream, segment, index); 3982 gst_avi_demux_move_stream (avi, ostream, segment, index);
3962 } 3983 }
3963 3984 GST_DEBUG_OBJECT (avi, "done seek to: %" GST_TIME_FORMAT,
3964 GST_DEBUG_OBJECT (avi, "seek: %" GST_TIME_FORMAT 3985 GST_TIME_ARGS (seek_time));
3965 " keyframe seeking:%d", GST_TIME_ARGS (seek_time), keyframe);
3966
3967 /* the seek time is also the last_stop and stream time */
3968 segment->last_stop = seek_time;
3969 segment->time = seek_time;
3970 3986
3971 return TRUE; 3987 return TRUE;
3972} 3988}
@@ -4442,14 +4458,14 @@ static GstFlowReturn
4442gst_avi_demux_advance (GstAviDemux * avi, GstAviStream * stream, 4458gst_avi_demux_advance (GstAviDemux * avi, GstAviStream * stream,
4443 GstFlowReturn ret) 4459 GstFlowReturn ret)
4444{ 4460{
4445 guint i; 4461 guint old_entry, new_entry;
4446 4462
4447 /* move to the next entry */ 4463 old_entry = stream->current_entry;
4448 stream->current_entry++; 4464 /* move forwards */
4449 stream->current_frame++; 4465 new_entry = old_entry + 1;
4450 4466
4451 /* see if we reached the end */ 4467 /* see if we reached the end */
4452 if (stream->current_entry >= stream->stop_entry) { 4468 if (new_entry >= stream->stop_entry) {
4453 if (avi->segment.rate < 0.0) { 4469 if (avi->segment.rate < 0.0) {
4454 if (stream->step_entry == stream->start_entry) { 4470 if (stream->step_entry == stream->start_entry) {
4455 /* we stepped all the way to the start, eos */ 4471 /* we stepped all the way to the start, eos */
@@ -4460,31 +4476,52 @@ gst_avi_demux_advance (GstAviDemux * avi, GstAviStream * stream,
4460 stream->stop_entry = stream->step_entry; 4476 stream->stop_entry = stream->step_entry;
4461 stream->step_entry = gst_avi_demux_index_prev (avi, stream, 4477 stream->step_entry = gst_avi_demux_index_prev (avi, stream,
4462 stream->stop_entry, TRUE); 4478 stream->stop_entry, TRUE);
4463 stream->current_entry = stream->step_entry;
4464 4479
4465 GST_DEBUG_OBJECT (avi, 4480 GST_DEBUG_OBJECT (avi,
4466 "reverse playback jump: start %u, step %u, stop %u", 4481 "reverse playback jump: start %u, step %u, stop %u",
4467 stream->start_entry, stream->step_entry, stream->stop_entry); 4482 stream->start_entry, stream->step_entry, stream->stop_entry);
4468 4483
4469 /* mark DISCONT */ 4484 /* and start from the previous keyframe now */
4470 for (i = 0; i < avi->num_streams; i++) { 4485 new_entry = stream->step_entry;
4471 avi->stream[i].last_flow = GST_FLOW_OK;
4472 avi->stream[i].discont = TRUE;
4473 }
4474 } else { 4486 } else {
4475 /* EOS */ 4487 /* EOS */
4476 GST_DEBUG_OBJECT (avi, "forward reached stop %u", stream->stop_entry); 4488 GST_DEBUG_OBJECT (avi, "forward reached stop %u", stream->stop_entry);
4477 goto eos; 4489 goto eos;
4478 } 4490 }
4479 } 4491 }
4492
4493 if (new_entry != old_entry) {
4494 stream->current_entry = new_entry;
4495 stream->current_total = stream->index[new_entry].total;
4496
4497 if (new_entry == old_entry + 1) {
4498 GST_DEBUG_OBJECT (avi, "moved forwards from %u to %u",
4499 old_entry, new_entry);
4500 /* we simply moved one step forwards, reuse current info */
4501 stream->current_timestamp = stream->current_ts_end;
4502 stream->current_offset = stream->current_offset_end;
4503 gst_avi_demux_get_buffer_info (avi, stream, new_entry,
4504 NULL, &stream->current_ts_end, NULL, &stream->current_offset_end);
4505 } else {
4506 GST_DEBUG_OBJECT (avi, "DISCONT move from %u to %u", old_entry,
4507 new_entry);
4508 /* we moved DISCONT, full update */
4509 gst_avi_demux_get_buffer_info (avi, stream, new_entry,
4510 &stream->current_timestamp, &stream->current_ts_end,
4511 &stream->current_offset, &stream->current_offset_end);
4512 /* and MARK discont for this stream */
4513 stream->last_flow = GST_FLOW_OK;
4514 stream->discont = TRUE;
4515 }
4516 }
4480 return ret; 4517 return ret;
4481 4518
4482 /* ERROR */ 4519 /* ERROR */
4483eos: 4520eos:
4484 { 4521 {
4485 GST_DEBUG_OBJECT (avi, "we are EOS"); 4522 GST_DEBUG_OBJECT (avi, "we are EOS");
4486 /* setting current_time to -1 marks EOS */ 4523 /* setting current_timestamp to -1 marks EOS */
4487 stream->current_time = -1; 4524 stream->current_timestamp = -1;
4488 return GST_FLOW_UNEXPECTED; 4525 return GST_FLOW_UNEXPECTED;
4489 } 4526 }
4490} 4527}
@@ -4493,25 +4530,27 @@ static GstFlowReturn
4493gst_avi_demux_loop_data (GstAviDemux * avi) 4530gst_avi_demux_loop_data (GstAviDemux * avi)
4494{ 4531{
4495 GstFlowReturn ret = GST_FLOW_OK; 4532 GstFlowReturn ret = GST_FLOW_OK;
4496 guint64 min_time;
4497 guint stream_num, i; 4533 guint stream_num, i;
4534 guint64 min_time;
4498 GstAviStream *stream; 4535 GstAviStream *stream;
4499 gboolean processed = FALSE; 4536 gboolean processed = FALSE;
4500 GstBuffer *buf; 4537 GstBuffer *buf;
4501 guint64 offset, size; 4538 guint64 offset, size;
4502 GstClockTime timestamp, duration; 4539 GstClockTime timestamp, duration;
4540 guint64 out_offset, out_offset_end;
4503 gboolean keyframe; 4541 gboolean keyframe;
4542 GstAviIndexEntry *entry;
4504 4543
4505 do { 4544 do {
4545 min_time = G_MAXUINT64;
4506 /* first find the stream with the lowest current position, this is the one 4546 /* first find the stream with the lowest current position, this is the one
4507 * we should push from next */ 4547 * we should push from next */
4508 min_time = G_MAXUINT64;
4509 stream_num = -1; 4548 stream_num = -1;
4510 for (i = 0; i < avi->num_streams; i++) { 4549 for (i = 0; i < avi->num_streams; i++) {
4511 guint64 position; 4550 guint64 position;
4512 4551
4513 stream = &avi->stream[i]; 4552 stream = &avi->stream[i];
4514 position = stream->current_time; 4553 position = stream->current_timestamp;
4515 4554
4516 /* position of -1 is EOS */ 4555 /* position of -1 is EOS */
4517 if (position != -1 && position < min_time) { 4556 if (position != -1 && position < min_time) {
@@ -4537,20 +4576,27 @@ gst_avi_demux_loop_data (GstAviDemux * avi)
4537 } 4576 }
4538 4577
4539 /* get the timing info for the entry */ 4578 /* get the timing info for the entry */
4540 gst_avi_demux_get_entry_info (avi, stream, stream->current_entry, 4579 timestamp = stream->current_timestamp;
4541 &timestamp, &duration, &offset, &size, &keyframe); 4580 duration = stream->current_ts_end - timestamp;
4581 out_offset = stream->current_offset;
4582 out_offset_end = stream->current_offset_end;
4583
4584 /* get the entry data info */
4585 entry = &stream->index[stream->current_entry];
4586 offset = entry->offset;
4587 size = entry->size;
4588 keyframe = ENTRY_IS_KEYFRAME (entry);
4542 4589
4543 /* skip empty entries */ 4590 /* skip empty entries */
4544 if (size == 0) { 4591 if (size == 0) {
4545 GST_DEBUG_OBJECT (avi, "Skipping entry %d (%d, %p)", 4592 GST_DEBUG_OBJECT (avi, "Skipping entry %u (%u, %p)",
4546 stream->current_entry, size, stream->pad); 4593 stream->current_entry, size, stream->pad);
4547 goto next; 4594 goto next;
4548 } 4595 }
4549 4596
4550 if (avi->segment.rate > 0.0) { 4597 if (avi->segment.rate > 0.0) {
4551 /* only check this for fowards playback for now */ 4598 /* only check this for fowards playback for now */
4552 if (keyframe && GST_CLOCK_TIME_IS_VALID (timestamp) 4599 if (keyframe && GST_CLOCK_TIME_IS_VALID (avi->segment.stop)
4553 && GST_CLOCK_TIME_IS_VALID (avi->segment.stop)
4554 && (timestamp > avi->segment.stop)) { 4600 && (timestamp > avi->segment.stop)) {
4555 goto eos_stop; 4601 goto eos_stop;
4556 } 4602 }
@@ -4580,16 +4626,17 @@ gst_avi_demux_loop_data (GstAviDemux * avi)
4580 4626
4581 GST_BUFFER_TIMESTAMP (buf) = timestamp; 4627 GST_BUFFER_TIMESTAMP (buf) = timestamp;
4582 GST_BUFFER_DURATION (buf) = duration; 4628 GST_BUFFER_DURATION (buf) = duration;
4583 GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE; 4629 GST_BUFFER_OFFSET (buf) = out_offset;
4584 GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; 4630 GST_BUFFER_OFFSET_END (buf) = out_offset_end;
4585 4631
4586 gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad)); 4632 gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad));
4587 4633
4588 GST_DEBUG_OBJECT (avi, "Pushing buffer of size %d, offset %" 4634 GST_DEBUG_OBJECT (avi, "Pushing buffer of size %u, ts %"
4589 G_GUINT64_FORMAT " and time %" 4635 GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", off %" G_GUINT64_FORMAT
4590 GST_TIME_FORMAT " on pad %s", 4636 ", off_end %" G_GUINT64_FORMAT " on pad %s",
4591 GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf), 4637 GST_BUFFER_SIZE (buf), GST_TIME_ARGS (timestamp),
4592 GST_TIME_ARGS (timestamp), GST_PAD_NAME (stream->pad)); 4638 GST_TIME_ARGS (duration), GST_BUFFER_OFFSET (buf),
4639 GST_BUFFER_OFFSET_END (buf), GST_PAD_NAME (stream->pad));
4593 4640
4594 /* update current position in the segment */ 4641 /* update current position in the segment */
4595 gst_segment_set_last_stop (&avi->segment, GST_FORMAT_TIME, timestamp); 4642 gst_segment_set_last_stop (&avi->segment, GST_FORMAT_TIME, timestamp);
@@ -4605,7 +4652,7 @@ gst_avi_demux_loop_data (GstAviDemux * avi)
4605 /* mark as processed, we increment the frame and byte counters then 4652 /* mark as processed, we increment the frame and byte counters then
4606 * leave the while loop and return the GstFlowReturn */ 4653 * leave the while loop and return the GstFlowReturn */
4607 processed = TRUE; 4654 processed = TRUE;
4608 GST_DEBUG_OBJECT (avi, "Processed buffer %d: %s", stream->current_entry, 4655 GST_DEBUG_OBJECT (avi, "Processed buffer %u: %s", stream->current_entry,
4609 gst_flow_get_name (ret)); 4656 gst_flow_get_name (ret));
4610 4657
4611 if (avi->segment.rate < 0) { 4658 if (avi->segment.rate < 0) {
@@ -4618,6 +4665,7 @@ gst_avi_demux_loop_data (GstAviDemux * avi)
4618 } 4665 }
4619 } 4666 }
4620 next: 4667 next:
4668 /* move to next item */
4621 ret = gst_avi_demux_advance (avi, stream, ret); 4669 ret = gst_avi_demux_advance (avi, stream, ret);
4622 4670
4623 /* combine flows */ 4671 /* combine flows */
@@ -4791,8 +4839,8 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
4791 if (G_UNLIKELY (format != GST_FORMAT_TIME)) 4839 if (G_UNLIKELY (format != GST_FORMAT_TIME))
4792 goto wrong_format; 4840 goto wrong_format;
4793 4841
4794 stream->current_frame++; 4842 stream->current_entry++;
4795 stream->current_byte += size; 4843 stream->current_total += size;
4796 4844
4797 /* invert the picture if needed */ 4845 /* invert the picture if needed */
4798 buf = gst_avi_demux_invert (stream, buf); 4846 buf = gst_avi_demux_invert (stream, buf);
@@ -4803,10 +4851,13 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
4803 4851
4804 GST_BUFFER_TIMESTAMP (buf) = next_ts; 4852 GST_BUFFER_TIMESTAMP (buf) = next_ts;
4805 GST_BUFFER_DURATION (buf) = dur_ts - next_ts; 4853 GST_BUFFER_DURATION (buf) = dur_ts - next_ts;
4806 if (stream->strh->type == GST_RIFF_FCC_vids) 4854 if (stream->strh->type == GST_RIFF_FCC_vids) {
4807 GST_BUFFER_OFFSET (buf) = stream->current_frame - 1; 4855 GST_BUFFER_OFFSET (buf) = stream->current_entry - 1;
4808 else 4856 GST_BUFFER_OFFSET_END (buf) = stream->current_entry;
4857 } else {
4809 GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE; 4858 GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE;
4859 GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE;
4860 }
4810 4861
4811 gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad)); 4862 gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad));
4812 GST_DEBUG_OBJECT (avi, 4863 GST_DEBUG_OBJECT (avi,
diff --git a/gst/avi/gstavidemux.h b/gst/avi/gstavidemux.h
index 93fb432ab..ff4235ff9 100644
--- a/gst/avi/gstavidemux.h
+++ b/gst/avi/gstavidemux.h
@@ -83,11 +83,15 @@ typedef struct {
83 guint start_entry; 83 guint start_entry;
84 guint step_entry; 84 guint step_entry;
85 guint stop_entry; 85 guint stop_entry;
86 /* current position (byte, frame, time) and other status vars */ 86
87 /* current index entry */
87 guint current_entry; 88 guint current_entry;
88 guint current_frame; 89 /* position (byte, frame, time) for current_entry */
89 guint64 current_byte; 90 guint current_total;
90 guint64 current_time; 91 GstClockTime current_timestamp;
92 GstClockTime current_ts_end;
93 guint64 current_offset;
94 guint64 current_offset_end;
91 95
92 GstFlowReturn last_flow; 96 GstFlowReturn last_flow;
93 gboolean discont; 97 gboolean discont;