diff options
Diffstat (limited to 'player')
-rw-r--r-- | player/command.c | 49 | ||||
-rw-r--r-- | player/core.h | 16 | ||||
-rw-r--r-- | player/sub.c | 4 | ||||
-rw-r--r-- | player/video.c | 145 |
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, ¶ms); } 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, ¶m) == VO_TRUE; + return vo_control(vo_c->vo, VOCTRL_SET_EQUALIZER, ¶m) == 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, ¶m) == VO_TRUE; + return vo_control(vo_c->vo, VOCTRL_GET_EQUALIZER, ¶m) == 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, ¶ms) < 0) { - vf_remove_filter(d_video->vfilter, vf); + if (vf_reconfig(vo_c->vf, ¶ms) < 0) { + vf_remove_filter(vo_c->vf, vf); // restore - vf_reconfig(d_video->vfilter, ¶ms); + vf_reconfig(vo_c->vf, ¶ms); 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, ¶ms) < 0) { + if (vf_reconfig(vo_c->vf, ¶ms) < 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); } |