mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 02:01:12 +00:00
matroskademux: skip buffers before a late keyframe (QoS)
Before, vp8dec had no option but to decode all frames even if some/all of them would be late. With this change, performance when keyframes are frequent is helped a great deal. On my Thinkpad X60s, decoding a 20 s 1080p sunflower encode with keyframes every 10 frames went from taking 42 s with 5 frames shown to 21 s with 15 frames shown (still slow enough to count by hand). When keyframes are more sparse, you will still be able to catch up eventually, but the results won't be as noticable.
This commit is contained in:
parent
f5bca501e5
commit
80926a5596
3 changed files with 68 additions and 1 deletions
|
@ -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, ×tamp);
|
||||
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -545,6 +545,9 @@ typedef struct _GstMatroskaTrackVideoContext {
|
|||
GstMatroskaAspectRatioMode asr_mode;
|
||||
guint32 fourcc;
|
||||
|
||||
/* QoS */
|
||||
GstClockTime earliest_time;
|
||||
|
||||
GstBuffer *dirac_unit;
|
||||
} GstMatroskaTrackVideoContext;
|
||||
|
||||
|
|
Loading…
Reference in a new issue