summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUoti Urpala <uau@mplayer2.org>2011-08-04 08:38:39 +0300
committerUoti Urpala <uau@mplayer2.org>2011-08-04 08:38:39 +0300
commit0ece360eeaf95f2c33df2c0177cb98ffd5fc0338 (patch)
tree3717c71405b255342f75008b8d357f421f9f24f0
parent1f3ad329601486e2e2e36ddef4d79f0f486ddc99 (diff)
downloadmpv-0ece360eeaf95f2c33df2c0177cb98ffd5fc0338.tar.bz2
mpv-0ece360eeaf95f2c33df2c0177cb98ffd5fc0338.tar.xz
demux_mkv: skip files faster in ordered chapter file search
Ordered chapter code tries opening files to find those matching the SegmentUID values specified in the timeline. Previously this scan did a full initialization of the Matroska demuxer for each file, then checked whether the UID value in the demuxer was a match. Make the scan code instead provide a list of searched-for UIDs to the demuxer open code, and make that do a comparison against the list as soon as it sees the UID in the file, aborting if there is no match. Also fix units used in "Merging timeline part" verbose message.
-rw-r--r--libmpdemux/demux_mkv.c82
-rw-r--r--libmpdemux/demuxer.c38
-rw-r--r--libmpdemux/demuxer.h10
-rw-r--r--timeline/tl_matroska.c16
4 files changed, 95 insertions, 51 deletions
diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c
index dadb3887cf..692bec9ecf 100644
--- a/libmpdemux/demux_mkv.c
+++ b/libmpdemux/demux_mkv.c
@@ -374,6 +374,7 @@ static int demux_mkv_read_info(demuxer_t *demuxer)
{
mkv_demuxer_t *mkv_d = demuxer->priv;
stream_t *s = demuxer->stream;
+ int res = 0;
mkv_d->tc_scale = 1000000;
mkv_d->duration = 0;
@@ -381,7 +382,7 @@ static int demux_mkv_read_info(demuxer_t *demuxer)
struct ebml_info info = {};
struct ebml_parse_ctx parse_ctx = {};
if (ebml_read_element(s, &parse_ctx, &info, &ebml_info_desc) < 0)
- return 1;
+ return -1;
if (info.n_timecode_scale) {
mkv_d->tc_scale = info.timecode_scale;
mp_msg(MSGT_DEMUX, MSGL_V,
@@ -407,8 +408,22 @@ static int demux_mkv_read_info(demuxer_t *demuxer)
mp_msg(MSGT_DEMUX, MSGL_V, "\n");
}
}
+ if (demuxer->params && demuxer->params->matroska_wanted_uids) {
+ unsigned char (*uids)[16] = demuxer->params->matroska_wanted_uids;
+ if (!info.n_segment_uid)
+ uids = NULL;
+ for (int i = 0; i < MP_TALLOC_ELEMS(uids); i++) {
+ if (!memcmp(info.segment_uid.start, uids[i], 16))
+ goto out;
+ }
+ mp_tmsg(MSGT_DEMUX, MSGL_INFO,
+ "[mkv] This is not one of the wanted files. "
+ "Stopping attempt to open.\n");
+ res = -2;
+ }
+ out:
talloc_free(parse_ctx.talloc_ctx);
- return 0;
+ return res;
}
static void parse_trackencodings(struct demuxer *demuxer,
@@ -923,7 +938,7 @@ static int demux_mkv_read_seekhead(demuxer_t *demuxer)
mp_msg(MSGT_DEMUX, MSGL_V,
"[mkv] /---- [ parsing seek head ] ---------\n");
if (ebml_read_element(s, &parse_ctx, &seekhead, &ebml_seek_head_desc) < 0) {
- res = 1;
+ res = -1;
goto out;
}
/* off now holds the position of the next element after the seek head. */
@@ -940,12 +955,16 @@ static int demux_mkv_read_seekhead(demuxer_t *demuxer)
"end of file - incomplete file?\n");
continue;
}
- read_header_element(demuxer, seek->seek_id, pos);
+ int r = read_header_element(demuxer, seek->seek_id, pos);
+ if (r <= -2) {
+ res = r;
+ goto out;
+ }
}
if (!stream_seek(s, off)) {
mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Couldn't seek back after "
"SeekHead??\n");
- res = 1;
+ res = -1;
}
out:
mp_msg(MSGT_DEMUX, MSGL_V,
@@ -982,7 +1001,7 @@ static int read_header_element(struct demuxer *demuxer, uint32_t id,
return -1;
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] |+ segment information...\n");
mkv_d->parsed_info = true;
- return demux_mkv_read_info(demuxer) ? -1 : 1;
+ return demux_mkv_read_info(demuxer);
case MATROSKA_ID_TRACKS:
if (mkv_d->parsed_tracks)
@@ -1013,7 +1032,7 @@ static int read_header_element(struct demuxer *demuxer, uint32_t id,
break;
if (at_filepos && !seek_pos_id(s, at_filepos, id))
return -1;
- return demux_mkv_read_seekhead(demuxer) ? -1 : 1;
+ return demux_mkv_read_seekhead(demuxer);
case MATROSKA_ID_CHAPTERS:
if (mkv_d->parsed_chapters)
@@ -1602,12 +1621,22 @@ static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track,
return 0;
}
+static void mkv_free(struct demuxer *demuxer)
+{
+ struct mkv_demuxer *mkv_d = demuxer->priv;
+ if (!mkv_d)
+ return;
+ for (int i = 0; i < mkv_d->num_tracks; i++)
+ demux_mkv_free_trackentry(mkv_d->tracks[i]);
+ free(mkv_d->indexes);
+ free(mkv_d->cluster_positions);
+}
+
static int demux_mkv_open(demuxer_t *demuxer)
{
stream_t *s = demuxer->stream;
mkv_demuxer_t *mkv_d;
mkv_track_t *track;
- int i, cont = 0;
stream_seek(s, s->start_pos);
if (ebml_read_id(s, NULL) != EBML_ID_EBML)
@@ -1660,7 +1689,7 @@ static int demux_mkv_open(demuxer_t *demuxer)
mkv_d->tc_scale = 1000000;
mkv_d->segment_start = stream_tell(s);
- while (!cont) {
+ while (1) {
uint32_t id = ebml_read_id(s, NULL);
switch (id) {
case MATROSKA_ID_CLUSTER:
@@ -1668,17 +1697,21 @@ static int demux_mkv_open(demuxer_t *demuxer)
"[mkv] |+ found cluster, headers are "
"parsed completely :)\n");
stream_seek(s, stream_tell(s) - 4);
- cont = 1;
- break;
-
- default:
- cont = read_header_element(demuxer, id, 0) < 1;
+ goto headersdone;
+ default:;
+ int res = read_header_element(demuxer, id, 0);
+ if (res == -2) {
+ mkv_free(demuxer);
+ return 0;
+ } else if (res < 1)
+ goto headersdone;
break;
case EBML_ID_VOID:
ebml_read_skip(s, NULL);
break;
}
}
+ headersdone:
display_create_tracks(demuxer);
@@ -1686,7 +1719,7 @@ static int demux_mkv_open(demuxer_t *demuxer)
track = NULL;
if (demuxer->video->id == -1) { /* automatically select a video track */
/* search for a video track that has the 'default' flag set */
- for (i = 0; i < mkv_d->num_tracks; i++)
+ for (int i = 0; i < mkv_d->num_tracks; i++)
if (mkv_d->tracks[i]->type == MATROSKA_TRACK_VIDEO
&& mkv_d->tracks[i]->default_track) {
track = mkv_d->tracks[i];
@@ -1696,7 +1729,7 @@ static int demux_mkv_open(demuxer_t *demuxer)
if (track == NULL)
/* no track has the 'default' flag set */
/* let's take the first video track */
- for (i = 0; i < mkv_d->num_tracks; i++)
+ for (int i = 0; i < mkv_d->num_tracks; i++)
if (mkv_d->tracks[i]->type == MATROSKA_TRACK_VIDEO
&& mkv_d->tracks[i]->id >= 0) {
track = mkv_d->tracks[i];
@@ -1731,21 +1764,6 @@ static int demux_mkv_open(demuxer_t *demuxer)
return DEMUXER_TYPE_MATROSKA;
}
-static void demux_close_mkv(demuxer_t *demuxer)
-{
- mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
-
- if (mkv_d) {
- int i;
- if (mkv_d->tracks) {
- for (i = 0; i < mkv_d->num_tracks; i++)
- demux_mkv_free_trackentry(mkv_d->tracks[i]);
- }
- free(mkv_d->indexes);
- free(mkv_d->cluster_positions);
- }
-}
-
static int demux_mkv_read_block_lacing(uint8_t *buffer, uint64_t *size,
uint8_t *laces,
uint32_t **all_lace_sizes)
@@ -2518,7 +2536,7 @@ const demuxer_desc_t demuxer_desc_matroska = {
demux_mkv_open,
demux_mkv_fill_buffer,
NULL,
- demux_close_mkv,
+ mkv_free,
demux_mkv_seek,
demux_mkv_control
};
diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c
index ef3bd36e29..c59fd3fdc7 100644
--- a/libmpdemux/demuxer.c
+++ b/libmpdemux/demuxer.c
@@ -911,12 +911,14 @@ static struct demuxer *open_given_type(struct MPOpts *opts,
const struct demuxer_desc *desc,
struct stream *stream, bool force,
int audio_id, int video_id, int sub_id,
- char *filename)
+ char *filename,
+ struct demuxer_params *params)
{
struct demuxer *demuxer;
int fformat;
demuxer = new_demuxer(opts, stream, desc->type, audio_id,
video_id, sub_id, filename);
+ demuxer->params = params;
if (desc->check_file)
fformat = desc->check_file(demuxer);
else
@@ -960,7 +962,7 @@ static struct demuxer *open_given_type(struct MPOpts *opts,
return NULL;
}
return open_given_type(opts, desc, stream, false, audio_id,
- video_id, sub_id, filename);
+ video_id, sub_id, filename, params);
}
fail:
free_demuxer(demuxer);
@@ -971,7 +973,8 @@ static struct demuxer *demux_open_stream(struct MPOpts *opts,
struct stream *stream,
int file_format, bool force,
int audio_id, int video_id, int sub_id,
- char *filename)
+ char *filename,
+ struct demuxer_params *params)
{
struct demuxer *demuxer = NULL;
const struct demuxer_desc *desc;
@@ -983,7 +986,7 @@ static struct demuxer *demux_open_stream(struct MPOpts *opts,
// should only happen with obsolete -demuxer 99 numeric format
return NULL;
demuxer = open_given_type(opts, desc, stream, force, audio_id,
- video_id, sub_id, filename);
+ video_id, sub_id, filename, params);
if (demuxer)
goto dmx_open;
return NULL;
@@ -993,7 +996,7 @@ static struct demuxer *demux_open_stream(struct MPOpts *opts,
for (int i = 0; (desc = demuxer_list[i]); i++) {
if (desc->safe_check) {
demuxer = open_given_type(opts, desc, stream, false, audio_id,
- video_id, sub_id, filename);
+ video_id, sub_id, filename, params);
if (demuxer)
goto dmx_open;
}
@@ -1006,7 +1009,7 @@ static struct demuxer *demux_open_stream(struct MPOpts *opts,
desc = get_demuxer_desc_from_type(demuxer_type_by_filename(filename));
if (desc)
demuxer = open_given_type(opts, desc, stream, false, audio_id,
- video_id, sub_id, filename);
+ video_id, sub_id, filename, params);
if (demuxer)
goto dmx_open;
}
@@ -1015,7 +1018,7 @@ static struct demuxer *demux_open_stream(struct MPOpts *opts,
for (int i = 0; (desc = demuxer_list[i]); i++) {
if (!desc->safe_check && desc->check_file) {
demuxer = open_given_type(opts, desc, stream, false, audio_id,
- video_id, sub_id, filename);
+ video_id, sub_id, filename, params);
if (demuxer)
goto dmx_open;
}
@@ -1041,9 +1044,17 @@ static struct demuxer *demux_open_stream(struct MPOpts *opts,
return demuxer;
}
-demuxer_t *demux_open(struct MPOpts *opts, stream_t *vs, int file_format,
- int audio_id, int video_id, int dvdsub_id,
- char *filename)
+struct demuxer *demux_open(struct MPOpts *opts, stream_t *vs, int file_format,
+ int audio_id, int video_id, int sub_id,
+ char *filename)
+{
+ return demux_open_withparams(opts, vs, file_format, audio_id, video_id,
+ sub_id, filename, NULL);
+}
+
+struct demuxer *demux_open_withparams(struct MPOpts *opts, stream_t *vs,
+ int file_format, int audio_id, int video_id, int dvdsub_id,
+ char *filename, struct demuxer_params *params)
{
stream_t *as = NULL, *ss = NULL;
demuxer_t *vd, *ad = NULL, *sd = NULL;
@@ -1108,7 +1119,8 @@ demuxer_t *demux_open(struct MPOpts *opts, stream_t *vs, int file_format,
vd = demux_open_stream(opts, vs, demuxer_type ? demuxer_type : file_format,
demuxer_force, opts->audio_stream ? -2 : audio_id,
- video_id, opts->sub_stream ? -2 : dvdsub_id, filename);
+ video_id, opts->sub_stream ? -2 : dvdsub_id,
+ filename, params);
if (!vd) {
if (as)
free_stream(as);
@@ -1120,7 +1132,7 @@ demuxer_t *demux_open(struct MPOpts *opts, stream_t *vs, int file_format,
ad = demux_open_stream(opts, as,
audio_demuxer_type ? audio_demuxer_type : afmt,
audio_demuxer_force, audio_id, -2, -2,
- opts->audio_stream);
+ opts->audio_stream, params);
if (!ad) {
mp_tmsg(MSGT_DEMUXER, MSGL_WARN, "Failed to open audio demuxer: %s\n",
opts->audio_stream);
@@ -1133,7 +1145,7 @@ demuxer_t *demux_open(struct MPOpts *opts, stream_t *vs, int file_format,
sd = demux_open_stream(opts, ss,
sub_demuxer_type ? sub_demuxer_type : sfmt,
sub_demuxer_force, -2, -2, dvdsub_id,
- opts->sub_stream);
+ opts->sub_stream, params);
if (!sd) {
mp_tmsg(MSGT_DEMUXER, MSGL_WARN,
"Failed to open subtitle demuxer: %s\n", opts->sub_stream);
diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h
index ee664d83e2..b3fef45ed7 100644
--- a/libmpdemux/demuxer.h
+++ b/libmpdemux/demuxer.h
@@ -239,6 +239,10 @@ typedef struct demux_attachment
unsigned int data_size;
} demux_attachment_t;
+struct demuxer_params {
+ unsigned char (*matroska_wanted_uids)[16];
+};
+
typedef struct demuxer {
const demuxer_desc_t *desc; ///< Demuxer description structure
const char *filetype; // format name when not identified by demuxer (libavformat)
@@ -289,6 +293,7 @@ typedef struct demuxer {
void *priv; // demuxer-specific internal data
char **info; // metadata
struct MPOpts *opts;
+ struct demuxer_params *params;
} demuxer_t;
typedef struct {
@@ -370,6 +375,11 @@ static inline int avi_stream_id(unsigned int id)
struct demuxer *demux_open(struct MPOpts *opts, struct stream *stream,
int file_format, int aid, int vid, int sid,
char *filename);
+
+struct demuxer *demux_open_withparams(struct MPOpts *opts,
+ struct stream *stream, int file_format, int aid, int vid, int sid,
+ char *filename, struct demuxer_params *params);
+
void demux_flush(struct demuxer *demuxer);
int demux_seek(struct demuxer *demuxer, float rel_seek_secs, float audio_delay,
int flags);
diff --git a/timeline/tl_matroska.c b/timeline/tl_matroska.c
index 6912bac159..967ee556ae 100644
--- a/timeline/tl_matroska.c
+++ b/timeline/tl_matroska.c
@@ -112,10 +112,12 @@ static int find_ordered_chapter_sources(struct MPContext *mpctx,
struct stream *s = open_stream(filenames[i], &mpctx->opts, &format);
if (!s)
continue;
- struct demuxer *d = demux_open(&mpctx->opts, s, DEMUXER_TYPE_MATROSKA,
- mpctx->opts.audio_id,
- mpctx->opts.video_id,
- mpctx->opts.sub_id, filenames[i]);
+ struct demuxer *d = demux_open_withparams(&mpctx->opts, s,
+ DEMUXER_TYPE_MATROSKA, mpctx->opts.audio_id,
+ mpctx->opts.video_id, mpctx->opts.sub_id, filenames[i],
+ &(struct demuxer_params){.matroska_wanted_uids = uid_map});
+
+
if (!d) {
free_stream(s);
continue;
@@ -176,7 +178,8 @@ void build_ordered_chapter_timeline(struct MPContext *mpctx)
m->num_ordered_chapters+1);
sources[0].stream = mpctx->stream;
sources[0].demuxer = mpctx->demuxer;
- unsigned char uid_map[m->num_ordered_chapters+1][16];
+ unsigned char (*uid_map)[16] = talloc_array_ptrtype(NULL, uid_map,
+ m->num_ordered_chapters + 1);
int num_sources = 1;
memcpy(uid_map[0], m->segment_uid, 16);
@@ -241,7 +244,7 @@ void build_ordered_chapter_timeline(struct MPContext *mpctx)
/* Chapter was merged at an inexact boundary;
* adjust timestamps to match. */
mp_msg(MSGT_CPLAYER, MSGL_V, "Merging timeline part %d with "
- "offset %d ms.\n", i, (int) join_diff);
+ "offset %g ms.\n", i, join_diff / 1e6);
starttime += join_diff;
}
chapters[num_chapters].start = starttime / 1e9;
@@ -250,6 +253,7 @@ void build_ordered_chapter_timeline(struct MPContext *mpctx)
num_chapters++;
}
timeline[part_count].start = starttime / 1e9;
+ talloc_free(uid_map);
if (!part_count) {
// None of the parts come from the file itself???