From dd23397b4f5e90a615f1745b8924c3306fcca931 Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Thu, 21 Jan 2010 11:55:15 +0100 Subject: [PATCH] avidemux: Drop video frames up to the desired keyframe after a seek The audio packets in AVI are generally muxed ~0.5s before the corresponding video packet. This changes causes downstream to only receive packets with roughly corresponding timestamps. --- gst/avi/gstavidemux.c | 106 +++++++++++++++++++++++++++++--------------------- gst/avi/gstavidemux.h | 2 + 2 files changed, 63 insertions(+), 45 deletions(-) diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c index 9758861..b87ee6c 100644 --- a/gst/avi/gstavidemux.c +++ b/gst/avi/gstavidemux.c @@ -4191,7 +4191,7 @@ avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad, GstEvent * event) /* re-use cur to be the timestamp of the seek as it _will_ be */ cur = stream->current_timestamp; - min_offset = stream->index[index].offset; + min_offset = avi->seek_kf_offset = stream->index[index].offset; GST_DEBUG_OBJECT (avi, "Seek to: ts %" GST_TIME_FORMAT " (on str %u, idx %u, offset %" @@ -4838,15 +4838,28 @@ gst_avi_demux_stream_data (GstAviDemux * avi) } else { GstAviStream *stream; GstClockTime next_ts = 0; - GstBuffer *buf; + GstBuffer *buf = NULL; guint64 offset; + gboolean saw_desired_kf = stream_nr != avi->main_stream + || avi->offset >= avi->seek_kf_offset; - gst_adapter_flush (avi->adapter, 8); + if (stream_nr == avi->main_stream && avi->offset == avi->seek_kf_offset) { + GST_DEBUG_OBJECT (avi, "Desired keyframe reached"); + avi->seek_kf_offset = 0; + } + + if (saw_desired_kf) { + gst_adapter_flush (avi->adapter, 8); + /* get buffer */ + buf = gst_adapter_take_buffer (avi->adapter, GST_ROUND_UP_2 (size)); + /* patch the size */ + GST_BUFFER_SIZE (buf) = size; + } else { + GST_DEBUG_OBJECT (avi, + "Desired keyframe not yet reached, flushing chunk"); + gst_adapter_flush (avi->adapter, 8 + GST_ROUND_UP_2 (size)); + } - /* get buffer */ - buf = gst_adapter_take_buffer (avi->adapter, GST_ROUND_UP_2 (size)); - /* patch the size */ - GST_BUFFER_SIZE (buf) = size; offset = avi->offset; avi->offset += 8 + GST_ROUND_UP_2 (size); @@ -4862,10 +4875,9 @@ gst_avi_demux_stream_data (GstAviDemux * avi) if (G_UNLIKELY (!stream->pad)) { GST_WARNING_OBJECT (avi, "no pad for stream ID %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (tag)); - gst_buffer_unref (buf); + if (buf) + gst_buffer_unref (buf); } else { - GstClockTime dur_ts = 0; - /* get time of this buffer */ gst_pad_query_position (stream->pad, &format, (gint64 *) & next_ts); if (G_UNLIKELY (format != GST_FORMAT_TIME)) @@ -4877,47 +4889,51 @@ gst_avi_demux_stream_data (GstAviDemux * avi) stream->current_entry++; stream->current_total += size; - /* invert the picture if needed */ - buf = gst_avi_demux_invert (stream, buf); + /* update current position in the segment */ + gst_segment_set_last_stop (&avi->segment, GST_FORMAT_TIME, next_ts); - gst_pad_query_position (stream->pad, &format, (gint64 *) & dur_ts); - if (G_UNLIKELY (format != GST_FORMAT_TIME)) - goto wrong_format; + if (saw_desired_kf && buf) { + GstClockTime dur_ts = 0; - GST_BUFFER_TIMESTAMP (buf) = next_ts; - GST_BUFFER_DURATION (buf) = dur_ts - next_ts; - if (stream->strh->type == GST_RIFF_FCC_vids) { - GST_BUFFER_OFFSET (buf) = stream->current_entry - 1; - GST_BUFFER_OFFSET_END (buf) = stream->current_entry; - } else { - GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE; - GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; - } + /* invert the picture if needed */ + buf = gst_avi_demux_invert (stream, buf); - gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad)); - GST_DEBUG_OBJECT (avi, - "Pushing buffer with time=%" GST_TIME_FORMAT ", duration %" - GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT - " and size %d over pad %s", GST_TIME_ARGS (next_ts), - GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf), - size, GST_PAD_NAME (stream->pad)); + gst_pad_query_position (stream->pad, &format, (gint64 *) & dur_ts); + if (G_UNLIKELY (format != GST_FORMAT_TIME)) + goto wrong_format; - /* update current position in the segment */ - gst_segment_set_last_stop (&avi->segment, GST_FORMAT_TIME, next_ts); + GST_BUFFER_TIMESTAMP (buf) = next_ts; + GST_BUFFER_DURATION (buf) = dur_ts - next_ts; + if (stream->strh->type == GST_RIFF_FCC_vids) { + GST_BUFFER_OFFSET (buf) = stream->current_entry - 1; + GST_BUFFER_OFFSET_END (buf) = stream->current_entry; + } else { + GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; + } - /* mark discont when pending */ - if (G_UNLIKELY (stream->discont)) { - GST_DEBUG_OBJECT (avi, "Setting DISCONT"); - GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); - stream->discont = FALSE; - } - res = gst_pad_push (stream->pad, buf); + gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad)); + GST_DEBUG_OBJECT (avi, + "Pushing buffer with time=%" GST_TIME_FORMAT ", duration %" + GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT + " and size %d over pad %s", GST_TIME_ARGS (next_ts), + GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), + GST_BUFFER_OFFSET (buf), size, GST_PAD_NAME (stream->pad)); + + /* mark discont when pending */ + if (G_UNLIKELY (stream->discont)) { + GST_DEBUG_OBJECT (avi, "Setting DISCONT"); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); + stream->discont = FALSE; + } + res = gst_pad_push (stream->pad, buf); - /* combine flows */ - res = gst_avi_demux_combine_flows (avi, stream, res); - if (G_UNLIKELY (res != GST_FLOW_OK)) { - GST_DEBUG ("Push failed; %s", gst_flow_get_name (res)); - return res; + /* combine flows */ + res = gst_avi_demux_combine_flows (avi, stream, res); + if (G_UNLIKELY (res != GST_FLOW_OK)) { + GST_DEBUG ("Push failed; %s", gst_flow_get_name (res)); + return res; + } } } } diff --git a/gst/avi/gstavidemux.h b/gst/avi/gstavidemux.h index c70ac28..8216d9f 100644 --- a/gst/avi/gstavidemux.h +++ b/gst/avi/gstavidemux.h @@ -199,6 +199,8 @@ typedef struct _GstAviDemux { guint odml_stream; guint odml_subidx; guint64 *odml_subidxs; + + guint64 seek_kf_offset; /* offset of the keyframe to which we want to seek */ } GstAviDemux; typedef struct _GstAviDemuxClass { -- 2.7.4