summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-08-21 14:56:07 +0200
committerwm4 <wm4@nowhere>2017-08-21 14:56:07 +0200
commit028faacff56d7f90f6b119b0b0ac686fd614825f (patch)
tree33d77aa61946f3bebfdb28fa8670065fdb79aed8 /video
parent82d9419f62c90cecc13c492e3b68feebe0229daa (diff)
downloadmpv-028faacff56d7f90f6b119b0b0ac686fd614825f.tar.bz2
mpv-028faacff56d7f90f6b119b0b0ac686fd614825f.tar.xz
video: add metadata handling for spherical video
This adds handling of spherical video metadata: retrieving it from demux_lavf and demux_mkv, passing it through filters, and adjusting it with vf_format. This does not include support for rendering this type of video. We don't expect we need/want to support the other projection types like cube maps, so we don't include that for now. They can be added later as needed. Also raise the maximum sizes of stringified image params, since they can get really long.
Diffstat (limited to 'video')
-rw-r--r--video/decode/dec_video.c4
-rw-r--r--video/filter/vf.c2
-rw-r--r--video/filter/vf_format.c15
-rw-r--r--video/mp_image.c28
-rw-r--r--video/mp_image.h17
5 files changed, 63 insertions, 3 deletions
diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c
index 8211d1f3b2..04e428246b 100644
--- a/video/decode/dec_video.c
+++ b/video/decode/dec_video.c
@@ -244,6 +244,10 @@ static void fix_image_params(struct dec_video *d_video,
p.color.sig_peak = 0.0;
}
+ p.spherical = c->spherical;
+ if (p.spherical.type == MP_SPHERICAL_AUTO)
+ p.spherical.type = MP_SPHERICAL_NONE;
+
// Guess missing colorspace fields from metadata. This guarantees all
// fields are at least set to legal values afterwards.
mp_image_params_guess_csp(&p);
diff --git a/video/filter/vf.c b/video/filter/vf.c
index a126007498..0db6f2a286 100644
--- a/video/filter/vf.c
+++ b/video/filter/vf.c
@@ -224,7 +224,7 @@ void vf_print_filter_chain(struct vf_chain *c, int msglevel,
return;
for (vf_instance_t *f = c->first; f; f = f->next) {
- char b[128] = {0};
+ char b[256] = {0};
mp_snprintf_cat(b, sizeof(b), " [%s] ", f->full_name);
if (f->label)
mp_snprintf_cat(b, sizeof(b), "\"%s\" ", f->label);
diff --git a/video/filter/vf_format.c b/video/filter/vf_format.c
index 1953b61ab6..581bbe332f 100644
--- a/video/filter/vf_format.c
+++ b/video/filter/vf_format.c
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
+#include <math.h>
#include <libavutil/rational.h>
@@ -46,6 +47,8 @@ struct vf_priv_s {
int rotate;
int dw, dh;
double dar;
+ int spherical;
+ float spherical_ref_angles[3];
};
static bool is_compatible(int fmt1, int fmt2)
@@ -127,6 +130,13 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
dsize = av_d2q(p->dar, INT_MAX);
mp_image_params_set_dsize(out, dsize.num, dsize.den);
+ if (p->spherical)
+ out->spherical.type = p->spherical;
+ for (int n = 0; n < 3; n++) {
+ if (isfinite(p->spherical_ref_angles[n]))
+ out->spherical.ref_angles[n] = p->spherical_ref_angles[n];
+ }
+
// Make sure the user-overrides are consistent (no RGB csp for YUV, etc.).
mp_image_params_guess_csp(out);
@@ -165,6 +175,10 @@ static const m_option_t vf_opts_fields[] = {
OPT_INT("dw", dw, 0),
OPT_INT("dh", dh, 0),
OPT_DOUBLE("dar", dar, 0),
+ OPT_CHOICE_C("spherical", spherical, 0, mp_spherical_names),
+ OPT_FLOAT("spherical-yaw", spherical_ref_angles[0], 0),
+ OPT_FLOAT("spherical-pitch", spherical_ref_angles[1], 0),
+ OPT_FLOAT("spherical-roll", spherical_ref_angles[2], 0),
OPT_REMOVED("outputlevels", "use the --video-output-levels global option"),
OPT_REMOVED("peak", "use sig-peak instead (changed value scale!)"),
{0}
@@ -178,5 +192,6 @@ const vf_info_t vf_info_format = {
.options = vf_opts_fields,
.priv_defaults = &(const struct vf_priv_s){
.rotate = -1,
+ .spherical_ref_angles = {NAN, NAN, NAN},
},
};
diff --git a/video/mp_image.c b/video/mp_image.c
index 765289f8ff..45e5330947 100644
--- a/video/mp_image.c
+++ b/video/mp_image.c
@@ -41,6 +41,14 @@
#define HAVE_OPAQUE_REF (LIBAVUTIL_VERSION_MICRO >= 100 && \
LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 47, 100))
+const struct m_opt_choice_alternatives mp_spherical_names[] = {
+ {"auto", MP_SPHERICAL_AUTO},
+ {"none", MP_SPHERICAL_NONE},
+ {"unknown", MP_SPHERICAL_UNKNOWN},
+ {"equirect", MP_SPHERICAL_EQUIRECTANGULAR},
+ {0}
+};
+
// Determine strides, plane sizes, and total required size for an image
// allocation. Returns total size on success, <0 on error. Unused planes
// have out_stride/out_plane_size to 0, and out_plane_offset set to -1 up
@@ -525,6 +533,7 @@ void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src)
dst->params.color.levels = src->params.color.levels;
dst->params.chroma_location = src->params.chroma_location;
}
+ dst->params.spherical = src->params.spherical;
mp_image_params_guess_csp(&dst->params); // ensure colorspace consistency
if ((dst->fmt.flags & MP_IMGFLAG_PAL) && (src->fmt.flags & MP_IMGFLAG_PAL)) {
if (dst->planes[1] && src->planes[1]) {
@@ -657,6 +666,12 @@ char *mp_image_params_to_str_buf(char *b, size_t bs,
MP_STEREO3D_NAME_DEF(p->stereo_in, "?"),
MP_STEREO3D_NAME_DEF(p->stereo_out, "?"));
}
+ if (p->spherical.type != MP_SPHERICAL_NONE) {
+ const float *a = p->spherical.ref_angles;
+ mp_snprintf_cat(b, bs, " (%s %f/%f/%f)",
+ m_opt_choice_str(mp_spherical_names, p->spherical.type),
+ a[0], a[1], a[2]);
+ }
} else {
snprintf(b, bs, "???");
}
@@ -691,6 +706,16 @@ bool mp_image_params_valid(const struct mp_image_params *p)
return true;
}
+static bool mp_spherical_equal(const struct mp_spherical_params *p1,
+ const struct mp_spherical_params *p2)
+{
+ for (int n = 0; n < 3; n++) {
+ if (p1->ref_angles[n] != p2->ref_angles[n])
+ return false;
+ }
+ return p1->type == p2->type;
+}
+
bool mp_image_params_equal(const struct mp_image_params *p1,
const struct mp_image_params *p2)
{
@@ -702,7 +727,8 @@ bool mp_image_params_equal(const struct mp_image_params *p1,
p1->chroma_location == p2->chroma_location &&
p1->rotate == p2->rotate &&
p1->stereo_in == p2->stereo_in &&
- p1->stereo_out == p2->stereo_out;
+ p1->stereo_out == p2->stereo_out &&
+ mp_spherical_equal(&p1->spherical, &p2->spherical);
}
// Set most image parameters, but not image format or size.
diff --git a/video/mp_image.h b/video/mp_image.h
index 640e2709e9..53b25c5999 100644
--- a/video/mp_image.h
+++ b/video/mp_image.h
@@ -36,6 +36,20 @@
#define MP_IMGFIELD_REPEAT_FIRST 0x04
#define MP_IMGFIELD_INTERLACED 0x20
+enum mp_spherical_type {
+ MP_SPHERICAL_AUTO = 0,
+ MP_SPHERICAL_NONE, // normal video
+ MP_SPHERICAL_UNKNOWN, // unknown projection
+ MP_SPHERICAL_EQUIRECTANGULAR, // (untiled)
+};
+
+extern const struct m_opt_choice_alternatives mp_spherical_names[];
+
+struct mp_spherical_params {
+ enum mp_spherical_type type;
+ float ref_angles[3]; // yaw/pitch/roll, refer to AVSphericalMapping
+};
+
// Describes image parameters that usually stay constant.
// New fields can be added in the future. Code changing the parameters should
// usually copy the whole struct, so that fields added later will be preserved.
@@ -50,6 +64,7 @@ struct mp_image_params {
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
+ struct mp_spherical_params spherical;
};
/* Memory management:
@@ -144,7 +159,7 @@ void mp_image_params_guess_csp(struct mp_image_params *params);
char *mp_image_params_to_str_buf(char *b, size_t bs,
const struct mp_image_params *p);
-#define mp_image_params_to_str(p) mp_image_params_to_str_buf((char[99]){0}, 99, p)
+#define mp_image_params_to_str(p) mp_image_params_to_str_buf((char[256]){0}, 256, p)
bool mp_image_params_valid(const struct mp_image_params *p);
bool mp_image_params_equal(const struct mp_image_params *p1,