diff options
-rw-r--r-- | DOCS/man/en/input.rst | 31 | ||||
-rw-r--r-- | core/command.c | 40 | ||||
-rw-r--r-- | core/input/input.c | 2 | ||||
-rw-r--r-- | core/input/input.h | 3 | ||||
-rw-r--r-- | core/mp_core.h | 1 | ||||
-rw-r--r-- | core/mplayer.c | 46 | ||||
-rw-r--r-- | video/decode/dec_video.c | 1 |
7 files changed, 112 insertions, 12 deletions
diff --git a/DOCS/man/en/input.rst b/DOCS/man/en/input.rst index bd62e65cd6..4acba49169 100644 --- a/DOCS/man/en/input.rst +++ b/DOCS/man/en/input.rst @@ -236,6 +236,37 @@ af_clr Remove all audio filters. (Conversion filters will be re-added automatically if needed.) +vf set|add|toggle|del "filter1=params,filter2,..." + Change video filter chain. + + The first argument decides what happens: + + set + Overwrite the previous filter chain with the new one. + + add + Append the new filter chain to the previous one. + + toggle + Check if the given filter (with the exact parameters) is already + in the video chain. If yes, remove the filter. If no, add the filter. + (If several filters are passed to the command, this is done for + each filter.) + + del + Remove the given filters from the video chain. Unlike in the other + cases, the second parameter is a comma separated list of filter names + or integer indexes. ``0`` would denote the first filter. Negative + indexes start from the last filter, and ``-1`` denotes the last + filter. + + *EXAMPLE for input.conf*: + + - ``a vf set flip`` turn video upside-down on the ``a`` key + - ``b vf set ""`` remove all video filters on ``b`` + - ``c vf toggle lavfi=gradfun`` toggle debanding on ``c`` + + Undocumented commands: tv_start_scan, tv_step_channel, tv_step_norm, tv_step_chanlist, tv_set_channel, tv_last_channel, tv_set_freq, tv_step_freq, tv_set_norm, dvb_set_channel, radio_step_channel, radio_set_channel, diff --git a/core/command.c b/core/command.c index ebc8d93485..9e16804e8a 100644 --- a/core/command.c +++ b/core/command.c @@ -1775,6 +1775,42 @@ static void show_playlist_on_osd(MPContext *mpctx) talloc_free(res); } +static void change_video_filters(MPContext *mpctx, const char *cmd, + const char *arg) +{ + struct MPOpts *opts = &mpctx->opts; + struct m_config *conf = mpctx->mconfig; + struct m_obj_settings *old_vf_settings = NULL; + bool success = false; + bool need_refresh = false; + double refresh_pts = mpctx->last_vo_pts; + + // The option parser is used to modify the filter list itself. + char optname[20]; + snprintf(optname, sizeof(optname), "vf-%s", cmd); + const struct m_option *type = m_config_get_option(conf, bstr0(optname)); + + // Backup old settings, in case it fails + m_option_copy(type, &old_vf_settings, &opts->vf_settings); + + if (m_config_set_option0(conf, optname, arg) >= 0) { + need_refresh = true; + success = reinit_video_filters(mpctx) >= 0; + } + + if (!success) { + m_option_copy(type, &opts->vf_settings, &old_vf_settings); + if (need_refresh) + reinit_video_filters(mpctx); + } + m_option_free(type, &old_vf_settings); + + // Try to refresh the video by doing a precise seek to the currently + // displayed frame. + if (need_refresh && opts->pause) + queue_seek(mpctx, MPSEEK_ABSOLUTE, refresh_pts, 1); +} + void run_command(MPContext *mpctx, mp_cmd_t *cmd) { struct MPOpts *opts = &mpctx->opts; @@ -2289,6 +2325,7 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) af_uninit(mpctx->mixer.afilter); af_init(mpctx->mixer.afilter); } + /* fallthrough */ case MP_CMD_AF_ADD: case MP_CMD_AF_DEL: { if (!sh_audio) @@ -2331,6 +2368,9 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) af_reinit(sh_audio->afilter); } break; + case MP_CMD_VF: + change_video_filters(mpctx, cmd->args[0].v.s, cmd->args[1].v.s); + break; case MP_CMD_SHOW_CHAPTERS: show_chapters_on_osd(mpctx); break; diff --git a/core/input/input.c b/core/input/input.c index 7ba6b64cdc..116e963b93 100644 --- a/core/input/input.c +++ b/core/input/input.c @@ -198,6 +198,8 @@ static const mp_cmd_t mp_cmds[] = { { MP_CMD_AF_CLR, "af_clr", }, { MP_CMD_AF_CMDLINE, "af_cmdline", { ARG_STRING, ARG_STRING } }, + { MP_CMD_VF, "vf", { ARG_STRING, ARG_STRING } }, + { MP_CMD_SHOW_CHAPTERS, "show_chapters", }, { MP_CMD_SHOW_TRACKS, "show_tracks", }, { MP_CMD_SHOW_PLAYLIST, "show_playlist", }, diff --git a/core/input/input.h b/core/input/input.h index 367abedfca..12823dd004 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -78,6 +78,9 @@ enum mp_command_type { MP_CMD_AF_CLR, MP_CMD_AF_CMDLINE, + /// Video filter commands + MP_CMD_VF, + MP_CMD_SHOW_CHAPTERS, MP_CMD_SHOW_TRACKS, MP_CMD_SHOW_PLAYLIST, diff --git a/core/mp_core.h b/core/mp_core.h index 941396c48a..ce576273b4 100644 --- a/core/mp_core.h +++ b/core/mp_core.h @@ -298,6 +298,7 @@ double playing_audio_pts(struct MPContext *mpctx); struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename, float fps, int noerr); int reinit_video_chain(struct MPContext *mpctx); +int reinit_video_filters(struct MPContext *mpctx); void pause_player(struct MPContext *mpctx); void unpause_player(struct MPContext *mpctx); void add_step_frame(struct MPContext *mpctx, int dir); diff --git a/core/mplayer.c b/core/mplayer.c index ac597beac1..a0b18cab62 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -2466,6 +2466,39 @@ static void update_fps(struct MPContext *mpctx) #endif } +static void recreate_video_filters(struct MPContext *mpctx) +{ + struct MPOpts *opts = &mpctx->opts; + struct sh_video *sh_video = mpctx->sh_video; + assert(sh_video); + + vf_uninit_filter_chain(sh_video->vfilter); + + char *vf_arg[] = { + "_oldargs_", (char *)mpctx->video_out, NULL + }; + sh_video->vfilter = vf_open_filter(opts, NULL, "vo", vf_arg); + + sh_video->vfilter = append_filters(sh_video->vfilter, opts->vf_settings); + + struct vf_instance *vf = sh_video->vfilter; + mpctx->osd->render_subs_in_filter + = vf->control(vf, VFCTRL_INIT_OSD, NULL) == VO_TRUE; +} + +int reinit_video_filters(struct MPContext *mpctx) +{ + struct sh_video *sh_video = mpctx->sh_video; + + if (!sh_video) + return -2; + + recreate_video_filters(mpctx); + video_reinit_vo(sh_video); + + return sh_video->vf_initialized > 0 ? 0 : -1; +} + int reinit_video_chain(struct MPContext *mpctx) { struct MPOpts *opts = &mpctx->opts; @@ -2518,18 +2551,7 @@ int reinit_video_chain(struct MPContext *mpctx) STREAM_CTRL_GET_ASPECT_RATIO, &ar) != STREAM_UNSUPPORTED) mpctx->sh_video->stream_aspect = ar; - { - char *vf_arg[] = { - "_oldargs_", (char *)mpctx->video_out, NULL - }; - sh_video->vfilter = vf_open_filter(opts, NULL, "vo", vf_arg); - } - - sh_video->vfilter = append_filters(sh_video->vfilter, opts->vf_settings); - - struct vf_instance *vf = sh_video->vfilter; - mpctx->osd->render_subs_in_filter - = vf->control(vf, VFCTRL_INIT_OSD, NULL) == VO_TRUE; + recreate_video_filters(mpctx); init_best_video_codec(sh_video, opts->video_decoders); diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c index 1dd83db8bd..5e55e78220 100644 --- a/video/decode/dec_video.c +++ b/video/decode/dec_video.c @@ -184,6 +184,7 @@ void uninit_video(sh_video_t *sh_video) mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Uninit video.\n"); sh_video->vd_driver->uninit(sh_video); vf_uninit_filter_chain(sh_video->vfilter); + sh_video->vfilter = NULL; talloc_free(sh_video->gsh->decoder_desc); sh_video->gsh->decoder_desc = NULL; sh_video->initialized = 0; |