summaryrefslogtreecommitdiff
path: root/gst/avi/gstavidemux.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/avi/gstavidemux.c')
-rw-r--r--gst/avi/gstavidemux.c243
1 files changed, 147 insertions, 96 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,