From 26a51464b68ce2571bdbe538da9c0a1c255b879f Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Wed, 31 Jan 2024 14:06:56 -0600 Subject: [PATCH] demux_mkv: detect images by reading blocks and timecodes 4709a94aec5b16534b1d6b0d6738caeaf692e9c9 along with some related commits added a way to detect image codecs embedded into mkv streams that weren't tagged with attached picture (arguably a broken file anyways, but maybe not the worst thing to workaround). Unfortunately, this has some false positives particularly with mjpeg playback. So, as usual, revert and rewrite. Instead, we can probe the file and count blocks in the stream. If the video stream has only 1 block and 1 timecode, then assume it's a still image. --- demux/demux_mkv.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 40b9a1b0ad..98be0cf6d6 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -2002,6 +2002,41 @@ static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track) return 0; } +// Workaround for broken files that don't set attached_picture +static void probe_if_image(demuxer_t *demuxer) +{ + mkv_demuxer_t *mkv_d = demuxer->priv; + + for (int n = 0; n < mkv_d->num_tracks; n++) { + int video_blocks = 0; + mkv_track_t *track = mkv_d->tracks[n]; + struct sh_stream *sh = track->stream; + + if (!sh || sh->type != STREAM_VIDEO) + continue; + + int64_t timecode = -1; + // Arbitrary restriction on packet reading. + for (int i = 0; i < 100; i++) { + int ret = read_next_block_into_queue(demuxer); + if (ret == 1 && mkv_d->blocks[i].track == track) { + if (timecode != mkv_d->blocks[i].timecode) + ++video_blocks; + timecode = mkv_d->blocks[i].timecode; + } + // No need to read more + if (video_blocks > 1) + break; + } + + // Assume still image + if (video_blocks == 1) { + sh->still_image = true; + sh->image = true; + } + } +} + static void probe_x264_garbage(demuxer_t *demuxer) { mkv_demuxer_t *mkv_d = demuxer->priv; @@ -2254,6 +2289,7 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check) if (mkv_d->opts->probe_duration) probe_last_timestamp(demuxer, start_pos); probe_x264_garbage(demuxer); + probe_if_image(demuxer); return 0; }