diff options
Diffstat (limited to 'demux')
-rw-r--r-- | demux/demux.c | 56 | ||||
-rw-r--r-- | demux/demux.h | 1 | ||||
-rw-r--r-- | demux/demux_lavf.c | 63 | ||||
-rw-r--r-- | demux/demux_mf.c | 14 | ||||
-rw-r--r-- | demux/demux_mkv.c | 37 | ||||
-rw-r--r-- | demux/demux_mkv_timeline.c | 24 | ||||
-rw-r--r-- | demux/demux_raw.c | 8 |
7 files changed, 137 insertions, 66 deletions
diff --git a/demux/demux.c b/demux/demux.c index 29e13f3344..9404629ad4 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -20,6 +20,7 @@ #include <string.h> #include <assert.h> #include <unistd.h> +#include <limits.h> #include <pthread.h> #include <math.h> @@ -28,7 +29,8 @@ #include <sys/stat.h> #include "config.h" -#include "options/options.h" +#include "options/m_config.h" +#include "options/m_option.h" #include "mpv_talloc.h" #include "common/msg.h" #include "common/global.h" @@ -81,6 +83,34 @@ const demuxer_desc_t *const demuxer_list[] = { NULL }; +struct demux_opts { + int max_packs; + int max_bytes; + double min_secs; + int force_seekable; + double min_secs_cache; +}; + +#define OPT_BASE_STRUCT struct demux_opts + +const struct m_sub_options demux_conf = { + .opts = (const struct m_option[]){ + OPT_DOUBLE("demuxer-readahead-secs", min_secs, M_OPT_MIN, .min = 0), + OPT_INTRANGE("demuxer-max-packets", max_packs, 0, 0, INT_MAX), + OPT_INTRANGE("demuxer-max-bytes", max_bytes, 0, 0, INT_MAX), + OPT_FLAG("force-seekable", force_seekable, 0), + OPT_DOUBLE("cache-secs", min_secs_cache, M_OPT_MIN, .min = 0), + {0} + }, + .size = sizeof(struct demux_opts), + .defaults = &(const struct demux_opts){ + .max_packs = 16000, + .max_bytes = 400 * 1024 * 1024, + .min_secs = 1.0, + .min_secs_cache = 10.0, + }, +}; + struct demux_internal { struct mp_log *log; @@ -1185,7 +1215,6 @@ static struct demuxer *open_given_type(struct mpv_global *global, .stream = stream, .seekable = stream->seekable, .filepos = -1, - .opts = global->opts, .global = global, .log = mp_log_new(demuxer, log, desc->name), .glog = log, @@ -1198,22 +1227,24 @@ static struct demuxer *open_given_type(struct mpv_global *global, !demuxer->stream->uncached_stream->seekable) demuxer->seekable = false; + struct demux_opts *opts = mp_get_config_group(demuxer, global, &demux_conf); + struct demux_internal *in = demuxer->in = talloc_ptrtype(demuxer, in); *in = (struct demux_internal){ .log = demuxer->log, .d_thread = talloc(demuxer, struct demuxer), .d_buffer = talloc(demuxer, struct demuxer), .d_user = demuxer, - .min_secs = demuxer->opts->demuxer_min_secs, - .max_packs = demuxer->opts->demuxer_max_packs, - .max_bytes = demuxer->opts->demuxer_max_bytes, + .min_secs = opts->min_secs, + .max_packs = opts->max_packs, + .max_bytes = opts->max_bytes, .initial_state = true, }; pthread_mutex_init(&in->lock, NULL); pthread_cond_init(&in->wakeup, NULL); if (stream->uncached_stream) - in->min_secs = MPMAX(in->min_secs, demuxer->opts->demuxer_min_secs_cache); + in->min_secs = MPMAX(in->min_secs, opts->min_secs_cache); *in->d_thread = *demuxer; *in->d_buffer = *demuxer; @@ -1244,7 +1275,7 @@ static struct demuxer *open_given_type(struct mpv_global *global, mp_verbose(log, "Detected file format: %s\n", desc->desc); if (!in->d_thread->seekable) mp_verbose(log, "Stream is not seekable.\n"); - if (!in->d_thread->seekable && demuxer->opts->force_seekable) { + if (!in->d_thread->seekable && opts->force_seekable) { mp_warn(log, "Not seekable, but enabling seeking on user request.\n"); in->d_thread->seekable = true; in->d_thread->partially_seekable = true; @@ -1336,7 +1367,6 @@ struct demuxer *demux_open_url(const char *url, struct mp_cancel *cancel, struct mpv_global *global) { - struct MPOpts *opts = global->opts; struct demuxer_params dummy = {0}; if (!params) params = &dummy; @@ -1344,10 +1374,14 @@ struct demuxer *demux_open_url(const char *url, cancel, global); if (!s) return NULL; - if (params->allow_capture) - stream_set_capture_file(s, opts->stream_capture); + if (params->allow_capture) { + char *f; + mp_read_option_raw(global, "stream-capture", &m_option_type_string, &f); + stream_set_capture_file(s, f); + talloc_free(f); + } if (!params->disable_cache) - stream_enable_cache(&s, &opts->stream_cache); + stream_enable_cache_defaults(&s); struct demuxer *d = demux_open(s, params, global); if (d) { demux_maybe_replace_stream(d); diff --git a/demux/demux.h b/demux/demux.h index 9978335cfd..39c2600257 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -207,7 +207,6 @@ typedef struct demuxer { struct mp_tags *metadata; void *priv; // demuxer-specific internal data - struct MPOpts *opts; struct mpv_global *global; struct mp_log *log, *glog; struct demuxer_params *params; diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index d7dbfe3ff1..43f2569369 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -35,7 +35,6 @@ #include <libavutil/display.h> #include <libavutil/opt.h> -#include "options/options.h" #include "common/msg.h" #include "common/tags.h" #include "common/av_common.h" @@ -45,6 +44,7 @@ #include "stream/stream.h" #include "demux.h" #include "stheader.h" +#include "options/m_config.h" #include "options/m_option.h" #include "options/path.h" @@ -69,22 +69,32 @@ struct demux_lavf_opts { char **avopts; int hacks; int genptsmode; + char *sub_cp; + int rtsp_transport; }; const struct m_sub_options demux_lavf_conf = { .opts = (const m_option_t[]) { - OPT_INTRANGE("probesize", probesize, 0, 32, INT_MAX), - OPT_STRING("format", format, 0), - OPT_FLOATRANGE("analyzeduration", analyzeduration, 0, 0, 3600), - OPT_INTRANGE("buffersize", buffersize, 0, 1, 10 * 1024 * 1024, - OPTDEF_INT(BIO_BUFFER_SIZE)), - OPT_FLAG("allow-mimetype", allow_mimetype, 0), - OPT_INTRANGE("probescore", probescore, 0, 1, AVPROBE_SCORE_MAX), - OPT_STRING("cryptokey", cryptokey, 0), - OPT_FLAG("hacks", hacks, 0), - OPT_CHOICE("genpts-mode", genptsmode, 0, + OPT_INTRANGE("demuxer-lavf-probesize", probesize, 0, 32, INT_MAX), + OPT_STRING("demuxer-lavf-format", format, 0), + OPT_FLOATRANGE("demuxer-lavf-analyzeduration", analyzeduration, 0, + 0, 3600), + OPT_INTRANGE("demuxer-lavf-buffersize", buffersize, 0, 1, + 10 * 1024 * 1024, OPTDEF_INT(BIO_BUFFER_SIZE)), + OPT_FLAG("demuxer-lavf-allow-mimetype", allow_mimetype, 0), + OPT_INTRANGE("demuxer-lavf-probescore", probescore, 0, + 1, AVPROBE_SCORE_MAX), + OPT_STRING("demuxer-lavf-cryptokey", cryptokey, 0), + OPT_FLAG("demuxer-lavf-hacks", hacks, 0), + OPT_CHOICE("demuxer-lavf-genpts-mode", genptsmode, 0, ({"lavf", 1}, {"no", 0})), - OPT_KEYVALUELIST("o", avopts, 0), + OPT_KEYVALUELIST("demuxer-lavf-o", avopts, 0), + OPT_STRING("sub-codepage", sub_cp, 0), + OPT_CHOICE("rtsp-transport", rtsp_transport, 0, + ({"lavf", 0}, + {"udp", 1}, + {"tcp", 2}, + {"http", 3})), {0} }, .size = sizeof(struct demux_lavf_opts), @@ -95,6 +105,8 @@ const struct m_sub_options demux_lavf_conf = { // user is supposed to retry with larger probe sizes until a higher // value is reached. .probescore = AVPROBE_SCORE_MAX/4 + 1, + .sub_cp = "auto", + .rtsp_transport = 2, }, }; @@ -174,6 +186,9 @@ typedef struct lavf_priv { int cur_program; char *mime_type; double seek_delay; + + struct demux_lavf_opts *opts; + double mf_fps; } lavf_priv_t; // At least mp4 has name="mov,mp4,m4a,3gp,3g2,mj2", so we split the name @@ -271,7 +286,7 @@ static void list_formats(struct demuxer *demuxer) static void convert_charset(struct demuxer *demuxer) { lavf_priv_t *priv = demuxer->priv; - char *cp = demuxer->opts->sub_cp; + char *cp = priv->opts->sub_cp; if (!cp || mp_charset_is_utf8(cp)) return; bstr data = stream_read_complete(priv->stream, NULL, 128 * 1024 * 1024); @@ -313,9 +328,8 @@ static const char *const prefixes[] = static int lavf_check_file(demuxer_t *demuxer, enum demux_check check) { - struct MPOpts *opts = demuxer->opts; - struct demux_lavf_opts *lavfdopts = opts->demux_lavf; lavf_priv_t *priv = demuxer->priv; + struct demux_lavf_opts *lavfdopts = priv->opts; struct stream *s = priv->stream; priv->filename = remove_prefix(s->url, prefixes); @@ -606,7 +620,7 @@ static void handle_new_stream(demuxer_t *demuxer, int i) if (st->avg_frame_rate.num) sh->codec->fps = av_q2d(st->avg_frame_rate); if (priv->format_hack.image_format) - sh->codec->fps = demuxer->opts->mf_fps; + sh->codec->fps = priv->mf_fps; sh->codec->par_w = st->sample_aspect_ratio.num; sh->codec->par_h = st->sample_aspect_ratio.den; @@ -736,8 +750,6 @@ static int interrupt_cb(void *ctx) static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check) { - struct MPOpts *opts = demuxer->opts; - struct demux_lavf_opts *lavfdopts = opts->demux_lavf; AVFormatContext *avfc; AVDictionaryEntry *t = NULL; float analyze_duration = 0; @@ -745,6 +757,15 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check) demuxer->priv = priv; priv->stream = demuxer->stream; + priv->opts = mp_get_config_group(priv, demuxer->global, &demux_lavf_conf); + struct demux_lavf_opts *lavfdopts = priv->opts; + + int index_mode; + mp_read_option_raw(demuxer->global, "index", &m_option_type_choice, + &index_mode); + mp_read_option_raw(demuxer->global, "mf-fps", &m_option_type_double, + &priv->mf_fps); + if (lavf_check_file(demuxer, check) < 0) return -1; @@ -756,7 +777,7 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check) parse_cryptokey(avfc, lavfdopts->cryptokey); if (lavfdopts->genptsmode) avfc->flags |= AVFMT_FLAG_GENPTS; - if (opts->index_mode != 1) + if (index_mode != 1) avfc->flags |= AVFMT_FLAG_IGNIDX; #if LIBAVFORMAT_VERSION_MICRO >= 100 @@ -789,7 +810,7 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check) priv->stream->type == STREAMTYPE_AVDEVICE || priv->format_hack.no_stream) { - mp_setup_av_network_options(&dopts, demuxer->global, demuxer->log, opts); + mp_setup_av_network_options(&dopts, demuxer->global, demuxer->log); // This might be incorrect. demuxer->seekable = true; } else { @@ -812,7 +833,7 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check) if (matches_avinputformat_name(priv, "rtsp")) { const char *transport = NULL; - switch (opts->network_rtsp_transport) { + switch (lavfdopts->rtsp_transport) { case 1: transport = "udp"; break; case 2: transport = "tcp"; break; case 3: transport = "http"; break; diff --git a/demux/demux_mf.c b/demux/demux_mf.c index 20b948630c..4abd394317 100644 --- a/demux/demux_mf.c +++ b/demux/demux_mf.c @@ -27,6 +27,7 @@ #include "mpv_talloc.h" #include "common/msg.h" #include "options/options.h" +#include "options/m_config.h" #include "options/path.h" #include "misc/ctype.h" @@ -304,10 +305,15 @@ static int demux_open_mf(demuxer_t *demuxer, enum demux_check check) if (!mf || mf->nr_of_files < 1) goto error; - char *force_type = demuxer->opts->mf_type; + double mf_fps; + char *mf_type; + mp_read_option_raw(demuxer->global, "mf-fps", &m_option_type_double, &mf_fps); + mp_read_option_raw(demuxer->global, "mf-type", &m_option_type_string, &mf_type); + const char *codec = mp_map_mimetype_to_video_codec(demuxer->stream->mime_type); - if (!codec || (force_type && force_type[0])) - codec = probe_format(mf, force_type, check); + if (!codec || (mf_type && mf_type[0])) + codec = probe_format(mf, mf_type, check); + talloc_free(mf_type); if (!codec) goto error; @@ -320,7 +326,7 @@ static int demux_open_mf(demuxer_t *demuxer, enum demux_check check) c->codec = codec; c->disp_w = 0; c->disp_h = 0; - c->fps = demuxer->opts->mf_fps; + c->fps = mf_fps; c->reliable_fps = true; demux_add_sh_stream(demuxer, sh); diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index da15c0fc0f..95eab29ec9 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -43,7 +43,7 @@ #include "mpv_talloc.h" #include "common/av_common.h" -#include "options/options.h" +#include "options/m_config.h" #include "options/m_option.h" #include "misc/bstr.h" #include "stream/stream.h" @@ -162,6 +162,8 @@ struct block_info { }; typedef struct mkv_demuxer { + struct demux_mkv_opts *opts; + int64_t segment_start, segment_end; double duration; @@ -179,6 +181,9 @@ typedef struct mkv_demuxer { mkv_index_t *indexes; size_t num_indexes; bool index_complete; + int index_mode; + + int edition_id; struct header_elem { int32_t id; @@ -747,11 +752,10 @@ static void add_block_position(demuxer_t *demuxer, struct mkv_track *track, static int demux_mkv_read_cues(demuxer_t *demuxer) { - struct MPOpts *opts = demuxer->opts; mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; stream_t *s = demuxer->stream; - if (opts->index_mode != 1 || mkv_d->index_complete) { + if (mkv_d->index_mode != 1 || mkv_d->index_complete) { ebml_read_skip(demuxer->log, -1, s); return 0; } @@ -810,9 +814,9 @@ done: static int demux_mkv_read_chapters(struct demuxer *demuxer) { - struct MPOpts *opts = demuxer->opts; + mkv_demuxer_t *mkv_d = demuxer->priv; stream_t *s = demuxer->stream; - int wanted_edition = opts->edition_id; + int wanted_edition = mkv_d->edition_id; uint64_t wanted_edition_uid = demuxer->matroska_data.uid.edition; /* A specific edition UID was requested; ignore the user option which is @@ -1191,10 +1195,9 @@ static int read_deferred_element(struct demuxer *demuxer, static void read_deferred_cues(demuxer_t *demuxer) { - struct MPOpts *opts = demuxer->opts; mkv_demuxer_t *mkv_d = demuxer->priv; - if (mkv_d->index_complete || opts->index_mode != 1) + if (mkv_d->index_complete || mkv_d->index_mode != 1) return; for (int n = 0; n < mkv_d->num_headers; n++) { @@ -1855,7 +1858,6 @@ static int read_mkv_segment_header(demuxer_t *demuxer, int64_t *segment_end) static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check) { stream_t *s = demuxer->stream; - struct MPOpts *opts = demuxer->opts; mkv_demuxer_t *mkv_d; int64_t start_pos; int64_t end_pos; @@ -1882,6 +1884,12 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check) mkv_d->a_skip_preroll = 1; mkv_d->skip_to_timecode = INT64_MIN; + mp_read_option_raw(demuxer->global, "index", &m_option_type_choice, + &mkv_d->index_mode); + mp_read_option_raw(demuxer->global, "edition", &m_option_type_choice, + &mkv_d->edition_id); + mkv_d->opts = mp_get_config_group(mkv_d, demuxer->global, &demux_mkv_conf); + if (demuxer->params && demuxer->params->matroska_was_valid) *demuxer->params->matroska_was_valid = true; @@ -1941,7 +1949,7 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check) process_tags(demuxer); probe_first_timestamp(demuxer); - if (opts->demux_mkv->probe_duration) + if (mkv_d->opts->probe_duration) probe_last_timestamp(demuxer, start_pos); return 0; @@ -2730,7 +2738,6 @@ static int create_index_until(struct demuxer *demuxer, int64_t timecode) static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id, int64_t target_timecode, int flags) { - struct MPOpts *opts = demuxer->opts; struct mkv_demuxer *mkv_d = demuxer->priv; struct mkv_index *index = NULL; @@ -2758,9 +2765,9 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id, if (flags & FLAG_SUBPREROLL) { // Find the cluster with the highest filepos, that has a timestamp // still lower than min_tc. - double secs = opts->demux_mkv->subtitle_preroll_secs; + double secs = mkv_d->opts->subtitle_preroll_secs; if (mkv_d->index_has_durations) - secs = MPMAX(secs, opts->demux_mkv->subtitle_preroll_secs_index); + secs = MPMAX(secs, mkv_d->opts->subtitle_preroll_secs_index); int64_t pre = MPMIN(INT64_MAX, secs * 1e9 / mkv_d->tc_scale); int64_t min_tc = pre < index->timecode ? index->timecode - pre : 0; uint64_t prev_target = 0; @@ -2823,7 +2830,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, double seek_pts, int flags) int cueflags = (flags & SEEK_BACKWARD) ? FLAG_BACKWARD : 0; mkv_d->subtitle_preroll = NUM_SUB_PREROLL_PACKETS; - int preroll_opt = demuxer->opts->demux_mkv->subtitle_preroll; + int preroll_opt = mkv_d->opts->subtitle_preroll; if (((flags & SEEK_HR) || preroll_opt == 1 || (preroll_opt == 2 && mkv_d->index_has_durations)) && st_active[STREAM_SUB] && st_active[STREAM_VIDEO]) @@ -2917,7 +2924,7 @@ static void probe_last_timestamp(struct demuxer *demuxer, int64_t start_pos) // In full mode, we start reading data from the current file position, // which works because this function is called after headers are parsed. - if (demuxer->opts->demux_mkv->probe_duration != 2) { + if (mkv_d->opts->probe_duration != 2) { read_deferred_cues(demuxer); if (mkv_d->index_complete) { // Find last cluster that still has video packets @@ -2974,7 +2981,7 @@ static void probe_first_timestamp(struct demuxer *demuxer) { mkv_demuxer_t *mkv_d = demuxer->priv; - if (!demuxer->opts->demux_mkv->probe_start_time) + if (!mkv_d->opts->probe_start_time) return; struct block_info block; diff --git a/demux/demux_mkv_timeline.c b/demux/demux_mkv_timeline.c index 256e009753..30d669c77f 100644 --- a/demux/demux_mkv_timeline.c +++ b/demux/demux_mkv_timeline.c @@ -32,10 +32,10 @@ #include "mpv_talloc.h" #include "common/msg.h" -#include "common/global.h" #include "demux/demux.h" #include "demux/timeline.h" #include "demux/matroska.h" +#include "options/m_config.h" #include "options/options.h" #include "options/path.h" #include "misc/bstr.h" @@ -46,6 +46,7 @@ struct tl_ctx { struct mp_log *log; struct mpv_global *global; + struct MPOpts *opts; struct timeline *tl; struct demuxer *demuxer; @@ -209,8 +210,7 @@ static bool check_file_seg(struct tl_ctx *ctx, char *filename, int segment) MP_TARRAY_APPEND(NULL, ctx->sources, ctx->num_sources, NULL); } - if (stream_wants_cache(d->stream, &ctx->global->opts->stream_cache)) - { + if (stream_wants_cache(d->stream, ctx->opts->stream_cache)) { free_demuxer_and_stream(d); params.disable_cache = false; params.matroska_wanted_uids = ctx->uids; // potentially reallocated, same data @@ -247,7 +247,7 @@ static bool missing(struct tl_ctx *ctx) static void find_ordered_chapter_sources(struct tl_ctx *ctx) { - struct MPOpts *opts = ctx->global->opts; + struct MPOpts *opts = ctx->opts; void *tmp = talloc_new(NULL); int num_filenames = 0; char **filenames = NULL; @@ -317,7 +317,7 @@ static int64_t add_timeline_part(struct tl_ctx *ctx, * early; we don't want to try seeking over a one frame gap. */ int64_t join_diff = start - ctx->last_end_time; if (ctx->num_parts == 0 - || FFABS(join_diff) > ctx->global->opts->chapter_merge_threshold * 1e6 + || FFABS(join_diff) > ctx->opts->chapter_merge_threshold * 1e6 || source != ctx->timeline[ctx->num_parts - 1].source) { struct timeline_part new = { @@ -505,20 +505,22 @@ void build_ordered_chapter_timeline(struct timeline *tl) if (!demuxer->matroska_data.ordered_chapters) return; - if (!demuxer->global->opts->ordered_chapters) { - MP_INFO(demuxer, "File uses ordered chapters, but " - "you have disabled support for them. Ignoring.\n"); - return; - } - struct tl_ctx *ctx = talloc_ptrtype(tl, ctx); *ctx = (struct tl_ctx){ .log = tl->log, .global = tl->global, .tl = tl, .demuxer = demuxer, + .opts = mp_get_config_group(ctx, tl->global, NULL), }; + if (!ctx->opts->ordered_chapters) { + MP_INFO(demuxer, "File uses ordered chapters, but " + "you have disabled support for them. Ignoring.\n"); + talloc_free(ctx); + return; + } + MP_INFO(ctx, "File uses ordered chapters, will build edit timeline.\n"); struct matroska_data *m = &demuxer->matroska_data; diff --git a/demux/demux_raw.c b/demux/demux_raw.c index 51378e7031..674d4e7fea 100644 --- a/demux/demux_raw.c +++ b/demux/demux_raw.c @@ -22,8 +22,8 @@ #include <unistd.h> #include <string.h> +#include "options/m_config.h" #include "options/m_option.h" -#include "options/options.h" #include "stream/stream.h" #include "demux.h" @@ -129,7 +129,8 @@ struct priv { static int demux_rawaudio_open(demuxer_t *demuxer, enum demux_check check) { - struct demux_rawaudio_opts *opts = demuxer->opts->demux_rawaudio; + struct demux_rawaudio_opts *opts = + mp_get_config_group(demuxer, demuxer->global, &demux_rawaudio_conf); if (check != DEMUX_CHECK_REQUEST && check != DEMUX_CHECK_FORCE) return -1; @@ -169,7 +170,8 @@ static int demux_rawaudio_open(demuxer_t *demuxer, enum demux_check check) static int demux_rawvideo_open(demuxer_t *demuxer, enum demux_check check) { - struct demux_rawvideo_opts *opts = demuxer->opts->demux_rawvideo; + struct demux_rawvideo_opts *opts = + mp_get_config_group(demuxer, demuxer->global, &demux_rawvideo_conf); if (check != DEMUX_CHECK_REQUEST && check != DEMUX_CHECK_FORCE) return -1; |