summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gst/matroska/matroska-demux.c65
-rw-r--r--gst/matroska/matroska-ids.c1
-rw-r--r--gst/matroska/matroska-ids.h3
3 files changed, 68 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);
diff --git a/gst/matroska/matroska-ids.c b/gst/matroska/matroska-ids.c
index 0ee39d31e..5bed5e6dd 100644
--- a/gst/matroska/matroska-ids.c
+++ b/gst/matroska/matroska-ids.c
@@ -56,6 +56,7 @@ gst_matroska_track_init_video_context (GstMatroskaTrackContext ** p_context)
video_context->asr_mode = 0;
video_context->fourcc = 0;
video_context->default_fps = 0.0;
+ video_context->earliest_time = GST_CLOCK_TIME_NONE;
return TRUE;
}
diff --git a/gst/matroska/matroska-ids.h b/gst/matroska/matroska-ids.h
index 085bf8409..16b56010b 100644
--- a/gst/matroska/matroska-ids.h
+++ b/gst/matroska/matroska-ids.h
@@ -545,6 +545,9 @@ typedef struct _GstMatroskaTrackVideoContext {
GstMatroskaAspectRatioMode asr_mode;
guint32 fourcc;
+ /* QoS */
+ GstClockTime earliest_time;
+
GstBuffer *dirac_unit;
} GstMatroskaTrackVideoContext;