core: add --deinterlace option, restore it with resume functionality

The --deinterlace option does on playback start what the "deinterlace"
property normally does at runtime. You could do this before by using the
--vf option or by messing with the vo_vdpau default options, but this
new option is supposed to be a "foolproof" way.

The main motivation for adding this is so that the deinterlace property
can be restored when using the video resume functionality
(quit_watch_later command).

Implementation-wise, this is a bit messy. The video chain is rebuilt in
mpcodecs_reconfig_vo(), where we don't have access to MPContext, so the
usual mechanism for enabling deinterlacing can't be used. Further,
mpcodecs_reconfig_vo() is called by the video decoder, which doesn't
have access to MPContext either. Moving this call to mplayer.c isn't
currently possible either (see below). So we just do this before frames
are filtered, which potentially means setting the deinterlacing every
frame. Fortunately, setting deinterlacing is stable and idempotent, so
this is hopefully not a problem. We also add a counter that is
incremented on each reconfig to reduce the amount of additional work per
frame to nearly zero.

The reason we can't move mpcodecs_reconfig_vo() to mplayer.c is because
of hardware decoding: we need to check whether the video chain works
before we decide that we can use hardware decoding. Changing it so that
this can be decided in advance without building a filter chain sounds
like a good idea and should be done, but we aren't there yet.
This commit is contained in:
wm4 2013-09-13 18:06:08 +02:00
parent ddd3ade023
commit 6cec60a454
9 changed files with 61 additions and 4 deletions

View File

@ -432,7 +432,7 @@ Name W Comment
``audio`` x alias for ``aid``
``balance`` x audio channel balance
``fullscreen`` x see ``--fullscreen``
``deinterlace`` x deinterlacing, if available (bool)
``deinterlace`` x similar to ``--deinterlace``
``colormatrix`` x see ``--colormatrix``
``colormatrix-input-range`` x see ``--colormatrix-input-range``
``colormatrix-output-range`` x see ``--colormatrix-output-range``

View File

@ -569,6 +569,21 @@
Audio delay in seconds (positive or negative float value). Negative values
delay the audio, and positive values delay the video.
``--deinterlace=<yes|no|auto>``
Enable or disable interlacing (default: auto, which usually means no).
Interlaced video shows ugly comb-like artifacts, which are visible on
fast movement. Enabling this typically inserts the yadif video filter in
order to deinterlace the video, or lets the video output apply deinterlacing
if supported.
This behaves exactly like the ``deinterlace`` input property (usually
mapped to ``Shift+D``).
``auto`` is a technicality. Strictly speaking, the default for this option
is deinterlacing disabled, but the ``auto`` case is needed if ``yadif`` was
added to the filter chain manually with ``--vf``. Then the core shouldn't
disable deinterlacing just because the ``--deinterlace`` was not set.
``--demuxer=<[+]name>``
Force demuxer type. Use a '+' before the name to force it; this will skip
some checks. Give the demuxer name as printed by ``--demuxer=help``.

View File

@ -131,6 +131,7 @@ typedef struct sh_video {
struct vf_instance *vfilter; // video filter chain
const struct vd_functions *vd_driver;
int vf_initialized; // -1 failed, 0 not done, 1 done
long vf_reconfig_count; // incremented each mpcodecs_reconfig_vo() call
struct mp_image_params *vf_input; // video filter input params
struct mp_hwdec_info *hwdec_info; // video output hwdec handles
// win32-compatible codec parameters:

View File

@ -1155,10 +1155,13 @@ static void set_deinterlacing(struct MPContext *mpctx, bool enable)
if (!enable)
change_video_filters(mpctx, "del", VF_DEINTERLACE);
} else {
int arg = enable;
if (vf->control(vf, VFCTRL_SET_DEINTERLACE, &arg) != CONTROL_OK)
change_video_filters(mpctx, "add", VF_DEINTERLACE);
if ((get_deinterlacing(mpctx) > 0) != enable) {
int arg = enable;
if (vf->control(vf, VFCTRL_SET_DEINTERLACE, &arg) != CONTROL_OK)
change_video_filters(mpctx, "add", VF_DEINTERLACE);
}
}
mpctx->opts->deinterlace = get_deinterlacing(mpctx) > 0;
}
static int mp_property_deinterlace(m_option_t *prop, int action,

View File

@ -229,6 +229,8 @@ typedef struct MPContext {
double last_vo_pts;
// Video PTS, or audio PTS if video has ended.
double playback_pts;
// Used to determine whether the video filter chain was rebuilt.
long last_vf_reconfig_count;
// History of video frames timestamps that were queued in the VO
// This includes even skipped frames during hr-seek

View File

@ -840,6 +840,7 @@ static const char *backup_properties[] = {
"contrast",
"saturation",
"hue",
"deinterlace",
"panscan",
"aid",
"vid",
@ -2438,6 +2439,7 @@ int reinit_video_chain(struct MPContext *mpctx)
sh_video->last_pts = MP_NOPTS_VALUE;
sh_video->num_buffered_pts = 0;
sh_video->next_frame_time = 0;
mpctx->last_vf_reconfig_count = 0;
mpctx->restart_playback = true;
mpctx->sync_audio_to_video = !sh_video->gsh->attached_picture;
mpctx->delay = 0;
@ -2524,10 +2526,35 @@ static bool load_next_vo_frame(struct MPContext *mpctx, bool eof)
return false;
}
static void init_filter_params(struct MPContext *mpctx)
{
struct MPOpts *opts = mpctx->opts;
struct sh_video *sh_video = mpctx->sh_video;
// Note that the video decoder already initializes the filter chain. This
// might recreate the chain a second time, which is not very elegant, but
// allows us to test whether enabling deinterlacing works with the current
// video format and other filters.
if (sh_video->vf_initialized != 1)
return;
if (sh_video->vf_reconfig_count <= mpctx->last_vf_reconfig_count) {
if (opts->deinterlace >= 0) {
mp_property_do("deinterlace", M_PROPERTY_SET, &opts->deinterlace,
mpctx);
}
}
// Setting filter params has to be "stable" (no change if params already
// set) - checking the reconfig count is just an optimization.
mpctx->last_vf_reconfig_count = sh_video->vf_reconfig_count;
}
static void filter_video(struct MPContext *mpctx, struct mp_image *frame)
{
struct sh_video *sh_video = mpctx->sh_video;
init_filter_params(mpctx);
frame->pts = sh_video->pts;
mp_image_set_params(frame, sh_video->vf_input);
vf_filter_frame(sh_video->vfilter, frame);

View File

@ -461,6 +461,11 @@ const m_option_t mp_opts[] = {
OPT_SETTINGSLIST("af*", af_settings, 0, &af_obj_list),
OPT_SETTINGSLIST("vf*", vf_settings, 0, &vf_obj_list),
OPT_CHOICE("deinterlace", deinterlace, M_OPT_OPTIONAL_PARAM,
({"auto", -1},
{"no", 0},
{"yes", 1}, {"", 1})),
OPT_STRING("ad", audio_decoders, 0),
OPT_STRING("vd", video_decoders, 0),
@ -745,6 +750,7 @@ const struct MPOpts mp_default_opts = {
.audio_driver_list = NULL,
.audio_decoders = "-spdif:*", // never select spdif by default
.video_decoders = NULL,
.deinterlace = -1,
.fixed_vo = 1,
.softvol = SOFTVOL_AUTO,
.softvol_max = 200,

View File

@ -169,6 +169,7 @@ typedef struct MPOpts {
double playback_speed;
struct m_obj_settings *vf_settings;
struct m_obj_settings *af_settings;
int deinterlace;
float movie_aspect;
int flip;
int field_dominance;

View File

@ -56,6 +56,8 @@ int mpcodecs_reconfig_vo(sh_video_t *sh, const struct mp_image_params *params)
int vocfg_flags = 0;
struct mp_image_params p = *params;
sh->vf_reconfig_count++;
if (!p.w || !p.h) {
// ideally, this should be dead code
mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Unknown size, using container size.\n");