video: auto-insert software rotation filter

If the VO can't do rotation, insert a filter to do this. Note that this
doesn't reuse the filter insertion code from command.c (used by "vf"
input command), because that would end up more complicated: we don't
even want to change the user filter option.
This commit is contained in:
wm4 2014-04-20 23:54:13 +02:00
parent f69312e329
commit ff9ac83419
1 changed files with 44 additions and 5 deletions

View File

@ -27,6 +27,8 @@
#include "common/msg.h" #include "common/msg.h"
#include "options/options.h" #include "options/options.h"
#include "options/m_config.h"
#include "options/m_option.h"
#include "common/common.h" #include "common/common.h"
#include "common/encode.h" #include "common/encode.h"
#include "options/m_property.h" #include "options/m_property.h"
@ -61,14 +63,34 @@ static void set_allowed_vo_formats(struct vf_chain *c, struct vo *vo)
} }
} }
static int try_filter(struct MPContext *mpctx, struct mp_image_params params,
char *name, char *label, char **args)
{
struct dec_video *d_video = mpctx->d_video;
struct vf_instance *vf = vf_append_filter(d_video->vfilter, name, args);
if (!vf)
return -1;
vf->label = talloc_strdup(vf, label);
if (video_reconfig_filters(d_video, &params) < 0) {
vf_remove_filter(d_video->vfilter, vf);
// restore
video_reconfig_filters(d_video, &params);
return -1;
}
return 0;
}
static void reconfig_video(struct MPContext *mpctx, static void reconfig_video(struct MPContext *mpctx,
const struct mp_image_params *params, struct mp_image_params params,
bool probe_only) bool probe_only)
{ {
struct MPOpts *opts = mpctx->opts; struct MPOpts *opts = mpctx->opts;
struct dec_video *d_video = mpctx->d_video; struct dec_video *d_video = mpctx->d_video;
d_video->decoder_output = *params; d_video->decoder_output = params;
set_allowed_vo_formats(d_video->vfilter, mpctx->video_out); set_allowed_vo_formats(d_video->vfilter, mpctx->video_out);
@ -76,7 +98,7 @@ static void reconfig_video(struct MPContext *mpctx,
// have any fine grained locking, this is just as good. // have any fine grained locking, this is just as good.
mp_notify(mpctx, MPV_EVENT_VIDEO_RECONFIG, NULL); mp_notify(mpctx, MPV_EVENT_VIDEO_RECONFIG, NULL);
if (video_reconfig_filters(d_video, params) < 0) { if (video_reconfig_filters(d_video, &params) < 0) {
// Most video filters don't work with hardware decoding, so this // Most video filters don't work with hardware decoding, so this
// might be the reason filter reconfig failed. // might be the reason filter reconfig failed.
if (!probe_only && if (!probe_only &&
@ -89,6 +111,23 @@ static void reconfig_video(struct MPContext *mpctx,
return; return;
} }
if (d_video->vfilter->initialized < 1)
return;
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};
if (try_filter(mpctx, params, "rotate", "autorotate", args) >= 0) {
params.rotate = 0;
} else {
MP_ERR(mpctx, "Can't insert rotation filter.\n");
}
}
}
if (d_video->vfilter->initialized < 1) if (d_video->vfilter->initialized < 1)
return; return;
@ -147,7 +186,7 @@ int reinit_video_filters(struct MPContext *mpctx)
recreate_video_filters(mpctx); recreate_video_filters(mpctx);
if (need_reconfig) if (need_reconfig)
reconfig_video(mpctx, &d_video->decoder_output, true); reconfig_video(mpctx, d_video->decoder_output, true);
if (!d_video->vfilter) if (!d_video->vfilter)
return 0; return 0;
@ -315,7 +354,7 @@ static void filter_video(struct MPContext *mpctx, struct mp_image *frame,
return; return;
} }
reconfig_video(mpctx, &params, false); reconfig_video(mpctx, params, false);
if (d_video->vfilter->initialized > 0) if (d_video->vfilter->initialized > 0)
init_filter_params(mpctx); init_filter_params(mpctx);
} }