summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demux/demux.c56
-rw-r--r--demux/demux.h1
-rw-r--r--demux/demux_lavf.c63
-rw-r--r--demux/demux_mf.c14
-rw-r--r--demux/demux_mkv.c37
-rw-r--r--demux/demux_mkv_timeline.c24
-rw-r--r--demux/demux_raw.c8
-rw-r--r--options/options.c85
-rw-r--r--options/options.h23
-rw-r--r--player/main.c6
-rw-r--r--stream/stream.c16
-rw-r--r--stream/stream.h5
-rw-r--r--stream/stream_lavf.c71
13 files changed, 241 insertions, 168 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;
diff --git a/options/options.c b/options/options.c
index b620ab9bc3..20153405cd 100644
--- a/options/options.c
+++ b/options/options.c
@@ -76,6 +76,8 @@ extern const struct m_sub_options encode_config;
extern const struct m_sub_options gl_video_conf;
extern const struct m_sub_options ao_alsa_conf;
+extern const struct m_sub_options demux_conf;
+
extern const struct m_obj_list vf_obj_list;
extern const struct m_obj_list af_obj_list;
extern const struct m_obj_list vo_obj_list;
@@ -105,6 +107,35 @@ static const struct m_sub_options screenshot_conf = {
.defaults = &image_writer_opts_defaults,
};
+#define OPT_BASE_STRUCT struct mp_cache_opts
+
+const struct m_sub_options stream_cache_conf = {
+ .opts = (const struct m_option[]){
+ OPT_CHOICE_OR_INT("cache", size, 0, 32, 0x7fffffff,
+ ({"no", 0},
+ {"auto", -1},
+ {"yes", -2})),
+ OPT_CHOICE_OR_INT("cache-default", def_size, 0, 32, 0x7fffffff,
+ ({"no", 0})),
+ OPT_INTRANGE("cache-initial", initial, 0, 0, 0x7fffffff),
+ OPT_INTRANGE("cache-seek-min", seek_min, 0, 0, 0x7fffffff),
+ OPT_INTRANGE("cache-backbuffer", back_buffer, 0, 0, 0x7fffffff),
+ OPT_STRING("cache-file", file, M_OPT_FILE),
+ OPT_INTRANGE("cache-file-size", file_max, 0, 0, 0x7fffffff),
+ {0}
+ },
+ .size = sizeof(struct mp_cache_opts),
+ .defaults = &(const struct mp_cache_opts){
+ .size = -1,
+ .def_size = 75000,
+ .initial = 0,
+ .seek_min = 500,
+ .back_buffer = 75000,
+ .file_max = 1024 * 1024,
+ },
+};
+
+#undef OPT_BASE_STRUCT
#define OPT_BASE_STRUCT struct mp_vo_opts
static const m_option_t mp_vo_opt_list[] = {
@@ -240,17 +271,7 @@ const m_option_t mp_opts[] = {
// ------------------------- stream options --------------------
- OPT_CHOICE_OR_INT("cache", stream_cache.size, 0, 32, 0x7fffffff,
- ({"no", 0},
- {"auto", -1},
- {"yes", -2})),
- OPT_CHOICE_OR_INT("cache-default", stream_cache.def_size, 0, 32, 0x7fffffff,
- ({"no", 0})),
- OPT_INTRANGE("cache-initial", stream_cache.initial, 0, 0, 0x7fffffff),
- OPT_INTRANGE("cache-seek-min", stream_cache.seek_min, 0, 0, 0x7fffffff),
- OPT_INTRANGE("cache-backbuffer", stream_cache.back_buffer, 0, 0, 0x7fffffff),
- OPT_STRING("cache-file", stream_cache.file, M_OPT_FILE),
- OPT_INTRANGE("cache-file-size", stream_cache.file_max, 0, 0, 0x7fffffff),
+ OPT_SUBSTRUCT("", stream_cache, stream_cache_conf, 0),
#if HAVE_DVDREAD || HAVE_DVDNAV
OPT_STRING("dvd-device", dvd_device, M_OPT_FILE),
@@ -265,22 +286,6 @@ const m_option_t mp_opts[] = {
OPT_INTRANGE("bluray-angle", bluray_angle, 0, 0, 999),
#endif /* HAVE_LIBBLURAY */
- OPT_STRINGLIST("http-header-fields", network_http_header_fields, 0),
- OPT_STRING("user-agent", network_useragent, 0),
- OPT_STRING("referrer", network_referrer, 0),
- OPT_FLAG("cookies", network_cookies_enabled, 0),
- OPT_STRING("cookies-file", network_cookies_file, M_OPT_FILE),
- OPT_CHOICE("rtsp-transport", network_rtsp_transport, 0,
- ({"lavf", 0},
- {"udp", 1},
- {"tcp", 2},
- {"http", 3})),
- OPT_FLAG("tls-verify", network_tls_verify, 0),
- OPT_STRING("tls-ca-file", network_tls_ca_file, M_OPT_FILE),
- OPT_STRING("tls-cert-file", network_tls_cert_file, M_OPT_FILE),
- OPT_STRING("tls-key-file", network_tls_key_file, M_OPT_FILE),
- OPT_DOUBLE("network-timeout", network_timeout, M_OPT_MIN, .min = 0),
-
// ------------------------- demuxer options --------------------
OPT_CHOICE_OR_INT("frames", play_frames, M_OPT_FIXED, 0, INT_MAX,
@@ -342,13 +347,6 @@ const m_option_t mp_opts[] = {
OPT_STRING("audio-demuxer", audio_demuxer_name, 0),
OPT_STRING("sub-demuxer", sub_demuxer_name, 0),
OPT_FLAG("demuxer-thread", demuxer_thread, 0),
- OPT_DOUBLE("demuxer-readahead-secs", demuxer_min_secs, M_OPT_MIN, .min = 0),
- OPT_INTRANGE("demuxer-max-packets", demuxer_max_packs, 0, 0, INT_MAX),
- OPT_INTRANGE("demuxer-max-bytes", demuxer_max_bytes, 0, 0, INT_MAX),
-
- OPT_FLAG("force-seekable", force_seekable, 0),
-
- OPT_DOUBLE("cache-secs", demuxer_min_secs_cache, M_OPT_MIN, .min = 0),
OPT_FLAG("cache-pause", cache_pausing, 0),
OPT_DOUBLE("mf-fps", mf_fps, 0),
@@ -417,7 +415,7 @@ const m_option_t mp_opts[] = {
OPT_SUBSTRUCT("vd-lavc", vd_lavc_params, vd_lavc_conf, 0),
OPT_SUBSTRUCT("ad-lavc", ad_lavc_params, ad_lavc_conf, 0),
- OPT_SUBSTRUCT("demuxer-lavf", demux_lavf, demux_lavf_conf, 0),
+ OPT_SUBSTRUCT("", demux_lavf, demux_lavf_conf, 0),
OPT_SUBSTRUCT("demuxer-rawaudio", demux_rawaudio, demux_rawaudio_conf, 0),
OPT_SUBSTRUCT("demuxer-rawvideo", demux_rawvideo, demux_rawvideo_conf, 0),
OPT_SUBSTRUCT("demuxer-mkv", demux_mkv, demux_mkv_conf, 0),
@@ -429,7 +427,6 @@ const m_option_t mp_opts[] = {
OPT_PATHLIST("audio-file-paths", audiofile_paths, 0),
OPT_STRING_APPEND_LIST("external-file", external_files, M_OPT_FILE),
OPT_FLAG("autoload-files", autoload_files, 0),
- OPT_STRING("sub-codepage", sub_cp, 0),
OPT_FLOAT("sub-delay", sub_delay, 0),
OPT_FLOAT("sub-fps", sub_fps, 0),
OPT_FLOAT("sub-speed", sub_speed, 0),
@@ -652,6 +649,7 @@ const m_option_t mp_opts[] = {
OPT_PRINT("V", print_version),
OPT_SUBSTRUCT("", vo, vo_sub_opts, 0),
+ OPT_SUBSTRUCT("", demux_opts, demux_conf, 0),
#if HAVE_GL
OPT_SUBSTRUCT("", gl_video_opts, gl_video_conf, 0),
@@ -799,22 +797,8 @@ const struct MPOpts mp_default_opts = {
.load_config = 1,
.position_resume = 1,
.autoload_files = 1,
- .stream_cache = {
- .size = -1,
- .def_size = 75000,
- .initial = 0,
- .seek_min = 500,
- .back_buffer = 75000,
- .file_max = 1024 * 1024,
- },
- .demuxer_max_packs = 16000,
- .demuxer_max_bytes = 400 * 1024 * 1024,
.demuxer_thread = 1,
- .demuxer_min_secs = 1.0,
- .network_rtsp_transport = 2,
- .network_timeout = 0.0,
.hls_bitrate = INT_MAX,
- .demuxer_min_secs_cache = 10.0,
.cache_pausing = 1,
.chapterrange = {-1, -1},
.ab_loop = {MP_NOPTS_VALUE, MP_NOPTS_VALUE},
@@ -863,7 +847,6 @@ const struct MPOpts mp_default_opts = {
.ass_shaper = 1,
.use_embedded_fonts = 1,
.sub_fix_timing = 1,
- .sub_cp = "auto",
.screenshot_template = "mpv-shot%n",
.hwdec_codecs = "h264,vc1,wmv3,hevc,mpeg2video,vp9",
diff --git a/options/options.h b/options/options.h
index 376c62e989..45af785518 100644
--- a/options/options.h
+++ b/options/options.h
@@ -149,9 +149,8 @@ typedef struct MPOpts {
int load_config;
char *force_configdir;
int use_filedir_conf;
- int network_rtsp_transport;
int hls_bitrate;
- struct mp_cache_opts stream_cache;
+ struct mp_cache_opts *stream_cache;
int chapterrange[2];
int edition_id;
int correct_pts;
@@ -211,19 +210,13 @@ typedef struct MPOpts {
int stretch_image_subs;
int sub_fix_timing;
- char *sub_cp;
char **audio_files;
char *demuxer_name;
- int demuxer_max_packs;
- int demuxer_max_bytes;
int demuxer_thread;
- double demuxer_min_secs;
char *audio_demuxer_name;
char *sub_demuxer_name;
- int force_seekable;
- double demuxer_min_secs_cache;
int cache_pausing;
struct image_writer_opts *screenshot_image_opts;
@@ -290,17 +283,6 @@ typedef struct MPOpts {
int w32_priority;
- int network_cookies_enabled;
- char *network_cookies_file;
- char *network_useragent;
- char *network_referrer;
- char **network_http_header_fields;
- int network_tls_verify;
- char *network_tls_ca_file;
- char *network_tls_cert_file;
- char *network_tls_key_file;
- double network_timeout;
-
struct tv_params *tv_params;
struct pvr_params *stream_pvr_opts;
struct cdda_params *stream_cdda_opts;
@@ -323,6 +305,8 @@ typedef struct MPOpts {
struct demux_lavf_opts *demux_lavf;
struct demux_mkv_opts *demux_mkv;
+ struct demux_opts *demux_opts;
+
struct vd_lavc_params *vd_lavc_params;
struct ad_lavc_params *ad_lavc_params;
@@ -340,5 +324,6 @@ typedef struct MPOpts {
extern const m_option_t mp_opts[];
extern const struct MPOpts mp_default_opts;
extern const struct m_sub_options vo_sub_opts;
+extern const struct m_sub_options stream_cache_conf;
#endif
diff --git a/player/main.c b/player/main.c
index 315c2978f5..0bf207f5b7 100644
--- a/player/main.c
+++ b/player/main.c
@@ -374,13 +374,9 @@ struct MPContext *mp_create(void)
mpctx->log = mp_log_new(mpctx, mpctx->global->log, "!cplayer");
mpctx->statusline = mp_log_new(mpctx, mpctx->log, "!statusline");
- struct MPOpts *def_opts = talloc_ptrtype(mpctx, def_opts);
- *def_opts = mp_default_opts;
- def_opts->network_useragent = (char *)mpv_version;
-
// Create the config context and register the options
mpctx->mconfig = m_config_new(mpctx, mpctx->log, sizeof(struct MPOpts),
- def_opts, mp_opts);
+ &mp_default_opts, mp_opts);
mpctx->opts = mpctx->mconfig->optstruct;
mpctx->mconfig->includefunc = cfg_include;
mpctx->mconfig->includefunc_ctx = mpctx;
diff --git a/stream/stream.c b/stream/stream.c
index 3ecdfb01ad..6e45f0a549 100644
--- a/stream/stream.c
+++ b/stream/stream.c
@@ -784,7 +784,7 @@ bool stream_wants_cache(stream_t *stream, struct mp_cache_opts *opts)
// return 1 on success, 0 if the cache is disabled/not needed, and -1 on error
// or if the cache is disabled
-int stream_enable_cache(stream_t **stream, struct mp_cache_opts *opts)
+static int stream_enable_cache(stream_t **stream, struct mp_cache_opts *opts)
{
stream_t *orig = *stream;
struct mp_cache_opts use_opts = check_cache_opts(*stream, opts);
@@ -815,6 +815,20 @@ int stream_enable_cache(stream_t **stream, struct mp_cache_opts *opts)
return res;
}
+// Do some crazy stuff to call stream_enable_cache() with the global options.
+int stream_enable_cache_defaults(stream_t **stream)
+{
+ struct mpv_global *global = (*stream)->global;
+ if (!global)
+ return 0;
+ void *tmp = talloc_new(NULL);
+ struct mp_cache_opts *opts =
+ mp_get_config_group(tmp, global, &stream_cache_conf);
+ int r = stream_enable_cache(stream, opts);
+ talloc_free(tmp);
+ return r;
+}
+
static uint16_t stream_read_word_endian(stream_t *s, bool big_endian)
{
unsigned int y = stream_read_char(s);
diff --git a/stream/stream.h b/stream/stream.h
index 1112e09f50..9ee1df25aa 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -223,7 +223,7 @@ void stream_set_capture_file(stream_t *s, const char *filename);
struct mp_cache_opts;
bool stream_wants_cache(stream_t *stream, struct mp_cache_opts *opts);
-int stream_enable_cache(stream_t **stream, struct mp_cache_opts *opts);
+int stream_enable_cache_defaults(stream_t **stream);
// Internal
int stream_cache_init(stream_t *cache, stream_t *stream,
@@ -294,8 +294,7 @@ char *mp_file_get_path(void *talloc_ctx, bstr url);
struct AVDictionary;
void mp_setup_av_network_options(struct AVDictionary **dict,
struct mpv_global *global,
- struct mp_log *log,
- struct MPOpts *opts);
+ struct mp_log *log);
void stream_print_proto_list(struct mp_log *log);
char **stream_get_proto_list(void);
diff --git a/stream/stream_lavf.c b/stream/stream_lavf.c
index d899629571..75508ac009 100644
--- a/stream/stream_lavf.c
+++ b/stream/stream_lavf.c
@@ -19,12 +19,13 @@
#include <libavformat/avio.h>
#include <libavutil/opt.h>
-#include "options/options.h"
#include "options/path.h"
+#include "common/common.h"
#include "common/msg.h"
#include "common/tags.h"
#include "common/av_common.h"
#include "stream.h"
+#include "options/m_config.h"
#include "options/m_option.h"
#include "cookies.h"
@@ -35,14 +36,37 @@
#define OPT_BASE_STRUCT struct stream_lavf_params
struct stream_lavf_params {
char **avopts;
+ int cookies_enabled;
+ char *cookies_file;
+ char *useragent;
+ char *referrer;
+ char **http_header_fields;
+ int tls_verify;
+ char *tls_ca_file;
+ char *tls_cert_file;
+ char *tls_key_file;
+ double timeout;
};
const struct m_sub_options stream_lavf_conf = {
.opts = (const m_option_t[]) {
OPT_KEYVALUELIST("stream-lavf-o", avopts, 0),
+ OPT_STRINGLIST("http-header-fields", http_header_fields, 0),
+ OPT_STRING("user-agent", useragent, 0),
+ OPT_STRING("referrer", referrer, 0),
+ OPT_FLAG("cookies", cookies_enabled, 0),
+ OPT_STRING("cookies-file", cookies_file, M_OPT_FILE),
+ OPT_FLAG("tls-verify", tls_verify, 0),
+ OPT_STRING("tls-ca-file", tls_ca_file, M_OPT_FILE),
+ OPT_STRING("tls-cert-file", tls_cert_file, M_OPT_FILE),
+ OPT_STRING("tls-key-file", tls_key_file, M_OPT_FILE),
+ OPT_DOUBLE("network-timeout", timeout, M_OPT_MIN, .min = 0),
{0}
},
.size = sizeof(struct stream_lavf_params),
+ .defaults = &(const struct stream_lavf_params){
+ .useragent = (char *)mpv_version,
+ },
};
static const char *const http_like[];
@@ -150,50 +174,52 @@ static int interrupt_cb(void *ctx)
static const char * const prefix[] = { "lavf://", "ffmpeg://" };
void mp_setup_av_network_options(AVDictionary **dict, struct mpv_global *global,
- struct mp_log *log, struct MPOpts *opts)
+ struct mp_log *log)
{
void *temp = talloc_new(NULL);
+ struct stream_lavf_params *opts =
+ mp_get_config_group(temp, global, &stream_lavf_conf);
// HTTP specific options (other protocols ignore them)
- if (opts->network_useragent)
- av_dict_set(dict, "user-agent", opts->network_useragent, 0);
- if (opts->network_cookies_enabled) {
- char *file = opts->network_cookies_file;
+ if (opts->useragent)
+ av_dict_set(dict, "user-agent", opts->useragent, 0);
+ if (opts->cookies_enabled) {
+ char *file = opts->cookies_file;
if (file && file[0])
file = mp_get_user_path(temp, global, file);
char *cookies = cookies_lavf(temp, log, file);
if (cookies && cookies[0])
av_dict_set(dict, "cookies", cookies, 0);
}
- av_dict_set(dict, "tls_verify", opts->network_tls_verify ? "1" : "0", 0);
- if (opts->network_tls_ca_file)
- av_dict_set(dict, "ca_file", opts->network_tls_ca_file, 0);
- if (opts->network_tls_cert_file)
- av_dict_set(dict, "cert_file", opts->network_tls_cert_file, 0);
- if (opts->network_tls_key_file)
- av_dict_set(dict, "key_file", opts->network_tls_key_file, 0);
+ av_dict_set(dict, "tls_verify", opts->tls_verify ? "1" : "0", 0);
+ if (opts->tls_ca_file)
+ av_dict_set(dict, "ca_file", opts->tls_ca_file, 0);
+ if (opts->tls_cert_file)
+ av_dict_set(dict, "cert_file", opts->tls_cert_file, 0);
+ if (opts->tls_key_file)
+ av_dict_set(dict, "key_file", opts->tls_key_file, 0);
char *cust_headers = talloc_strdup(temp, "");
- if (opts->network_referrer) {
+ if (opts->referrer) {
cust_headers = talloc_asprintf_append(cust_headers, "Referer: %s\r\n",
- opts->network_referrer);
+ opts->referrer);
}
- if (opts->network_http_header_fields) {
- for (int n = 0; opts->network_http_header_fields[n]; n++) {
+ if (opts->http_header_fields) {
+ for (int n = 0; opts->http_header_fields[n]; n++) {
cust_headers = talloc_asprintf_append(cust_headers, "%s\r\n",
- opts->network_http_header_fields[n]);
+ opts->http_header_fields[n]);
}
}
if (strlen(cust_headers))
av_dict_set(dict, "headers", cust_headers, 0);
av_dict_set(dict, "icy", "1", 0);
// So far, every known protocol uses microseconds for this
- if (opts->network_timeout > 0) {
+ if (opts->timeout > 0) {
char buf[80];
- snprintf(buf, sizeof(buf), "%lld", (long long)(opts->network_timeout * 1e6));
+ snprintf(buf, sizeof(buf), "%lld", (long long)(opts->timeout * 1e6));
av_dict_set(dict, "timeout", buf, 0);
}
- mp_set_avdict(dict, opts->stream_lavf_opts->avopts);
+ mp_set_avdict(dict, opts->avopts);
talloc_free(temp);
}
@@ -215,7 +241,6 @@ static char *normalize_url(void *ta_parent, const char *filename)
static int open_f(stream_t *stream)
{
- struct MPOpts *opts = stream->opts;
AVIOContext *avio = NULL;
int res = STREAM_ERROR;
AVDictionary *dict = NULL;
@@ -255,7 +280,7 @@ static int open_f(stream_t *stream)
filename = talloc_asprintf(temp, "mmsh://%.*s", BSTR_P(b_filename));
}
- mp_setup_av_network_options(&dict, stream->global, stream->log, opts);
+ mp_setup_av_network_options(&dict, stream->global, stream->log);
AVIOInterruptCB cb = {
.callback = interrupt_cb,