[FFmpeg-devel] [PATCH] avfilter/vf_tile: add overlap option
Nicolas George
george at nsup.org
Sun Nov 12 18:15:00 EET 2017
Le primidi 21 brumaire, an CCXXVI, Paul B Mahol a écrit :
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
> ---
> doc/filters.texi | 5 +++++
> libavfilter/vf_tile.c | 54 ++++++++++++++++++++++++++++++++++++++++++---------
> 2 files changed, 50 insertions(+), 9 deletions(-)
>
> diff --git a/doc/filters.texi b/doc/filters.texi
> index 5c6729a484..6079290fbd 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -14441,6 +14441,11 @@ refer to the pad video filter.
> Specify the color of the unused area. For the syntax of this option, check the
> "Color" section in the ffmpeg-utils manual. The default value of @var{color}
> is "black".
> +
> + at item overlap
> +Set the number of frames to overlap when tiling several successive frames together.
> +The default value is @code{0}, meaning overlap @var{0} frames. If it is more
> +than @var{nb_frames - 1} its set to @var{nb_frames - 1} and warning is displayed.
"The value must be between 0 and nb_frames-1", and do not specify what
happens if it is outside the range. Otherwise, we cannot extend the
behaviour without breaking the API.
> @end table
>
> @subsection Examples
> diff --git a/libavfilter/vf_tile.c b/libavfilter/vf_tile.c
> index e9d246fc73..7717ce12e7 100644
> --- a/libavfilter/vf_tile.c
> +++ b/libavfilter/vf_tile.c
> @@ -37,11 +37,13 @@ typedef struct TileContext {
> unsigned w, h;
> unsigned margin;
> unsigned padding;
> + unsigned overlap;
> unsigned current;
> unsigned nb_frames;
> FFDrawContext draw;
> FFDrawColor blank;
> AVFrame *out_ref;
> + AVFrame *prev_out_ref;
> uint8_t rgba_color[4];
> } TileContext;
>
> @@ -58,6 +60,8 @@ static const AVOption tile_options[] = {
> { "padding", "set inner border thickness in pixels", OFFSET(padding),
> AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1024, FLAGS },
> { "color", "set the color of the unused area", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str = "black"}, .flags = FLAGS },
> + { "overlap", "set how many frames to overlap for each render", OFFSET(overlap),
> + AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS },
> { NULL }
> };
>
> @@ -90,6 +94,11 @@ static av_cold int init(AVFilterContext *ctx)
> return AVERROR(EINVAL);
> }
>
> + if (tile->overlap >= tile->nb_frames) {
> + av_log(ctx, AV_LOG_WARNING, "overlap must be less than %d\n", tile->nb_frames);
> + tile->overlap = tile->nb_frames - 1;
> + }
> +
> return 0;
> }
>
> @@ -120,19 +129,19 @@ static int config_props(AVFilterLink *outlink)
> outlink->h = tile->h * inlink->h + total_margin_h;
> outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
> outlink->frame_rate = av_mul_q(inlink->frame_rate,
> - av_make_q(1, tile->nb_frames));
> + av_make_q(1, tile->nb_frames - tile->overlap));
> ff_draw_init(&tile->draw, inlink->format, 0);
> ff_draw_color(&tile->draw, &tile->blank, tile->rgba_color);
>
> return 0;
> }
>
> -static void get_current_tile_pos(AVFilterContext *ctx, unsigned *x, unsigned *y)
> +static void get_tile_pos(AVFilterContext *ctx, unsigned *x, unsigned *y, unsigned current)
> {
> TileContext *tile = ctx->priv;
> AVFilterLink *inlink = ctx->inputs[0];
> - const unsigned tx = tile->current % tile->w;
> - const unsigned ty = tile->current / tile->w;
> + const unsigned tx = current % tile->w;
> + const unsigned ty = current / tile->w;
>
> *x = tile->margin + (inlink->w + tile->padding) * tx;
> *y = tile->margin + (inlink->h + tile->padding) * ty;
> @@ -144,7 +153,7 @@ static void draw_blank_frame(AVFilterContext *ctx, AVFrame *out_buf)
> AVFilterLink *inlink = ctx->inputs[0];
> unsigned x0, y0;
>
> - get_current_tile_pos(ctx, &x0, &y0);
> + get_tile_pos(ctx, &x0, &y0, tile->current);
> ff_fill_rectangle(&tile->draw, &tile->blank,
> out_buf->data, out_buf->linesize,
> x0, y0, inlink->w, inlink->h);
> @@ -160,8 +169,13 @@ static int end_last_frame(AVFilterContext *ctx)
>
> while (tile->current < tile->nb_frames)
> draw_blank_frame(ctx, out_buf);
> + tile->current = tile->overlap;
> + if (tile->current) {
> + av_frame_free(&tile->prev_out_ref);
> + tile->prev_out_ref = av_frame_clone(out_buf);
> + }
> ret = ff_filter_frame(outlink, out_buf);
> - tile->current = 0;
> + tile->out_ref = NULL;
> return ret;
> }
>
> @@ -176,7 +190,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
> AVFilterLink *outlink = ctx->outputs[0];
> unsigned x0, y0;
>
> - if (!tile->current) {
> + if (!tile->out_ref) {
> tile->out_ref = ff_get_video_buffer(outlink, outlink->w, outlink->h);
> if (!tile->out_ref) {
> av_frame_free(&picref);
> @@ -194,7 +208,21 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
> 0, 0, outlink->w, outlink->h);
> }
>
> - get_current_tile_pos(ctx, &x0, &y0);
> + if (tile->prev_out_ref) {
> + unsigned x1, y1, i;
> +
> + for (i = tile->nb_frames - tile->overlap; i < tile->nb_frames; i++) {
> + get_tile_pos(ctx, &x1, &y1, i);
> + get_tile_pos(ctx, &x0, &y0, i - (tile->nb_frames - tile->overlap));
> + ff_copy_rectangle2(&tile->draw,
> + tile->out_ref->data, tile->out_ref->linesize,
> + tile->prev_out_ref->data, tile->prev_out_ref->linesize,
> + x0, y0, x1, y1, inlink->w, inlink->h);
> +
> + }
> + }
> +
> + get_tile_pos(ctx, &x0, &y0, tile->current);
> ff_copy_rectangle2(&tile->draw,
> tile->out_ref->data, tile->out_ref->linesize,
> picref->data, picref->linesize,
> @@ -215,11 +243,18 @@ static int request_frame(AVFilterLink *outlink)
> int r;
>
> r = ff_request_frame(inlink);
> - if (r == AVERROR_EOF && tile->current)
> + if (r == AVERROR_EOF && tile->current && tile->out_ref)
> r = end_last_frame(ctx);
> return r;
> }
>
> +static av_cold void uninit(AVFilterContext *ctx)
> +{
> + TileContext *tile = ctx->priv;
> +
> + av_frame_free(&tile->prev_out_ref);
> +}
> +
> static const AVFilterPad tile_inputs[] = {
> {
> .name = "default",
> @@ -243,6 +278,7 @@ AVFilter ff_vf_tile = {
> .name = "tile",
> .description = NULL_IF_CONFIG_SMALL("Tile several successive frames together."),
> .init = init,
> + .uninit = uninit,
> .query_formats = query_formats,
> .priv_size = sizeof(TileContext),
> .inputs = tile_inputs,
Apart from the minor point about the doc, LGTM. Thanks.
Regards,
--
Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20171112/1ffe3ac3/attachment.sig>
More information about the ffmpeg-devel
mailing list