diff options
Diffstat (limited to 'video/filter/vf_sub.c')
-rw-r--r-- | video/filter/vf_sub.c | 177 |
1 files changed, 94 insertions, 83 deletions
diff --git a/video/filter/vf_sub.c b/video/filter/vf_sub.c index 065a8c66c7..8b2c1c83f0 100644 --- a/video/filter/vf_sub.c +++ b/video/filter/vf_sub.c @@ -29,11 +29,13 @@ #include "config.h" #include "common/msg.h" +#include "filters/filter.h" +#include "filters/filter_internal.h" +#include "filters/user_filters.h" #include "options/options.h" - #include "video/img_format.h" #include "video/mp_image.h" -#include "vf.h" +#include "video/mp_image_pool.h" #include "sub/osd.h" #include "sub/dec_sub.h" @@ -41,112 +43,121 @@ #include "options/m_option.h" -struct vf_priv_s { - int opt_top_margin, opt_bottom_margin; - - int outh, outw; +struct vf_sub_opts { + int top_margin, bottom_margin; +}; - struct osd_state *osd; - struct mp_osd_res dim; +struct priv { + struct vf_sub_opts *opts; + struct mp_image_pool *pool; }; -static int reconfig(struct vf_instance *vf, struct mp_image_params *in, - struct mp_image_params *out) +static void vf_sub_process(struct mp_filter *f) { - int width = in->w, height = in->h; - - vf->priv->outh = height + vf->priv->opt_top_margin + - vf->priv->opt_bottom_margin; - vf->priv->outw = width; - - vf->priv->dim = (struct mp_osd_res) { - .w = vf->priv->outw, - .h = vf->priv->outh, - .mt = vf->priv->opt_top_margin, - .mb = vf->priv->opt_bottom_margin, - .display_par = in->p_w / (double)in->p_h, - }; + struct priv *priv = f->priv; - *out = *in; - out->w = vf->priv->outw; - out->h = vf->priv->outh; - return 0; -} + if (!mp_pin_can_transfer_data(f->ppins[1], f->ppins[0])) + return; -static void prepare_image(struct vf_instance *vf, struct mp_image *dmpi, - struct mp_image *mpi) -{ - int y1 = MP_ALIGN_DOWN(vf->priv->opt_top_margin, mpi->fmt.align_y); - int y2 = MP_ALIGN_DOWN(y1 + mpi->h, mpi->fmt.align_y); - struct mp_image cropped = *dmpi; - mp_image_crop(&cropped, 0, y1, mpi->w, y1 + mpi->h); - mp_image_copy(&cropped, mpi); - mp_image_clear(dmpi, 0, 0, dmpi->w, y1); - mp_image_clear(dmpi, 0, y2, dmpi->w, vf->priv->outh); -} + struct mp_frame frame = mp_pin_out_read(f->ppins[0]); -static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) -{ - struct vf_priv_s *priv = vf->priv; - struct osd_state *osd = priv->osd; + if (mp_frame_is_signaling(frame)) { + mp_pin_in_write(f->ppins[1], frame); + return; + } + + struct mp_stream_info *info = mp_filter_find_stream_info(f); + struct osd_state *osd = info ? info->osd : NULL; + + if (!osd) + goto error; + + osd_set_render_subs_in_filter(osd, true); + + if (frame.type != MP_FRAME_VIDEO) + goto error; + + struct mp_image *mpi = frame.data; - if (vf->priv->opt_top_margin || vf->priv->opt_bottom_margin) { - struct mp_image *dmpi = vf_alloc_out_image(vf); + if (!mp_sws_supported_format(mpi->imgfmt)) + goto error; + + struct mp_osd_res dim = { + .w = mpi->w, + .h = mpi->h + priv->opts->top_margin + priv->opts->bottom_margin, + .mt = priv->opts->top_margin, + .mb = priv->opts->bottom_margin, + .display_par = mpi->params.p_w / (double)mpi->params.p_h, + }; + + if (dim.w != mpi->w || dim.h != mpi->h) { + struct mp_image *dmpi = + mp_image_pool_get(priv->pool, mpi->imgfmt, dim.w, dim.h); if (!dmpi) - return NULL; + goto error; mp_image_copy_attributes(dmpi, mpi); - prepare_image(vf, dmpi, mpi); - talloc_free(mpi); + int y1 = MP_ALIGN_DOWN(priv->opts->top_margin, mpi->fmt.align_y); + int y2 = MP_ALIGN_DOWN(y1 + mpi->h, mpi->fmt.align_y); + struct mp_image cropped = *dmpi; + mp_image_crop(&cropped, 0, y1, mpi->w, y1 + mpi->h); + mp_image_copy(&cropped, mpi); + mp_image_clear(dmpi, 0, 0, dmpi->w, y1); + mp_image_clear(dmpi, 0, y2, dmpi->w, dim.h); + mp_frame_unref(&frame); mpi = dmpi; + frame = (struct mp_frame){MP_FRAME_VIDEO, mpi}; } - if (!osd) - return mpi; + osd_draw_on_image_p(osd, dim, mpi->pts, OSD_DRAW_SUB_FILTER, priv->pool, mpi); - osd_draw_on_image_p(osd, priv->dim, mpi->pts, OSD_DRAW_SUB_FILTER, - vf->out_pool, mpi); + mp_pin_in_write(f->ppins[1], frame); + return; - return mpi; +error: + MP_ERR(f, "unsupported format, missing OSD, or failed allocation\n"); + mp_frame_unref(&frame); + mp_filter_internal_mark_failed(f); } -static int query_format(struct vf_instance *vf, unsigned int fmt) -{ - if (!mp_sws_supported_format(fmt)) - return 0; - return vf_next_query_format(vf, fmt); -} +static const struct mp_filter_info vf_sub_filter = { + .name = "sub", + .process = vf_sub_process, + .priv_size = sizeof(struct priv), +}; -static int control(vf_instance_t *vf, int request, void *data) +static struct mp_filter *vf_sub_create(struct mp_filter *parent, void *options) { - switch (request) { - case VFCTRL_INIT_OSD: - vf->priv->osd = data; - return CONTROL_TRUE; + struct mp_filter *f = mp_filter_create(parent, &vf_sub_filter); + if (!f) { + talloc_free(options); + return NULL; } - return CONTROL_UNKNOWN; -} -static int vf_open(vf_instance_t *vf) -{ - MP_WARN(vf, "This filter is deprecated and will be removed (no replacement)\n"); - vf->reconfig = reconfig; - vf->query_format = query_format; - vf->control = control; - vf->filter = filter; - return 1; + MP_WARN(f, "This filter is deprecated and will be removed (no replacement)\n"); + + mp_filter_add_pin(f, MP_PIN_IN, "in"); + mp_filter_add_pin(f, MP_PIN_OUT, "out"); + + struct priv *priv = f->priv; + priv->opts = talloc_steal(priv, options); + priv->pool = mp_image_pool_new(priv); + + return f; } -#define OPT_BASE_STRUCT struct vf_priv_s +#define OPT_BASE_STRUCT struct vf_sub_opts static const m_option_t vf_opts_fields[] = { - OPT_INTRANGE("bottom-margin", opt_bottom_margin, 0, 0, 2000), - OPT_INTRANGE("top-margin", opt_top_margin, 0, 0, 2000), + OPT_INTRANGE("bottom-margin", bottom_margin, 0, 0, 2000), + OPT_INTRANGE("top-margin", top_margin, 0, 0, 2000), {0} }; -const vf_info_t vf_info_sub = { - .description = "Render subtitles", - .name = "sub", - .open = vf_open, - .priv_size = sizeof(struct vf_priv_s), - .options = vf_opts_fields, +const struct mp_user_filter_entry vf_sub = { + .desc = { + .description = "Render subtitles", + .name = "sub", + .priv_size = sizeof(OPT_BASE_STRUCT), + .options = vf_opts_fields, + }, + .create = vf_sub_create, }; |