From 0ece360eeaf95f2c33df2c0177cb98ffd5fc0338 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Thu, 4 Aug 2011 08:38:39 +0300 Subject: 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. --- libmpdemux/demux_mkv.c | 82 ++++++++++++++++++++++++++++++-------------------- libmpdemux/demuxer.c | 38 +++++++++++++++-------- libmpdemux/demuxer.h | 10 ++++++ 3 files changed, 85 insertions(+), 45 deletions(-) (limited to 'libmpdemux') 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); -- cgit v1.2.3