mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
gst/asfdemux/: Seeking improvements: honour the KEY_UNIT seek flag; after a seek, only send data from the keyframe ri...
Original commit message from CVS: * gst/asfdemux/asfpacket.c: (gst_asf_payload_queue_for_stream): * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_seek_index_lookup), (gst_asf_demux_handle_seek_event), (gst_asf_demux_push_complete_payloads): Seeking improvements: honour the KEY_UNIT seek flag; after a seek, only send data from the keyframe right before the new segment start to make sure the decoder doesn't have to decode more than absolutely necessary.
This commit is contained in:
parent
b46ece6980
commit
279b2b0290
3 changed files with 88 additions and 3 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
|||
2007-05-01 Tim-Philipp Müller <tim at centricular dot net>
|
||||
|
||||
* gst/asfdemux/asfpacket.c: (gst_asf_payload_queue_for_stream):
|
||||
* gst/asfdemux/gstasfdemux.c: (gst_asf_demux_seek_index_lookup),
|
||||
(gst_asf_demux_handle_seek_event),
|
||||
(gst_asf_demux_push_complete_payloads):
|
||||
Seeking improvements: honour the KEY_UNIT seek flag; after a seek, only
|
||||
send data from the keyframe right before the new segment start to
|
||||
make sure the decoder doesn't have to decode more than absolutely
|
||||
necessary.
|
||||
|
||||
2007-04-30 Tim-Philipp Müller <tim at centricular dot net>
|
||||
|
||||
* gst/asfdemux/asfheaders.c:
|
||||
|
|
|
@ -142,6 +142,31 @@ gst_asf_payload_queue_for_stream (GstASFDemux * demux, AsfPayload * payload,
|
|||
GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DISCONT);
|
||||
}
|
||||
|
||||
/* If we're about to queue a key frame that is before the segment start, we
|
||||
* can ditch any previously queued payloads (which would also be before the
|
||||
* segment start). This makes sure the decoder doesn't decode more than
|
||||
* absolutely necessary after a seek (we don't push out payloads that are
|
||||
* before the segment start until we have at least one that falls within the
|
||||
* segment) */
|
||||
if (GST_CLOCK_TIME_IS_VALID (payload->ts) &&
|
||||
payload->ts < demux->segment.start && payload->keyframe) {
|
||||
GST_DEBUG_OBJECT (demux, "Queueing keyframe before segment start, removing"
|
||||
" %u previously-queued payloads, which would be out of segment too and"
|
||||
" hence don't have to be decoded", stream->payloads->len);
|
||||
while (stream->payloads->len > 0) {
|
||||
AsfPayload *last;
|
||||
guint idx_last;
|
||||
|
||||
idx_last = stream->payloads->len - 1;
|
||||
last = &g_array_index (stream->payloads, AsfPayload, idx_last);
|
||||
gst_buffer_replace (&last->buf, NULL);
|
||||
g_array_remove_index (stream->payloads, idx_last);
|
||||
}
|
||||
|
||||
/* Mark discontinuity (should be done via stream->discont anyway though) */
|
||||
GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DISCONT);
|
||||
}
|
||||
|
||||
g_array_append_vals (stream->payloads, payload, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -336,22 +336,40 @@ gst_asf_demux_sink_event (GstPad * pad, GstEvent * event)
|
|||
|
||||
static gboolean
|
||||
gst_asf_demux_seek_index_lookup (GstASFDemux * demux, guint * packet,
|
||||
GstClockTime seek_time)
|
||||
GstClockTime seek_time, GstClockTime * p_idx_time)
|
||||
{
|
||||
GstClockTime idx_time;
|
||||
guint idx;
|
||||
|
||||
if (demux->sidx_num_entries == 0 || demux->sidx_interval == 0)
|
||||
return FALSE;
|
||||
|
||||
idx = (guint) (seek_time / demux->sidx_interval);
|
||||
|
||||
/* FIXME: seek beyond end of file should result in immediate EOS from
|
||||
* streaming thread instead of a failed seek */
|
||||
if (idx >= demux->sidx_num_entries)
|
||||
return FALSE;
|
||||
|
||||
*packet = demux->sidx_entries[idx];
|
||||
|
||||
/* so we get closer to the actual time of the packet ... actually, let's not
|
||||
* do this, since we throw away superfluous payloads before the seek position
|
||||
* anyway; this way, our key unit seek 'snap resolution' is a bit better
|
||||
* (ie. same as index resolution) */
|
||||
/*
|
||||
while (idx > 0 && demux->sidx_entries[idx-1] == demux->sidx_entries[idx])
|
||||
--idx;
|
||||
*/
|
||||
|
||||
idx_time = demux->sidx_interval * idx;
|
||||
|
||||
GST_DEBUG_OBJECT (demux, "%" GST_TIME_FORMAT " => packet %u at %"
|
||||
GST_TIME_FORMAT, GST_TIME_ARGS (seek_time), *packet,
|
||||
GST_TIME_ARGS (demux->sidx_interval * idx));
|
||||
GST_TIME_ARGS (idx_time));
|
||||
|
||||
if (p_idx_time)
|
||||
*p_idx_time = idx_time;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -389,6 +407,7 @@ gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * demux)
|
|||
static gboolean
|
||||
gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
|
||||
{
|
||||
GstClockTime idx_time;
|
||||
GstSegment segment;
|
||||
GstSeekFlags flags;
|
||||
GstSeekType cur_type, stop_type;
|
||||
|
@ -467,7 +486,7 @@ gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
|
|||
|
||||
/* FIXME: should check the KEY_UNIT flag; need to adjust last_stop to
|
||||
* real start of data and segment_start to indexed time for key unit seek*/
|
||||
if (!gst_asf_demux_seek_index_lookup (demux, &packet, seek_time)) {
|
||||
if (!gst_asf_demux_seek_index_lookup (demux, &packet, seek_time, &idx_time)) {
|
||||
/* Hackety hack, this sucks. We just seek to an earlier position
|
||||
* and let the sinks throw away the stuff before the segment start */
|
||||
if (flush && (accurate || keyunit_sync)) {
|
||||
|
@ -481,6 +500,15 @@ gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
|
|||
|
||||
if (packet > demux->num_packets)
|
||||
packet = demux->num_packets;
|
||||
} else {
|
||||
if (keyunit_sync) {
|
||||
GST_DEBUG_OBJECT (demux, "key unit seek, adjust seek_time = %"
|
||||
GST_TIME_FORMAT " to index_time = %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (seek_time), GST_TIME_ARGS (idx_time));
|
||||
segment.start = idx_time;
|
||||
segment.last_stop = idx_time;
|
||||
segment.time = idx_time;
|
||||
}
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (demux, "seeking to packet %u", packet);
|
||||
|
@ -945,6 +973,27 @@ gst_asf_demux_push_complete_payloads (GstASFDemux * demux)
|
|||
AsfStream *stream;
|
||||
|
||||
stream = &demux->stream[i];
|
||||
|
||||
/* Don't push any data until we have at least one payload that falls within
|
||||
* the current segment. This way we can remove out-of-segment payloads that
|
||||
* don't need to be decoded after a seek, sending only data from the
|
||||
* keyframe directly before our segment start */
|
||||
if (stream->payloads->len > 0) {
|
||||
AsfPayload *payload;
|
||||
guint last_idx;
|
||||
|
||||
last_idx = stream->payloads->len - 1;
|
||||
payload = &g_array_index (stream->payloads, AsfPayload, last_idx);
|
||||
if (GST_CLOCK_TIME_IS_VALID (payload->ts) &&
|
||||
payload->ts < demux->segment.start) {
|
||||
GST_DEBUG_OBJECT (stream->pad, "Last queued payload has timestamp %"
|
||||
GST_TIME_FORMAT " which is before our segment start %"
|
||||
GST_TIME_FORMAT ", not pushing yet", GST_TIME_ARGS (payload->ts),
|
||||
GST_TIME_ARGS (demux->segment.start));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
while (stream->payloads->len > 0) {
|
||||
AsfPayload *payload;
|
||||
|
||||
|
|
Loading…
Reference in a new issue