summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-10-16 16:49:23 +0200
committerwm4 <wm4@nowhere>2015-10-16 17:11:44 +0200
commit76bfd5b4a237dda8f4ec5c05315bf566421f7908 (patch)
tree37ecccf2a9a43c2ade501d83dbae7ccf0fe60422
parent8d414e2fe7f79f1bbf9158e8aa034e9ac9cf2222 (diff)
downloadmpv-76bfd5b4a237dda8f4ec5c05315bf566421f7908.tar.bz2
mpv-76bfd5b4a237dda8f4ec5c05315bf566421f7908.tar.xz
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.)
-rw-r--r--demux/demux_mkv.c53
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;