diff options
author | wm4 <wm4@nowhere> | 2015-10-16 16:49:23 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2015-10-16 17:11:44 +0200 |
commit | 76bfd5b4a237dda8f4ec5c05315bf566421f7908 (patch) | |
tree | 37ecccf2a9a43c2ade501d83dbae7ccf0fe60422 /demux | |
parent | 8d414e2fe7f79f1bbf9158e8aa034e9ac9cf2222 (diff) |
demux_mkv: probe start time
MKV files can very well start with timestamps other than 0. While mpv
has support for such files in general, and demux_lavf enables this
feature, demux_mkv didn't export a start time.
Implement this by simply reading the first cluster timestamp. This in
turn is done by reading 1 block. While we don't need the block for this
prupose at all, it's the easiest way to get the cluster timestamp read
correctly without code duplication. In theory this could be wrong, and
a packet could start at a much later time, but in practice this won't
happen.
This commit also adds an option to disable this feature. It's not
documented because nobody should use it. (But I happen to have a need
for this.)
Diffstat (limited to 'demux')
-rw-r--r-- | demux/demux_mkv.c | 53 |
1 files changed, 43 insertions, 10 deletions
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index daf03d615b..15c03de0bd 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -149,6 +149,16 @@ typedef struct mkv_index { uint64_t filepos; // position of the cluster which contains the packet } mkv_index_t; +struct block_info { + uint64_t duration, discardpadding; + bool simple, keyframe; + uint64_t timecode; + mkv_track_t *track; + bstr data; + void *alloc; + int64_t filepos; +}; + typedef struct mkv_demuxer { int64_t segment_start, segment_end; @@ -183,6 +193,8 @@ typedef struct mkv_demuxer { bool index_has_durations; bool eof_warning; + + struct block_info tmp_block; } mkv_demuxer_t; #define OPT_BASE_STRUCT struct demux_mkv_opts @@ -190,6 +202,7 @@ struct demux_mkv_opts { int subtitle_preroll; double subtitle_preroll_secs; int probe_duration; + int probe_start_time; int fix_timestamps; }; @@ -200,12 +213,14 @@ const struct m_sub_options demux_mkv_conf = { M_OPT_MIN, .min = 0), OPT_CHOICE("probe-video-duration", probe_duration, 0, ({"no", 0}, {"yes", 1}, {"full", 2})), + OPT_FLAG("probe-start-time", probe_start_time, 0), OPT_FLAG("fix-timestamps", fix_timestamps, 0), {0} }, .size = sizeof(struct demux_mkv_opts), .defaults = &(const struct demux_mkv_opts){ .subtitle_preroll_secs = 1.0, + .probe_start_time = 1, .fix_timestamps = 0, }, }; @@ -220,6 +235,8 @@ const struct m_sub_options demux_mkv_conf = { #define NUM_SUB_PREROLL_PACKETS 500 static void probe_last_timestamp(struct demuxer *demuxer); +static void probe_first_timestamp(struct demuxer *demuxer); +static void free_block(struct block_info *block); #define AAC_SYNC_EXTENSION_TYPE 0x02b7 static int aac_get_sample_rate_index(uint32_t sample_rate) @@ -1884,6 +1901,7 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check) add_coverart(demuxer); demuxer->allow_refresh_seeks = true; + probe_first_timestamp(demuxer); if (opts->demux_mkv->probe_duration) probe_last_timestamp(demuxer); @@ -2095,6 +2113,8 @@ static void mkv_seek_reset(demuxer_t *demuxer) } track->av_parser_codec = NULL; } + + free_block(&mkv_d->tmp_block); } // Copied from libavformat/matroskadec.c (FFmpeg 310f9dd / 2013-05-30) @@ -2268,16 +2288,6 @@ static void mkv_parse_and_add_packet(demuxer_t *demuxer, mkv_track_t *track, } } -struct block_info { - uint64_t duration, discardpadding; - bool simple, keyframe; - uint64_t timecode; - mkv_track_t *track; - bstr data; - void *alloc; - int64_t filepos; -}; - static void free_block(struct block_info *block) { free(block->alloc); @@ -2526,6 +2536,12 @@ static int read_next_block(demuxer_t *demuxer, struct block_info *block) mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; stream_t *s = demuxer->stream; + if (mkv_d->tmp_block.alloc) { + *block = mkv_d->tmp_block; + mkv_d->tmp_block = (struct block_info){0}; + return 1; + } + while (1) { while (stream_tell(s) < mkv_d->cluster_end) { int64_t start_filepos = stream_tell(s); @@ -2923,6 +2939,23 @@ static void probe_last_timestamp(struct demuxer *demuxer) mkv_d->cluster_start = mkv_d->cluster_end = 0; } +static void probe_first_timestamp(struct demuxer *demuxer) +{ + mkv_demuxer_t *mkv_d = demuxer->priv; + + if (!demuxer->opts->demux_mkv->probe_start_time) + return; + + struct block_info block; + if (read_next_block(demuxer, &block) > 0) + mkv_d->tmp_block = block; + + demuxer->start_time = mkv_d->cluster_tc / 1e9; + + if (demuxer->start_time > 0) + MP_VERBOSE(demuxer, "Start PTS: %f\n", demuxer->start_time); +} + static int demux_mkv_control(demuxer_t *demuxer, int cmd, void *arg) { mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; |