summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/options.rst16
-rw-r--r--TOOLS/lib/Parse/Matroska/Definitions.pm1
-rw-r--r--demux/demux_mkv.c12
-rw-r--r--demux/stheader.h1
-rw-r--r--options/m_option.c53
-rw-r--r--options/m_option.h6
-rw-r--r--options/options.c1
-rw-r--r--options/options.h1
-rw-r--r--player/video.c12
-rw-r--r--video/csputils.c22
-rw-r--r--video/csputils.h11
-rw-r--r--video/decode/vd_lavc.c2
-rw-r--r--video/filter/vf_stereo3d.c2
-rw-r--r--video/mp_image.c6
-rw-r--r--video/mp_image.h2
15 files changed, 146 insertions, 2 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 0062165f0c..87f7eb54b2 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -561,6 +561,22 @@ Video
which means the value ``0`` would rotate the video according to the
rotation metadata.)
+``--video-stereo-mode=<mode>``
+ Set the stereo 3D output mode (default: ``mono``). This is done by inserting
+ the ``stereo3d`` conversion filter.
+
+ The mode ``mono`` is an alias to ``ml``, which refers to the left frame in
+ 2D. This is the default, which means mpv will try to show 3D movies in 2D,
+ instead of the mangled 3D image not intended for consumption (such as
+ showing the left and right frame side by side, etc.).
+
+ The pseudo-mode ``none`` disables automatic conversion completely.
+
+ Use ``--video-stereo-mode=help`` to list all available modes. Check with
+ the ``stereo3d`` filter documentation to see what the names mean. Note that
+ some names refer to modes not supported by ``stereo3d`` - these modes can
+ appear in files, but can't be handled properly by mpv.
+
``--video-zoom=<value>``
Adjust the video display scale factor by the given value. The unit is in
fractions of the (scaled) window video size.
diff --git a/TOOLS/lib/Parse/Matroska/Definitions.pm b/TOOLS/lib/Parse/Matroska/Definitions.pm
index c52c2172b3..081fe5bb97 100644
--- a/TOOLS/lib/Parse/Matroska/Definitions.pm
+++ b/TOOLS/lib/Parse/Matroska/Definitions.pm
@@ -265,6 +265,7 @@ sub define_matroska {
elem('DisplayUnit', '54b2', 'uint'),
elem('FrameRate', '2383e3', 'float'),
elem('ColourSpace', '2eb524', 'binary'),
+ elem('StereoMode', '53b8', 'uint'),
}),
elem('Audio', 'e1', {
elem('SamplingFrequency', 'b5', 'float'),
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index 02efcb2a0a..1f4ef89e34 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -46,6 +46,7 @@
#include "options/options.h"
#include "misc/bstr.h"
#include "stream/stream.h"
+#include "video/csputils.h"
#include "demux.h"
#include "stheader.h"
#include "ebml.h"
@@ -102,6 +103,7 @@ typedef struct mkv_track {
bool v_dwidth_set, v_dheight_set;
double v_frate;
uint32_t colorspace;
+ int stereo_mode;
uint32_t a_formattag;
uint32_t a_channels, a_bps;
@@ -504,6 +506,15 @@ static void parse_trackvideo(struct demuxer *demuxer, struct mkv_track *track,
MP_VERBOSE(demuxer, "| + Colorspace: %#x\n",
(unsigned int)track->colorspace);
}
+ if (video->n_stereo_mode) {
+ const char *name = MP_STEREO3D_NAME(video->stereo_mode);
+ if (name) {
+ track->stereo_mode = video->stereo_mode;
+ MP_VERBOSE(demuxer, "| + StereoMode: %s\n", name);
+ } else {
+ MP_WARN(demuxer, "Unknown StereoMode: %d\n", (int)video->stereo_mode);
+ }
+ }
}
/**
@@ -1276,6 +1287,7 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
}
MP_VERBOSE(demuxer, "Aspect: %f\n", sh_v->aspect);
sh_v->avi_dts = track->ms_compat;
+ sh_v->stereo_mode = track->stereo_mode;
return 0;
}
diff --git a/demux/stheader.h b/demux/stheader.h
index 082fffa5e2..3fc8c999d4 100644
--- a/demux/stheader.h
+++ b/demux/stheader.h
@@ -82,6 +82,7 @@ typedef struct sh_video {
int bitrate; // compressed bits/sec
int disp_w, disp_h; // display size
int rotate; // intended display rotation, in degrees, [0, 359]
+ int stereo_mode; // mp_stereo3d_mode (0 if none/unknown)
MP_BITMAPINFOHEADER *bih;
} sh_video_t;
diff --git a/options/m_option.c b/options/m_option.c
index 6ab1fc1f7a..a84d7e4d41 100644
--- a/options/m_option.c
+++ b/options/m_option.c
@@ -1983,6 +1983,59 @@ const m_option_type_t m_option_type_imgfmt = {
.copy = copy_opt,
};
+#include "video/csputils.h"
+
+static int parse_stereo_mode(struct mp_log *log, const m_option_t *opt,
+ struct bstr name, struct bstr param, void *dst)
+{
+ if (param.len == 0)
+ return M_OPT_MISSING_PARAM;
+
+ if (!bstrcmp0(param, "help")) {
+ mp_info(log, "Available modes:");
+ for (int n = 0; n < MP_STEREO3D_COUNT; n++) {
+ if (mp_stereo3d_names[n])
+ mp_info(log, " %s\n", mp_stereo3d_names[n]);
+ }
+ mp_info(log, " none\n");
+ return M_OPT_EXIT - 1;
+ }
+
+ int mode = -1;
+
+ for (int n = 0; n < MP_STEREO3D_COUNT; n++) {
+ if (bstr_equals(param, bstr0(mp_stereo3d_names[n]))) {
+ mode = n;
+ break;
+ }
+ }
+
+ if (mode < 0 && !bstr_equals0(param, "none")) {
+ mp_err(log, "Option %.*s: unknown parameter: '%.*s'\n",
+ BSTR_P(name), BSTR_P(param));
+ return M_OPT_INVALID;
+ }
+
+ if (dst)
+ *((int *)dst) = mode;
+
+ return 1;
+}
+
+static char *print_stereo_mode(const m_option_t *opt, const void *val)
+{
+ int mode = *(int *)val;
+ const char *name = mode >= 0 ? MP_STEREO3D_NAME(mode) : "none";
+ return talloc_strdup(NULL, name);
+}
+
+const m_option_type_t m_option_vid_stereo_mode = {
+ .name = "Stereo 3D mode",
+ .size = sizeof(int),
+ .parse = parse_stereo_mode,
+ .print = print_stereo_mode,
+};
+
static int parse_fourcc(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param, void *dst)
{
diff --git a/options/m_option.h b/options/m_option.h
index d0ca211aa1..d7541a5c73 100644
--- a/options/m_option.h
+++ b/options/m_option.h
@@ -56,6 +56,7 @@ extern const m_option_type_t m_option_type_msglevels;
extern const m_option_type_t m_option_type_print_fn;
extern const m_option_type_t m_option_type_subconfig;
extern const m_option_type_t m_option_type_imgfmt;
+extern const m_option_type_t m_option_vid_stereo_mode;
extern const m_option_type_t m_option_type_fourcc;
extern const m_option_type_t m_option_type_afmt;
extern const m_option_type_t m_option_type_color;
@@ -648,8 +649,11 @@ extern const char m_option_path_separator;
#define OPT_TRACKCHOICE(name, var) \
OPT_CHOICE_OR_INT(name, var, 0, 1, 8190, ({"no", -2}, {"auto", -1}))
+#define OPT_VID_STEREO_MODE(...) \
+ OPT_GENERAL(int, __VA_ARGS__, .type = &m_option_vid_stereo_mode)
+
#define OPT_STRING_VALIDATE_(optname, varname, flags, validate_fn, ...) \
- OPT_GENERAL(char*, optname, varname, flags, __VA_ARGS__, \
+ OPT_GENERAL(char*, optname, varname, flags, __VA_ARGS__, \
.priv = MP_EXPECT_TYPE(m_opt_string_validate_fn, validate_fn))
#define OPT_STRING_VALIDATE(...) \
OPT_STRING_VALIDATE_(__VA_ARGS__, .type = &m_option_type_string)
diff --git a/options/options.c b/options/options.c
index 0f97528ba1..00c8c0fbb5 100644
--- a/options/options.c
+++ b/options/options.c
@@ -415,6 +415,7 @@ const m_option_t mp_opts[] = {
{"BT.2020", MP_CSP_PRIM_BT_2020})),
OPT_CHOICE_OR_INT("video-rotate", video_rotate, 0, 0, 359,
({"no", -1})),
+ OPT_VID_STEREO_MODE("video-stereo-mode", video_stereo_mode, 0),
OPT_CHOICE_OR_INT("cursor-autohide", cursor_autohide_delay, 0,
0, 30000, ({"no", -1}, {"always", -2})),
diff --git a/options/options.h b/options/options.h
index 4468d2abbd..701c9e236b 100644
--- a/options/options.h
+++ b/options/options.h
@@ -98,6 +98,7 @@ typedef struct MPOpts {
int requested_primaries;
int video_rotate;
+ int video_stereo_mode;
char *audio_decoders;
char *video_decoders;
diff --git a/player/video.c b/player/video.c
index 7aaef07f4f..f36a41b8f7 100644
--- a/player/video.c
+++ b/player/video.c
@@ -157,6 +157,18 @@ static void filter_reconfig(struct MPContext *mpctx,
}
}
}
+
+ if (params.stereo_in != params.stereo_out &&
+ params.stereo_in > 0 && params.stereo_out >= 0)
+ {
+ char *from = MP_STEREO3D_NAME(params.stereo_in);
+ char *to = MP_STEREO3D_NAME(params.stereo_out);
+ if (from && to) {
+ char *args[] = {"in", from, "out", to, NULL, NULL};
+ if (try_filter(mpctx, params, "stereo3d", "stereo3d", args) < 0)
+ MP_ERR(mpctx, "Can't insert 3D conversion filter.\n");
+ }
+ }
}
static void recreate_video_filters(struct MPContext *mpctx)
diff --git a/video/csputils.c b/video/csputils.c
index 1cbaf47de9..d07b3a096e 100644
--- a/video/csputils.c
+++ b/video/csputils.c
@@ -77,6 +77,28 @@ const char *const mp_chroma_names[MP_CHROMA_COUNT] = {
"mpeg1/jpeg",
};
+// The short name _must_ match with what vf_stereo3d accepts (if supported).
+// The long name is closer to the Matroska spec (StereoMode element).
+// If you add entries that don't match Matroska, make sure demux_mkv.c rejects
+// them properly.
+// The long name is unused.
+#define E(index, short, long) [index] = short
+const char *const mp_stereo3d_names[MP_STEREO3D_COUNT] = {
+ E(0, "mono", "mono"), // unsupported by vf_stereo3d
+ E(1, "sbs2l", "side_by_side_left"),
+ E(2, "abr", "top_bottom_right"),
+ E(3, "abl", "top_bottom_left"),
+ E(4, "checkr", "checkboard_right"), // unsupported by vf_stereo3d
+ E(5, "checkl", "checkboard_left"),
+ E(6, "irr", "row_interleaved_right"),
+ E(7, "irl", "row_interleaved_left"),
+ E(8, "icr", "column_interleaved_right"),// unsupported by vf_stereo3d
+ E(9, "icl", "column_interleaved_left"), // unsupported by vf_stereo3d
+ E(10, "arcc", "anaglyph_cyan_red"), // Matroska: unclear which mode
+ E(11, "sbs2r", "side_by_side_right"),
+ E(12, "agmc", "anaglyph_green_magenta"), // Matroska: unclear which mode
+};
+
enum mp_csp avcol_spc_to_mp_csp(int avcolorspace)
{
switch (avcolorspace) {
diff --git a/video/csputils.h b/video/csputils.h
index 757ac72cdc..1a559ebfd2 100644
--- a/video/csputils.h
+++ b/video/csputils.h
@@ -79,6 +79,17 @@ enum mp_render_intent {
MP_INTENT_ABSOLUTE_COLORIMETRIC = 3
};
+enum mp_stereo3d_mode {
+ MP_STEREO3D_INVALID = -1,
+ MP_STEREO3D_MONO = 0,
+ MP_STEREO3D_COUNT = 13, // 12 is last valid mode
+};
+
+extern const char *const mp_stereo3d_names[MP_STEREO3D_COUNT];
+
+#define MP_STEREO3D_NAME(x) \
+ ((x) >= 0 && (x) < MP_STEREO3D_COUNT ? (char *)mp_stereo3d_names[(x)] : NULL)
+
struct mp_csp_details {
enum mp_csp format;
enum mp_csp_levels levels_in; // encoded video
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 1d33742bc5..45ae9fce94 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -485,6 +485,7 @@ static void update_image_params(struct dec_video *vd, AVFrame *frame,
.chroma_location =
avchroma_location_to_mp(ctx->avctx->chroma_sample_location),
.rotate = vd->header->video->rotate,
+ .stereo_in = vd->header->video->stereo_mode,
};
if (opts->video_rotate < 0) {
@@ -492,6 +493,7 @@ static void update_image_params(struct dec_video *vd, AVFrame *frame,
} else {
out_params->rotate = (out_params->rotate + opts->video_rotate) % 360;
}
+ out_params->stereo_out = opts->video_stereo_mode;
}
static enum AVPixelFormat get_format_hwdec(struct AVCodecContext *avctx,
diff --git a/video/filter/vf_stereo3d.c b/video/filter/vf_stereo3d.c
index 15d2095f5d..fcf583eef4 100644
--- a/video/filter/vf_stereo3d.c
+++ b/video/filter/vf_stereo3d.c
@@ -445,6 +445,8 @@ const struct m_opt_choice_alternatives stereo_code_names[] = {
{"interleave_rows_left_first", INTERLEAVE_ROWS_LR},
{"irr", INTERLEAVE_ROWS_RL},
{"interleave_rows_right_first", INTERLEAVE_ROWS_RL},
+ // convenience alias for MP_STEREO3D_MONO
+ {"mono", MONO_L},
{ NULL, 0}
};
diff --git a/video/mp_image.c b/video/mp_image.c
index d83a9ae3c1..7b430dfaf6 100644
--- a/video/mp_image.c
+++ b/video/mp_image.c
@@ -364,6 +364,8 @@ void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src)
dst->fields = src->fields;
dst->qscale_type = src->qscale_type;
dst->pts = src->pts;
+ dst->params.stereo_in = src->params.stereo_in;
+ dst->params.stereo_out = src->params.stereo_out;
if (dst->w == src->w && dst->h == src->h) {
dst->params.d_w = src->params.d_w;
dst->params.d_h = src->params.d_h;
@@ -489,7 +491,9 @@ bool mp_image_params_equal(const struct mp_image_params *p1,
p1->outputlevels == p2->outputlevels &&
p1->primaries == p2->primaries &&
p1->chroma_location == p2->chroma_location &&
- p1->rotate == p2->rotate;
+ p1->rotate == p2->rotate &&
+ p1->stereo_in == p2->stereo_in &&
+ p1->stereo_out == p2->stereo_out;
}
// Set most image parameters, but not image format or size.
diff --git a/video/mp_image.h b/video/mp_image.h
index 5ab12ae3d8..9cdc7fdf77 100644
--- a/video/mp_image.h
+++ b/video/mp_image.h
@@ -55,6 +55,8 @@ struct mp_image_params {
enum mp_csp_levels outputlevels;
// The image should be rotated clockwise (0-359 degrees).
int rotate;
+ enum mp_stereo3d_mode stereo_in; // image is encoded with this mode
+ enum mp_stereo3d_mode stereo_out; // should be displayed with this mode
};
/* Memory management: