matroskademux: improve segment handling with non-zero starting timestamp

... as well as related items, such as seeking and position reporting.

https://bugzilla.gnome.org/show_bug.cgi?id=659808
This commit is contained in:
Vincent Penquerc'h 2011-09-21 18:45:42 +01:00 committed by Mark Nauwelaerts
parent 73fac4e5bc
commit be82dd8e3a
2 changed files with 39 additions and 18 deletions

View file

@ -436,6 +436,7 @@ gst_matroska_demux_reset (GstElement * element)
gst_segment_init (&demux->common.segment, GST_FORMAT_TIME); gst_segment_init (&demux->common.segment, GST_FORMAT_TIME);
demux->last_stop_end = GST_CLOCK_TIME_NONE; demux->last_stop_end = GST_CLOCK_TIME_NONE;
demux->seek_block = 0; demux->seek_block = 0;
demux->stream_start_time = GST_CLOCK_TIME_NONE;
demux->common.offset = 0; demux->common.offset = 0;
demux->cluster_time = GST_CLOCK_TIME_NONE; demux->cluster_time = GST_CLOCK_TIME_NONE;
@ -1370,10 +1371,11 @@ gst_matroska_demux_query (GstMatroskaDemux * demux, GstPad * pad,
if (format == GST_FORMAT_TIME) { if (format == GST_FORMAT_TIME) {
GST_OBJECT_LOCK (demux); GST_OBJECT_LOCK (demux);
if (context) if (context)
gst_query_set_position (query, GST_FORMAT_TIME, context->pos); gst_query_set_position (query, GST_FORMAT_TIME,
context->pos - demux->stream_start_time);
else else
gst_query_set_position (query, GST_FORMAT_TIME, gst_query_set_position (query, GST_FORMAT_TIME,
demux->common.segment.last_stop); demux->common.segment.last_stop - demux->stream_start_time);
GST_OBJECT_UNLOCK (demux); GST_OBJECT_UNLOCK (demux);
} else if (format == GST_FORMAT_DEFAULT && context } else if (format == GST_FORMAT_DEFAULT && context
&& context->default_duration) { && context->default_duration) {
@ -1748,9 +1750,15 @@ gst_matroska_demux_search_pos (GstMatroskaDemux * demux, GstClockTime time)
retry: retry:
GST_LOG_OBJECT (demux, GST_LOG_OBJECT (demux,
"opos: %" G_GUINT64_FORMAT ", otime: %" GST_TIME_FORMAT, opos, "opos: %" G_GUINT64_FORMAT ", otime: %" GST_TIME_FORMAT ", %"
GST_TIME_ARGS (otime)); GST_TIME_FORMAT " in stream time (start %" GST_TIME_FORMAT "), time %"
newpos = gst_util_uint64_scale (opos, time, otime) - chunk; GST_TIME_FORMAT, opos, GST_TIME_ARGS (otime),
GST_TIME_ARGS (otime - demux->stream_start_time),
GST_TIME_ARGS (demux->stream_start_time), GST_TIME_ARGS (time));
newpos =
gst_util_uint64_scale (opos - demux->common.ebml_segment_start,
time - demux->stream_start_time,
otime - demux->stream_start_time) - chunk;
if (newpos < 0) if (newpos < 0)
newpos = 0; newpos = 0;
/* favour undershoot */ /* favour undershoot */
@ -1918,6 +1926,14 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
GST_DEBUG_OBJECT (demux, "configuring seek"); GST_DEBUG_OBJECT (demux, "configuring seek");
gst_segment_set_seek (&seeksegment, rate, format, flags, gst_segment_set_seek (&seeksegment, rate, format, flags,
cur_type, cur, stop_type, stop, &update); cur_type, cur, stop_type, stop, &update);
/* compensate for clip start time */
if (GST_CLOCK_TIME_IS_VALID (demux->stream_start_time)) {
seeksegment.last_stop += demux->stream_start_time;
seeksegment.start += demux->stream_start_time;
if (GST_CLOCK_TIME_IS_VALID (seeksegment.stop))
seeksegment.stop += demux->stream_start_time;
/* note that time should stay at indicated position */
}
} }
GST_DEBUG_OBJECT (demux, "New segment %" GST_SEGMENT_FORMAT, &seeksegment); GST_DEBUG_OBJECT (demux, "New segment %" GST_SEGMENT_FORMAT, &seeksegment);
@ -1988,7 +2004,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
GST_TIME_FORMAT, GST_TIME_ARGS (entry->time)); GST_TIME_FORMAT, GST_TIME_ARGS (entry->time));
seeksegment.start = entry->time; seeksegment.start = entry->time;
seeksegment.last_stop = entry->time; seeksegment.last_stop = entry->time;
seeksegment.time = entry->time; seeksegment.time = entry->time - demux->stream_start_time;
} }
if (flush) { if (flush) {
@ -3259,10 +3275,15 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
GST_DEBUG_OBJECT (demux, GST_DEBUG_OBJECT (demux,
"generating segment starting at %" GST_TIME_FORMAT, "generating segment starting at %" GST_TIME_FORMAT,
GST_TIME_ARGS (lace_time)); GST_TIME_ARGS (lace_time));
/* pretend we seeked here */ if (!GST_CLOCK_TIME_IS_VALID (demux->stream_start_time)) {
gst_segment_set_seek (&demux->common.segment, demux->common.segment.rate, demux->stream_start_time = lace_time;
GST_FORMAT_TIME, 0, GST_SEEK_TYPE_SET, lace_time, GST_DEBUG_OBJECT (demux,
GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE, NULL); "Setting stream start time to %" GST_TIME_FORMAT,
GST_TIME_ARGS (lace_time));
}
gst_segment_set_newsegment (&demux->common.segment, FALSE,
demux->common.segment.rate, GST_FORMAT_TIME, lace_time,
GST_CLOCK_TIME_NONE, lace_time - demux->stream_start_time);
/* now convey our segment notion downstream */ /* now convey our segment notion downstream */
gst_matroska_demux_send_event (demux, gst_event_new_new_segment (FALSE, gst_matroska_demux_send_event (demux, gst_event_new_new_segment (FALSE,
demux->common.segment.rate, demux->common.segment.format, demux->common.segment.rate, demux->common.segment.format,
@ -3449,9 +3470,10 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
GST_OBJECT_LOCK (demux); GST_OBJECT_LOCK (demux);
if (demux->common.segment.duration == -1 || if (demux->common.segment.duration == -1 ||
demux->common.segment.duration < lace_time) { demux->common.segment.duration <
lace_time - demux->stream_start_time) {
gst_segment_set_duration (&demux->common.segment, GST_FORMAT_TIME, gst_segment_set_duration (&demux->common.segment, GST_FORMAT_TIME,
last_stop_end); last_stop_end - demux->stream_start_time);
GST_OBJECT_UNLOCK (demux); GST_OBJECT_UNLOCK (demux);
gst_element_post_message (GST_ELEMENT_CAST (demux), gst_element_post_message (GST_ELEMENT_CAST (demux),
gst_message_new_duration (GST_OBJECT_CAST (demux), gst_message_new_duration (GST_OBJECT_CAST (demux),
@ -4106,12 +4128,10 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
demux->first_cluster_offset = demux->common.offset; demux->first_cluster_offset = demux->common.offset;
GST_DEBUG_OBJECT (demux, "signaling no more pads"); GST_DEBUG_OBJECT (demux, "signaling no more pads");
gst_element_no_more_pads (GST_ELEMENT (demux)); gst_element_no_more_pads (GST_ELEMENT (demux));
/* send initial newsegment */ /* send initial newsegment - we wait till we know the first
gst_matroska_demux_send_event (demux, incoming timestamp, so we can properly set the start of
gst_event_new_new_segment (FALSE, 1.0, the segment. */
GST_FORMAT_TIME, 0, demux->need_newsegment = TRUE;
(demux->common.segment.duration >
0) ? demux->common.segment.duration : -1, 0));
} }
demux->cluster_time = GST_CLOCK_TIME_NONE; demux->cluster_time = GST_CLOCK_TIME_NONE;
demux->cluster_offset = demux->common.offset; demux->cluster_offset = demux->common.offset;

View file

@ -71,6 +71,7 @@ typedef struct _GstMatroskaDemux {
/* keeping track of playback position */ /* keeping track of playback position */
gboolean segment_running; gboolean segment_running;
GstClockTime last_stop_end; GstClockTime last_stop_end;
GstClockTime stream_start_time;
GstEvent *close_segment; GstEvent *close_segment;
GstEvent *new_segment; GstEvent *new_segment;