summaryrefslogtreecommitdiff
path: root/gst/matroska/matroska-demux.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/matroska/matroska-demux.c')
-rw-r--r--gst/matroska/matroska-demux.c65
1 files changed, 64 insertions, 1 deletions
diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c
index a5f551d1d..06a5a69bf 100644
--- a/gst/matroska/matroska-demux.c
+++ b/gst/matroska/matroska-demux.c
@@ -2197,6 +2197,13 @@ gst_matroska_demux_reset_streams (GstMatroskaDemux * demux, GstClockTime time,
context->from_time = GST_CLOCK_TIME_NONE;
if (full)
context->last_flow = GST_FLOW_OK;
+ if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
+ GstMatroskaTrackVideoContext *videocontext =
+ (GstMatroskaTrackVideoContext *) context;
+ GST_OBJECT_LOCK (demux);
+ videocontext->earliest_time = GST_CLOCK_TIME_NONE;
+ GST_OBJECT_UNLOCK (demux);
+ }
}
}
@@ -2496,9 +2503,29 @@ gst_matroska_demux_handle_src_event (GstPad * pad, GstEvent * event)
gst_event_unref (event);
break;
+ case GST_EVENT_QOS:
+ {
+ GstMatroskaTrackContext *context = gst_pad_get_element_private (pad);
+ if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
+ GstMatroskaTrackVideoContext *videocontext =
+ (GstMatroskaTrackVideoContext *) context;
+ gdouble proportion;
+ GstClockTimeDiff diff;
+ GstClockTime timestamp;
+
+ gst_event_parse_qos (event, &proportion, &diff, &timestamp);
+
+ GST_OBJECT_LOCK (demux);
+ videocontext->earliest_time = timestamp + diff;
+ GST_OBJECT_UNLOCK (demux);
+ }
+ res = TRUE;
+ gst_event_unref (event);
+ break;
+ }
+
/* events we don't need to handle */
case GST_EVENT_NAVIGATION:
- case GST_EVENT_QOS:
gst_event_unref (event);
res = FALSE;
break;
@@ -4635,6 +4662,42 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
break;
}
+ /* QoS for video track with an index. the assumption is that
+ index entries point to keyframes, but if that is not true we
+ will instad skip until the next keyframe. */
+ if (GST_CLOCK_TIME_IS_VALID (lace_time) &&
+ stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO &&
+ stream->index_table) {
+ GstMatroskaTrackVideoContext *videocontext =
+ (GstMatroskaTrackVideoContext *) stream;
+ GstClockTime running_time;
+ GstClockTime earliest_time;
+ running_time = gst_segment_to_running_time (&demux->segment,
+ GST_FORMAT_TIME, lace_time);
+ GST_OBJECT_LOCK (demux);
+ earliest_time = videocontext->earliest_time;
+ GST_OBJECT_UNLOCK (demux);
+ if (GST_CLOCK_TIME_IS_VALID (running_time) &&
+ GST_CLOCK_TIME_IS_VALID (earliest_time) &&
+ running_time <= earliest_time) {
+ /* find index entry (keyframe) <= earliest_time */
+ GstMatroskaIndex *entry =
+ gst_util_array_binary_search (stream->index_table->data,
+ stream->index_table->len, sizeof (GstMatroskaIndex),
+ (GCompareDataFunc) gst_matroska_index_seek_find,
+ GST_SEARCH_MODE_BEFORE, &earliest_time, NULL);
+ /* if that entry (keyframe) is after the current the current
+ buffer, we can skip pushing (and thus decoding) all
+ buffers until that keyframe. */
+ if (entry && GST_CLOCK_TIME_IS_VALID (entry->time) &&
+ entry->time > lace_time) {
+ GST_LOG_OBJECT (demux, "Skipping lace before late keyframe");
+ stream->set_discont = TRUE;
+ goto next_lace;
+ }
+ }
+ }
+
sub = gst_buffer_create_sub (buf,
GST_BUFFER_SIZE (buf) - size, lace_size[n]);
GST_DEBUG_OBJECT (demux, "created subbuffer %p", sub);