summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--player/video.c9
-rw-r--r--video/filter/vf_rotate.c39
-rw-r--r--video/filter/vf_stereo3d.c83
3 files changed, 114 insertions, 17 deletions
diff --git a/player/video.c b/player/video.c
index 61c7914920..3d308ae955 100644
--- a/player/video.c
+++ b/player/video.c
@@ -147,9 +147,7 @@ static void filter_reconfig(struct MPContext *mpctx,
if (params.rotate && (params.rotate % 90 == 0)) {
if (!(mpctx->video_out->driver->caps & VO_CAP_ROTATE90)) {
// Try to insert a rotation filter.
- char deg[10];
- snprintf(deg, sizeof(deg), "%d", params.rotate);
- char *args[] = {"angle", deg, NULL, NULL};
+ char *args[] = {"angle", "auto", NULL};
if (try_filter(mpctx, params, "rotate", "autorotate", args) >= 0) {
params.rotate = 0;
} else {
@@ -161,10 +159,9 @@ 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 (to) {
+ char *args[] = {"in", "auto", "out", to, NULL, NULL};
if (try_filter(mpctx, params, "stereo3d", "stereo3d", args) < 0)
MP_ERR(mpctx, "Can't insert 3D conversion filter.\n");
}
diff --git a/video/filter/vf_rotate.c b/video/filter/vf_rotate.c
index 6328e75722..579c3ea24a 100644
--- a/video/filter/vf_rotate.c
+++ b/video/filter/vf_rotate.c
@@ -32,19 +32,39 @@ struct vf_priv_s {
struct vf_lw_opts *lw_opts;
};
+static const char *const rot[] = {
+ "null",
+ "transpose=clock",
+ "vflip,hflip",
+ "transpose=cclock",
+ "null", // actually set in lavfi_recreate()
+};
+
+static int lavfi_reconfig(struct vf_instance *vf,
+ struct mp_image_params *in,
+ struct mp_image_params *out)
+{
+ struct vf_priv_s *p = vf_lw_old_priv(vf);
+ if (p->angle == 4) { // "auto"
+ int r = in->rotate;
+ if (r < 0 || (r % 90) != 0) {
+ MP_ERR(vf, "Can't apply rotation of %d degrees.\n", r);
+ return -1;
+ }
+ vf_lw_update_graph(vf, NULL, "%s", rot[(r / 90) % 360]);
+ out->rotate = 0;
+ }
+ return 0;
+}
+
static int vf_open(vf_instance_t *vf)
{
struct vf_priv_s *p = vf->priv;
- static const char *const rot[] = {
- "null",
- "transpose=clock",
- "vflip,hflip",
- "transpose=cclock",
- };
-
- if (vf_lw_set_graph(vf, p->lw_opts, NULL, "%s", rot[p->angle]) >= 0)
+ if (vf_lw_set_graph(vf, p->lw_opts, NULL, "%s", rot[p->angle]) >= 0) {
+ vf_lw_set_reconfig_cb(vf, lavfi_reconfig);
return 1;
+ }
MP_FATAL(vf, "Requires libavfilter.\n");
return 1;
@@ -61,7 +81,8 @@ const vf_info_t vf_info_rotate = {
({"0", 0},
{"90", 1},
{"180", 2},
- {"270", 3})),
+ {"270", 3},
+ {"auto", 4})),
OPT_SUBSTRUCT("", lw_opts, vf_lw_conf, 0),
{0}
},
diff --git a/video/filter/vf_stereo3d.c b/video/filter/vf_stereo3d.c
index fcf583eef4..77d041af79 100644
--- a/video/filter/vf_stereo3d.c
+++ b/video/filter/vf_stereo3d.c
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdbool.h>
#include <libavutil/common.h>
@@ -64,6 +65,7 @@ typedef enum stereo_code {
ABOVE_BELOW_2_RL, //above-below with half height resolution
INTERLEAVE_ROWS_LR, //row-interleave (left eye has top row)
INTERLEAVE_ROWS_RL, //row-interleave (right eye has top row)
+ STEREO_AUTO, //use video metadata info (for input)
STEREO_CODE_COUNT //no value set - TODO: needs autodetection
} stereo_code;
@@ -132,6 +134,7 @@ static const int ana_coeff[][3][6] = {
struct vf_priv_s {
component in;
component out;
+ bool auto_in;
int ana_matrix[3][6];
unsigned int width;
unsigned int height;
@@ -142,6 +145,8 @@ struct vf_priv_s {
{ANAGLYPH_RC_DUBOIS}
};
+static bool handle_auto_in(struct vf_instance *vf);
+
//==functions==//
static inline uint8_t ana_convert(int coeff[6], uint8_t left[3], uint8_t right[3])
{
@@ -171,6 +176,9 @@ static int config(struct vf_instance *vf, int width, int height, int d_width,
vf->priv->in.row_left = 0;
vf->priv->in.row_right = 0;
+ if (vf->priv->auto_in && !handle_auto_in(vf))
+ return 0;
+
//check input format
switch (vf->priv->in.fmt) {
case SIDE_BY_SIDE_2_LR:
@@ -447,6 +455,8 @@ const struct m_opt_choice_alternatives stereo_code_names[] = {
{"interleave_rows_right_first", INTERLEAVE_ROWS_RL},
// convenience alias for MP_STEREO3D_MONO
{"mono", MONO_L},
+ // for filter auto-insertion
+ {"auto", STEREO_AUTO},
{ NULL, 0}
};
@@ -461,18 +471,87 @@ static const char *rev_map_name(int val)
return NULL;
}
+// Extremely stupid; can be dropped when the internal filter is dropped,
+// and OPT_VID_STEREO_MODE() can be used instead.
+static int opt_to_stereo3dmode(int val)
+{
+ // Find x for rev_map_name(val) == MP_STEREO3D_NAME(x)
+ const char *name = rev_map_name(val);
+ for (int n = 0; n < MP_STEREO3D_COUNT; n++) {
+ const char *o = MP_STEREO3D_NAME(val);
+ if (name && o && strcmp(o, name) == 0)
+ return n;
+ }
+ return MP_STEREO3D_INVALID;
+}
+static int stereo3dmode_to_opt(int val)
+{
+ // Find x for rev_map_name(x) == MP_STEREO3D_NAME(val)
+ const char *name = MP_STEREO3D_NAME(val);
+ for (int n = 0; stereo_code_names[n].name; n++) {
+ if (name && strcmp(stereo_code_names[n].name, name) == 0)
+ return stereo_code_names[n].value;
+ }
+ return -1;
+}
+
+static bool handle_auto_in(struct vf_instance *vf)
+{
+ if (vf->priv->auto_in) {
+ int inv = stereo3dmode_to_opt(vf->fmt_in.stereo_in);
+ if (inv < 0) {
+ MP_ERR(vf, "Unknown/unsupported 3D mode.\n");
+ return false;
+ }
+ vf->priv->in.fmt = inv;
+ vf->fmt_out.stereo_in = vf->fmt_out.stereo_out =
+ opt_to_stereo3dmode(vf->priv->out.fmt);
+ }
+ return true;
+}
+
+static int lavfi_reconfig(struct vf_instance *vf,
+ struct mp_image_params *in,
+ struct mp_image_params *out)
+{
+ struct vf_priv_s *p = vf_lw_old_priv(vf);
+ if (p->auto_in) {
+ const char *inf = MP_STEREO3D_NAME(in->stereo_in);
+ if (!inf) {
+ MP_ERR(vf, "Unknown/unsupported 3D mode.\n");
+ return -1;
+ }
+ vf_lw_update_graph(vf, "stereo3d", "%s:%s",
+ inf, rev_map_name(p->out.fmt));
+ out->stereo_in = out->stereo_out = opt_to_stereo3dmode(p->out.fmt);
+ }
+ return 0;
+}
+
static int vf_open(vf_instance_t *vf)
{
vf->config = config;
vf->filter = filter;
vf->query_format = query_format;
+ if (vf->priv->out.fmt == STEREO_AUTO) {
+ MP_FATAL(vf, "No autodetection for stereo output.\n");
+ return 0;
+ }
+ if (vf->priv->in.fmt == STEREO_AUTO)
+ vf->priv->auto_in = 1;
+
+ if (vf->priv->in.fmt == STEREO_AUTO &&
+ vf_lw_set_graph(vf, vf->priv->lw_opts, NULL, "null") >= 0)
+ {
+ vf_lw_set_reconfig_cb(vf, lavfi_reconfig);
+ return 1;
+ }
+
if (vf_lw_set_graph(vf, vf->priv->lw_opts, "stereo3d", "%s:%s",
rev_map_name(vf->priv->in.fmt),
rev_map_name(vf->priv->out.fmt)) >= 0)
- {
return 1;
- }
return 1;
}