summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
Diffstat (limited to 'player')
-rw-r--r--player/command.c49
-rw-r--r--player/core.h16
-rw-r--r--player/sub.c4
-rw-r--r--player/video.c145
4 files changed, 119 insertions, 95 deletions
diff --git a/player/command.c b/player/command.c
index f2f73059ef..941dd34ec5 100644
--- a/player/command.c
+++ b/player/command.c
@@ -1234,9 +1234,9 @@ static int mp_property_filter_metadata(void *ctx, struct m_property *prop,
struct mp_tags metadata = {0};
int res = CONTROL_UNKNOWN;
if (strcmp(type, "vf") == 0) {
- if (!(mpctx->d_video && mpctx->d_video->vfilter))
+ if (!mpctx->vo_chain)
return M_PROPERTY_UNAVAILABLE;
- struct vf_chain *vf = mpctx->d_video->vfilter;
+ struct vf_chain *vf = mpctx->vo_chain->vf;
res = vf_control_by_label(vf, VFCTRL_GET_METADATA, &metadata, key);
} else if (strcmp(type, "af") == 0) {
if (!(mpctx->d_audio && mpctx->d_audio->afilter))
@@ -2181,10 +2181,10 @@ static bool probe_deint_filter(struct MPContext *mpctx, const char *filt)
static bool check_output_format(struct MPContext *mpctx, int imgfmt)
{
- struct dec_video *vd = mpctx->d_video;
- if (!vd)
+ struct vo_chain *vo_c = mpctx->vo_chain;
+ if (!vo_c)
return false;
- return vd->vfilter->allowed_output_formats[imgfmt - IMGFMT_START];
+ return vo_c->vf->allowed_output_formats[imgfmt - IMGFMT_START];
}
static int probe_deint_filters(struct MPContext *mpctx)
@@ -2214,13 +2214,13 @@ static int probe_deint_filters(struct MPContext *mpctx)
static int get_deinterlacing(struct MPContext *mpctx)
{
- struct dec_video *vd = mpctx->d_video;
+ struct vo_chain *vo_c = mpctx->vo_chain;
int enabled = 0;
- if (video_vf_vo_control(vd, VFCTRL_GET_DEINTERLACE, &enabled) != CONTROL_OK)
+ if (video_vf_vo_control(vo_c, VFCTRL_GET_DEINTERLACE, &enabled) != CONTROL_OK)
enabled = -1;
if (enabled < 0) {
// vf_lavfi doesn't support VFCTRL_GET_DEINTERLACE
- if (vf_find_by_label(vd->vfilter, VF_DEINTERLACE_LABEL))
+ if (vf_find_by_label(vo_c->vf, VF_DEINTERLACE_LABEL))
enabled = 1;
}
return enabled;
@@ -2233,14 +2233,14 @@ void remove_deint_filter(struct MPContext *mpctx)
void set_deinterlacing(struct MPContext *mpctx, bool enable)
{
- struct dec_video *vd = mpctx->d_video;
- if (vf_find_by_label(vd->vfilter, VF_DEINTERLACE_LABEL)) {
+ struct vo_chain *vo_c = mpctx->vo_chain;
+ if (vf_find_by_label(vo_c->vf, VF_DEINTERLACE_LABEL)) {
if (!enable)
remove_deint_filter(mpctx);
} else {
if ((get_deinterlacing(mpctx) > 0) != enable) {
int arg = enable;
- if (video_vf_vo_control(vd, VFCTRL_SET_DEINTERLACE, &arg) != CONTROL_OK)
+ if (video_vf_vo_control(vo_c, VFCTRL_SET_DEINTERLACE, &arg) != CONTROL_OK)
probe_deint_filters(mpctx);
}
}
@@ -2251,7 +2251,7 @@ static int mp_property_deinterlace(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
- if (!mpctx->d_video || !mpctx->d_video->vfilter)
+ if (!mpctx->vo_chain)
return mp_property_generic_option(mpctx, prop, action, arg);
switch (action) {
case M_PROPERTY_GET:
@@ -2403,17 +2403,17 @@ static int mp_property_video_color(void *ctx, struct m_property *prop,
{
const char *name = prop->priv ? prop->priv : prop->name;
MPContext *mpctx = ctx;
- if (!mpctx->d_video)
+ if (!mpctx->vo_chain)
return M_PROPERTY_UNAVAILABLE;
switch (action) {
case M_PROPERTY_SET: {
- if (video_set_colors(mpctx->d_video, name, *(int *) arg) <= 0)
+ if (video_set_colors(mpctx->vo_chain, name, *(int *) arg) <= 0)
return M_PROPERTY_UNAVAILABLE;
break;
}
case M_PROPERTY_GET:
- if (video_get_colors(mpctx->d_video, name, (int *)arg) <= 0)
+ if (video_get_colors(mpctx->vo_chain, name, (int *)arg) <= 0)
return M_PROPERTY_UNAVAILABLE;
// Write new value to option variable
mp_property_generic_option(mpctx, prop, M_PROPERTY_SET, arg);
@@ -2491,11 +2491,10 @@ static int property_imgparams(struct mp_image_params p, int action, void *arg)
static struct mp_image_params get_video_out_params(struct MPContext *mpctx)
{
- if (!mpctx->d_video || !mpctx->d_video->vfilter ||
- mpctx->d_video->vfilter->initialized < 1)
+ if (!mpctx->vo_chain || mpctx->vo_chain->vf->initialized < 1)
return (struct mp_image_params){0};
- return mpctx->d_video->vfilter->output_params;
+ return mpctx->vo_chain->vf->output_params;
}
static int mp_property_vo_imgparams(void *ctx, struct m_property *prop,
@@ -2508,12 +2507,12 @@ static int mp_property_vd_imgparams(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
- struct dec_video *vd = mpctx->d_video;
- if (!vd)
+ struct vo_chain *vo_c = mpctx->vo_chain;
+ if (!vo_c && !mpctx->d_video)
return M_PROPERTY_UNAVAILABLE;
- struct mp_codec_params *c = vd->header->codec;
- if (vd->vfilter->input_params.imgfmt) {
- return property_imgparams(vd->vfilter->input_params, action, arg);
+ struct mp_codec_params *c = mpctx->d_video->header->codec;
+ if (vo_c->vf->input_params.imgfmt) {
+ return property_imgparams(vo_c->vf->input_params, action, arg);
} else if (c->disp_w && c->disp_h) {
// Simplistic fallback for stupid scripts querying "width"/"height"
// before the first frame is decoded.
@@ -2776,10 +2775,10 @@ static int mp_property_aspect(void *ctx, struct m_property *prop,
}
case M_PROPERTY_GET: {
float aspect = mpctx->opts->movie_aspect;
- if (mpctx->d_video && aspect <= 0) {
+ if (mpctx->d_video && mpctx->vo_chain && aspect <= 0) {
struct dec_video *d_video = mpctx->d_video;
struct mp_codec_params *c = d_video->header->codec;
- struct mp_image_params *params = &d_video->vfilter->input_params;
+ struct mp_image_params *params = &mpctx->vo_chain->vf->input_params;
if (params && params->p_w > 0 && params->p_h > 0) {
int d_w, d_h;
mp_image_params_get_dsize(params, &d_w, &d_h);
diff --git a/player/core.h b/player/core.h
index fe7f380b2e..6057725983 100644
--- a/player/core.h
+++ b/player/core.h
@@ -148,6 +148,14 @@ struct track {
bool preloaded;
};
+// Summarizes video filtering and output.
+struct vo_chain {
+ struct mp_log *log;
+
+ struct vf_chain *vf;
+ struct vo *vo;
+};
+
/* Note that playback can be paused, stopped, etc. at any time. While paused,
* playback restart is still active, because you want seeking to work even
* if paused.
@@ -258,6 +266,8 @@ typedef struct MPContext {
struct mp_audio *ao_decoder_fmt; // for weak gapless audio check
struct mp_audio_buffer *ao_buffer; // queued audio; passed to ao_play() later
+ struct vo_chain *vo_chain;
+
struct vo *video_out;
// next_frame[0] is the next frame, next_frame[1] the one after that.
// The +1 is for adding 1 additional frame in backstep mode.
@@ -511,9 +521,9 @@ void update_osd_msg(struct MPContext *mpctx);
bool update_subtitles(struct MPContext *mpctx, double video_pts);
// video.c
-int video_get_colors(struct dec_video *d_video, const char *item, int *value);
-int video_set_colors(struct dec_video *d_video, const char *item, int value);
-int video_vf_vo_control(struct dec_video *d_video, int vf_cmd, void *data);
+int video_get_colors(struct vo_chain *vo_c, const char *item, int *value);
+int video_set_colors(struct vo_chain *vo_c, const char *item, int value);
+int video_vf_vo_control(struct vo_chain *vo_c, int vf_cmd, void *data);
void reset_video_state(struct MPContext *mpctx);
int reinit_video_chain(struct MPContext *mpctx);
int reinit_video_filters(struct MPContext *mpctx);
diff --git a/player/sub.c b/player/sub.c
index c20df53c60..0633ebaea1 100644
--- a/player/sub.c
+++ b/player/sub.c
@@ -77,8 +77,8 @@ static bool update_subtitle(struct MPContext *mpctx, double video_pts, int order
if (!track || !dec_sub || video_pts == MP_NOPTS_VALUE)
return true;
- if (mpctx->d_video) {
- struct mp_image_params params = mpctx->d_video->vfilter->input_params;
+ if (mpctx->vo_chain) {
+ struct mp_image_params params = mpctx->vo_chain->vf->input_params;
if (params.imgfmt)
sub_control(dec_sub, SD_CTRL_SET_VIDEO_PARAMS, &params);
}
diff --git a/player/video.c b/player/video.c
index afd0a2aa7a..043132a690 100644
--- a/player/video.c
+++ b/player/video.c
@@ -68,97 +68,91 @@ static const char av_desync_help_text[] =
static bool decode_coverart(struct dec_video *d_video);
-int video_set_colors(struct dec_video *d_video, const char *item, int value)
+int video_set_colors(struct vo_chain *vo_c, const char *item, int value)
{
vf_equalizer_t data;
data.item = item;
data.value = value;
- MP_VERBOSE(d_video, "set video colors %s=%d \n", item, value);
- if (d_video->vfilter) {
- int ret = video_vf_vo_control(d_video, VFCTRL_SET_EQUALIZER, &data);
- if (ret == CONTROL_TRUE)
- return 1;
- }
- MP_VERBOSE(d_video, "Video attribute '%s' is not supported by selected vo.\n",
+ MP_VERBOSE(vo_c, "set video colors %s=%d \n", item, value);
+ if (video_vf_vo_control(vo_c, VFCTRL_SET_EQUALIZER, &data) == CONTROL_TRUE)
+ return 1;
+ MP_VERBOSE(vo_c, "Video attribute '%s' is not supported by selected vo.\n",
item);
return 0;
}
-int video_get_colors(struct dec_video *d_video, const char *item, int *value)
+int video_get_colors(struct vo_chain *vo_c, const char *item, int *value)
{
vf_equalizer_t data;
data.item = item;
- MP_VERBOSE(d_video, "get video colors %s \n", item);
- if (d_video->vfilter) {
- int ret = video_vf_vo_control(d_video, VFCTRL_GET_EQUALIZER, &data);
- if (ret == CONTROL_TRUE) {
- *value = data.value;
- return 1;
- }
+ MP_VERBOSE(vo_c, "get video colors %s \n", item);
+ if (video_vf_vo_control(vo_c, VFCTRL_GET_EQUALIZER, &data) == CONTROL_TRUE) {
+ *value = data.value;
+ return 1;
}
return 0;
}
// Send a VCTRL, or if it doesn't work, translate it to a VOCTRL and try the VO.
-int video_vf_vo_control(struct dec_video *d_video, int vf_cmd, void *data)
+int video_vf_vo_control(struct vo_chain *vo_c, int vf_cmd, void *data)
{
- if (d_video->vfilter && d_video->vfilter->initialized > 0) {
- int r = vf_control_any(d_video->vfilter, vf_cmd, data);
+ if (vo_c->vf->initialized > 0) {
+ int r = vf_control_any(vo_c->vf, vf_cmd, data);
if (r != CONTROL_UNKNOWN)
return r;
}
switch (vf_cmd) {
case VFCTRL_GET_DEINTERLACE:
- return vo_control(d_video->vo, VOCTRL_GET_DEINTERLACE, data) == VO_TRUE;
+ return vo_control(vo_c->vo, VOCTRL_GET_DEINTERLACE, data) == VO_TRUE;
case VFCTRL_SET_DEINTERLACE:
- return vo_control(d_video->vo, VOCTRL_SET_DEINTERLACE, data) == VO_TRUE;
+ return vo_control(vo_c->vo, VOCTRL_SET_DEINTERLACE, data) == VO_TRUE;
case VFCTRL_SET_EQUALIZER: {
vf_equalizer_t *eq = data;
- if (!d_video->vo->config_ok)
+ if (!vo_c->vo->config_ok)
return CONTROL_FALSE; // vo not configured?
struct voctrl_set_equalizer_args param = {
eq->item, eq->value
};
- return vo_control(d_video->vo, VOCTRL_SET_EQUALIZER, &param) == VO_TRUE;
+ return vo_control(vo_c->vo, VOCTRL_SET_EQUALIZER, &param) == VO_TRUE;
}
case VFCTRL_GET_EQUALIZER: {
vf_equalizer_t *eq = data;
- if (!d_video->vo->config_ok)
+ if (!vo_c->vo->config_ok)
return CONTROL_FALSE; // vo not configured?
struct voctrl_get_equalizer_args param = {
eq->item, &eq->value
};
- return vo_control(d_video->vo, VOCTRL_GET_EQUALIZER, &param) == VO_TRUE;
+ return vo_control(vo_c->vo, VOCTRL_GET_EQUALIZER, &param) == VO_TRUE;
}
}
return CONTROL_UNKNOWN;
}
-static void set_allowed_vo_formats(struct vf_chain *c, struct vo *vo)
+static void set_allowed_vo_formats(struct vo_chain *vo_c)
{
- vo_query_formats(vo, c->allowed_output_formats);
+ vo_query_formats(vo_c->vo, vo_c->vf->allowed_output_formats);
}
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 vo_chain *vo_c = mpctx->vo_chain;
- struct vf_instance *vf = vf_append_filter(d_video->vfilter, name, args);
+ struct vf_instance *vf = vf_append_filter(vo_c->vf, name, args);
if (!vf)
return -1;
vf->label = talloc_strdup(vf, label);
- if (vf_reconfig(d_video->vfilter, &params) < 0) {
- vf_remove_filter(d_video->vfilter, vf);
+ if (vf_reconfig(vo_c->vf, &params) < 0) {
+ vf_remove_filter(vo_c->vf, vf);
// restore
- vf_reconfig(d_video->vfilter, &params);
+ vf_reconfig(vo_c->vf, &params);
return -1;
}
return 0;
@@ -171,14 +165,15 @@ static void filter_reconfig(struct MPContext *mpctx,
bool probe_only)
{
struct dec_video *d_video = mpctx->d_video;
+ struct vo_chain *vo_c = mpctx->vo_chain;
struct mp_image_params params = d_video->decoder_output;
mp_notify(mpctx, MPV_EVENT_VIDEO_RECONFIG, NULL);
- set_allowed_vo_formats(d_video->vfilter, mpctx->video_out);
+ set_allowed_vo_formats(vo_c);
- if (vf_reconfig(d_video->vfilter, &params) < 0) {
+ if (vf_reconfig(vo_c->vf, &params) < 0) {
// Most video filters don't work with hardware decoding, so this
// might be the reason why filter reconfig failed.
if (!probe_only &&
@@ -186,7 +181,7 @@ static void filter_reconfig(struct MPContext *mpctx,
{
// Fallback active; decoder will return software format next
// time. Don't abort video decoding.
- d_video->vfilter->initialized = 0;
+ vo_c->vf->initialized = 0;
mp_image_unrefp(&d_video->waiting_decoded_mpi);
d_video->decoder_output = (struct mp_image_params){0};
MP_VERBOSE(mpctx, "hwdec falback due to filters.\n");
@@ -196,7 +191,7 @@ static void filter_reconfig(struct MPContext *mpctx,
return;
}
- if (d_video->vfilter->initialized < 1)
+ if (vo_c->vf->initialized < 1)
return;
if (params.rotate && (params.rotate % 90 == 0)) {
@@ -227,48 +222,56 @@ static void recreate_video_filters(struct MPContext *mpctx)
{
struct MPOpts *opts = mpctx->opts;
struct dec_video *d_video = mpctx->d_video;
- assert(d_video);
+ struct vo_chain *vo_c = mpctx->vo_chain;
+ assert(d_video && vo_c);
- vf_destroy(d_video->vfilter);
- d_video->vfilter = vf_new(mpctx->global);
- d_video->vfilter->hwdec = d_video->hwdec_info;
- d_video->vfilter->wakeup_callback = wakeup_playloop;
- d_video->vfilter->wakeup_callback_ctx = mpctx;
- d_video->vfilter->container_fps = d_video->fps;
- vo_control(mpctx->video_out, VOCTRL_GET_DISPLAY_FPS,
- &d_video->vfilter->display_fps);
+ vf_destroy(vo_c->vf);
+ vo_c->vf = vf_new(mpctx->global);
+ vo_c->vf->hwdec = d_video->hwdec_info;
+ vo_c->vf->wakeup_callback = wakeup_playloop;
+ vo_c->vf->wakeup_callback_ctx = mpctx;
+ vo_c->vf->container_fps = d_video->fps;
+ vo_control(vo_c->vo, VOCTRL_GET_DISPLAY_FPS, &vo_c->vf->display_fps);
- vf_append_filter_list(d_video->vfilter, opts->vf_settings);
+ vf_append_filter_list(vo_c->vf, opts->vf_settings);
// for vf_sub
osd_set_render_subs_in_filter(mpctx->osd,
- vf_control_any(d_video->vfilter, VFCTRL_INIT_OSD, mpctx->osd) > 0);
+ vf_control_any(vo_c->vf, VFCTRL_INIT_OSD, mpctx->osd) > 0);
- set_allowed_vo_formats(d_video->vfilter, mpctx->video_out);
+ set_allowed_vo_formats(vo_c);
}
int reinit_video_filters(struct MPContext *mpctx)
{
struct dec_video *d_video = mpctx->d_video;
+ struct vo_chain *vo_c = mpctx->vo_chain;
if (!d_video)
return 0;
- bool need_reconfig = d_video->vfilter->initialized != 0;
+ bool need_reconfig = vo_c->vf->initialized != 0;
recreate_video_filters(mpctx);
if (need_reconfig)
filter_reconfig(mpctx, true);
- return d_video->vfilter->initialized;
+ return vo_c->vf->initialized;
+}
+
+static void vo_chain_reset_state(struct vo_chain *vo_c)
+{
+ if (vo_c->vf->initialized == 1)
+ vf_seek_reset(vo_c->vf);
+ vo_seek_reset(vo_c->vo);
}
void reset_video_state(struct MPContext *mpctx)
{
if (mpctx->d_video)
video_reset_decoding(mpctx->d_video);
- if (mpctx->video_out)
- vo_seek_reset(mpctx->video_out);
+ if (mpctx->vo_chain)
+ vo_chain_reset_state(mpctx->vo_chain);
for (int n = 0; n < mpctx->num_next_frames; n++)
mp_image_unrefp(&mpctx->next_frames[n]);
@@ -302,10 +305,19 @@ void uninit_video_out(struct MPContext *mpctx)
mpctx->video_out = NULL;
}
+static void vo_chain_uninit(struct vo_chain *vo_c)
+{
+ if (vo_c)
+ vf_destroy(vo_c->vf);
+ talloc_free(vo_c);
+}
+
void uninit_video_chain(struct MPContext *mpctx)
{
if (mpctx->d_video) {
reset_video_state(mpctx);
+ vo_chain_uninit(mpctx->vo_chain);
+ mpctx->vo_chain = NULL;
video_uninit(mpctx->d_video);
mpctx->d_video = NULL;
mpctx->video_status = STATUS_EOF;
@@ -320,6 +332,7 @@ int reinit_video_chain(struct MPContext *mpctx)
{
struct MPOpts *opts = mpctx->opts;
assert(!mpctx->d_video);
+ assert(!mpctx->vo_chain);
struct track *track = mpctx->current_track[0][STREAM_VIDEO];
struct sh_stream *sh = track ? track->stream : NULL;
if (!sh)
@@ -351,7 +364,10 @@ int reinit_video_chain(struct MPContext *mpctx)
d_video->opts = mpctx->opts;
d_video->header = sh;
d_video->fps = sh->codec->fps;
- d_video->vo = mpctx->video_out;
+
+ mpctx->vo_chain = talloc_zero(NULL, struct vo_chain);
+ mpctx->vo_chain->log = d_video->log;
+ mpctx->vo_chain->vo = mpctx->video_out;
MP_VERBOSE(d_video, "Container reported FPS: %f\n", sh->codec->fps);
@@ -508,7 +524,7 @@ static void init_filter_params(struct MPContext *mpctx)
static int video_filter(struct MPContext *mpctx, bool eof)
{
struct dec_video *d_video = mpctx->d_video;
- struct vf_chain *vf = d_video->vfilter;
+ struct vf_chain *vf = mpctx->vo_chain->vf;
if (vf->initialized < 0)
return VD_ERROR;
@@ -578,8 +594,7 @@ static int video_decode_and_filter(struct MPContext *mpctx)
static int video_feed_async_filter(struct MPContext *mpctx)
{
- struct dec_video *d_video = mpctx->d_video;
- struct vf_chain *vf = d_video->vfilter;
+ struct vf_chain *vf = mpctx->vo_chain->vf;
if (vf->initialized < 0)
return VD_ERROR;
@@ -714,7 +729,7 @@ static int video_output_image(struct MPContext *mpctx, double endpts)
return VD_NEW_FRAME;
int r = video_decode_and_filter(mpctx);
video_filter(mpctx, true); // force EOF filtering (avoid decoding more)
- mpctx->next_frames[0] = vf_read_output_frame(mpctx->d_video->vfilter);
+ mpctx->next_frames[0] = vf_read_output_frame(mpctx->vo_chain->vf);
if (mpctx->next_frames[0]) {
mpctx->next_frames[0]->pts = MP_NOPTS_VALUE;
mpctx->num_next_frames = 1;
@@ -732,7 +747,7 @@ static int video_output_image(struct MPContext *mpctx, double endpts)
r = video_decode_and_filter(mpctx);
if (r < 0)
return r; // error
- struct mp_image *img = vf_read_output_frame(mpctx->d_video->vfilter);
+ struct mp_image *img = vf_read_output_frame(mpctx->vo_chain->vf);
if (img) {
if (endpts != MP_NOPTS_VALUE && img->pts >= endpts) {
r = VD_EOF;
@@ -845,19 +860,19 @@ static void update_av_diff(struct MPContext *mpctx, double offset)
static void init_vo(struct MPContext *mpctx)
{
struct MPOpts *opts = mpctx->opts;
- struct dec_video *d_video = mpctx->d_video;
+ struct vo_chain *vo_c = mpctx->vo_chain;
if (opts->gamma_gamma != 1000)
- video_set_colors(d_video, "gamma", opts->gamma_gamma);
+ video_set_colors(vo_c, "gamma", opts->gamma_gamma);
if (opts->gamma_brightness != 1000)
- video_set_colors(d_video, "brightness", opts->gamma_brightness);
+ video_set_colors(vo_c, "brightness", opts->gamma_brightness);
if (opts->gamma_contrast != 1000)
- video_set_colors(d_video, "contrast", opts->gamma_contrast);
+ video_set_colors(vo_c, "contrast", opts->gamma_contrast);
if (opts->gamma_saturation != 1000)
- video_set_colors(d_video, "saturation", opts->gamma_saturation);
+ video_set_colors(vo_c, "saturation", opts->gamma_saturation);
if (opts->gamma_hue != 1000)
- video_set_colors(d_video, "hue", opts->gamma_hue);
- video_set_colors(d_video, "output-levels", opts->video_output_levels);
+ video_set_colors(vo_c, "hue", opts->gamma_hue);
+ video_set_colors(vo_c, "output-levels", opts->video_output_levels);
mp_notify(mpctx, MPV_EVENT_VIDEO_RECONFIG, NULL);
}