summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-09-16 00:20:19 +0200
committerwm4 <wm4@nowhere>2013-09-16 00:46:14 +0200
commit4a3ceac2b5cbe784355caac4140e309139cbc242 (patch)
treef49ef1c8f006f9e9031bea6f90ad65c7cd0b44e9 /demux
parent4f400d2b855c63f9793dc5447d35c10f9be354bb (diff)
downloadmpv-4a3ceac2b5cbe784355caac4140e309139cbc242.tar.bz2
mpv-4a3ceac2b5cbe784355caac4140e309139cbc242.tar.xz
demux_mkv: don't add too many subtitle packets during seeking
In insane files with a very huge number of subtitle events, and if the --demuxer-mkv-subtitle-preroll option is given, seeking can still overflow the packet queue. Normally, the subtitle_preroll variable specifies the maximum number of packets that can be added. But once this number is reached, the normal seeking behavior is enabled, which will add all subtitle packets with the right timestamps to the packet queue. At this point the next video keyframe can still be quite far away, with enough subtitle packets on the way to overflow the packet queue. Fix this by always setting an upper limit of subtitle packets read during seeking. This should provide additional robustness even if the preroll option is not used. This means that even with normal seeking, at most 500 subtitle packets are demuxed. Packets after that are discarded. One slightly questionable aspect of this commit is that subtitle_preroll is never reset in audio-only mode, but that is probably ok.
Diffstat (limited to 'demux')
-rw-r--r--demux/demux_mkv.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index cf9818d74c..03ffc84844 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -197,7 +197,8 @@ typedef struct mkv_demuxer {
#define RAPROPERTIES5_SIZE 70
// Maximum number of subtitle packets that are accepted for pre-roll.
-#define NUM_SUB_PREROLL_PACKETS 100
+// (Subtitle packets added before first A/V keyframe packet is found with seek.)
+#define NUM_SUB_PREROLL_PACKETS 500
/**
* \brief ensures there is space for at least one additional element
@@ -2292,9 +2293,16 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info)
if (mkv_d->v_skip_to_keyframe)
use_this_block = 0;
} else if (track->type == MATROSKA_TRACK_SUBTITLE) {
- if (!use_this_block && mkv_d->subtitle_preroll) {
- mkv_d->subtitle_preroll--;
+ if (!use_this_block && mkv_d->subtitle_preroll)
use_this_block = 1;
+ if (use_this_block) {
+ if (mkv_d->subtitle_preroll) {
+ mkv_d->subtitle_preroll--;
+ } else {
+ // This could overflow the demuxer queue.
+ if (mkv_d->a_skip_to_keyframe || mkv_d->v_skip_to_keyframe)
+ use_this_block = 0;
+ }
}
if (use_this_block) {
if (laces > 1) {
@@ -2586,7 +2594,7 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id,
if (index) { /* We've found an entry. */
uint64_t seek_pos = index->filepos;
- if (mkv_d->subtitle_preroll) {
+ if (flags & SEEK_SUBPREROLL) {
uint64_t prev_target = 0;
for (int i = 0; i < mkv_d->num_indexes; i++) {
if (seek_id < 0 || mkv_d->indexes[i].tnum == seek_id) {
@@ -2622,10 +2630,9 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs, int flags)
a_tnum = track->tnum;
}
}
- mkv_d->subtitle_preroll = 0;
- if ((flags & SEEK_SUBPREROLL) && st_active[STREAM_SUB] &&
- st_active[STREAM_VIDEO])
- mkv_d->subtitle_preroll = NUM_SUB_PREROLL_PACKETS;
+ mkv_d->subtitle_preroll = NUM_SUB_PREROLL_PACKETS;
+ if (!st_active[STREAM_SUB] || !st_active[STREAM_VIDEO])
+ flags &= ~SEEK_SUBPREROLL;
if (!(flags & (SEEK_BACKWARD | SEEK_FORWARD))) {
if (flags & SEEK_ABSOLUTE || rel_seek_secs < 0)
flags |= SEEK_BACKWARD;
@@ -2654,14 +2661,13 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs, int flags)
if (!index)
stream_seek(demuxer->stream, old_pos);
- if (st_active[STREAM_VIDEO])
- mkv_d->v_skip_to_keyframe = 1;
+ mkv_d->v_skip_to_keyframe = st_active[STREAM_VIDEO];
+ mkv_d->a_skip_to_keyframe = st_active[STREAM_AUDIO];
if (flags & SEEK_FORWARD)
mkv_d->skip_to_timecode = target_timecode;
else
mkv_d->skip_to_timecode = index ? index->timecode * mkv_d->tc_scale
: 0;
- mkv_d->a_skip_to_keyframe = 1;
demux_mkv_fill_buffer(demuxer);
} else if ((demuxer->movi_end <= 0) || !(flags & SEEK_ABSOLUTE))
@@ -2697,10 +2703,9 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs, int flags)
mkv_d->cluster_end = 0;
stream_seek(s, index->filepos);
- if (st_active[STREAM_VIDEO])
- mkv_d->v_skip_to_keyframe = 1;
+ mkv_d->v_skip_to_keyframe = st_active[STREAM_VIDEO];
+ mkv_d->a_skip_to_keyframe = st_active[STREAM_AUDIO];
mkv_d->skip_to_timecode = index->timecode * mkv_d->tc_scale;
- mkv_d->a_skip_to_keyframe = 1;
demux_mkv_fill_buffer(demuxer);
}