[FFmpeg-devel] Rotate video filter

Stefano Sabatini stefano.sabatini-lala
Sun Oct 10 12:03:11 CEST 2010


On date Saturday 2010-10-09 22:29:53 +0200, Radek Polak encoded:
> Hi,
> i would like to write video converter which scales & rotates video. I found 
> scale option but i havent found rotate option, so i assume it's missing in 
> current ffmpeg.
> 
> However i searched web and found SOC project of Vitor Sessak who implemented 
> video filter that can be used for rotation [1].
> 
> I have checked out the sources from svn://svn.ffmpeg.org/soc/libavfilter and did 
> a patch (attached) against current ffmpeg for this video filter and for me it 
> works good.
> 
> Would it be possible to include such patch in ffmpeg upstream sources?

We're already discussing a rotate filter, but given that this is a
simpler variant I guess it makes sense to implement this functionality
as a separate filter.

> Thanks
> 
> Radek
> 
> [1] http://www.mail-archive.com/ffmpeg-soc at mplayerhq.hu/msg01688.html

> From 4a1f2f6ae45c90acbdf1e2e5bce97e1c05263f01 Mon Sep 17 00:00:00 2001
> From: Vitor Sessak <vitor1001 at gmail.com>
> Date: Sat, 9 Oct 2010 22:12:33 +0200
> Subject: [PATCH] Added transpose video filter
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
> 
> It can be used together with vflip to rotate videos:
> 
> traspose + vflip == 90?ccw rotate
> vflip + transpose== 90? cw rotate
> ---
>  libavfilter/vf_transpose.c |  134 ++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 134 insertions(+), 0 deletions(-)
>  create mode 100644 libavfilter/vf_transpose.c
> 
> diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
> new file mode 100644
> index 0000000..c968283
> --- /dev/null
> +++ b/libavfilter/vf_transpose.c
> @@ -0,0 +1,134 @@
> +/*

> + * transpose (line => column) video filter

remove this line, file description goes in @file

> + * Copyright (c) 2008 Vitor Sessak

Nit: (c) => (C)

> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +/**
> + * @file
> + * Transposition filter
> + *
> + * @todo handle packed pixel formats

What about to fix this?

> + */
> +
> +#include "avfilter.h"
> +
> +typedef struct
> +{

nit: typedef struct {

> +    int hsub, vsub;
> +} TransContext;
> +
> +static int config_props_input(AVFilterLink *link)

inlink for better readability.

> +{
> +    TransContext *trans = link->dst->priv;
> +
> +    avcodec_get_chroma_sub_sample(link->format, &trans->hsub, &trans->vsub);

This add a dependency on libavcodec. Use av_pix_fmt_descriptors.

> +
> +    return 0;
> +}
> +
> +static int query_formats(AVFilterContext *ctx)
> +{
> +    enum PixelFormat pix_fmts[] = {
> +        PIX_FMT_YUV444P,  PIX_FMT_YUV422P,  PIX_FMT_YUV420P,
> +        PIX_FMT_YUV411P,  PIX_FMT_YUV410P,
> +        PIX_FMT_YUVJ444P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ420P,
> +        PIX_FMT_YUV440P,  PIX_FMT_YUVJ440P,
> +        PIX_FMT_NONE
> +    };
> +
> +    avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
> +    return 0;
> +}
> +
> +static int config_props_output(AVFilterLink *link)

inlink

> +{
> +    link->w = link->src->inputs[0]->h;
> +    link->h = link->src->inputs[0]->w;
> +
> +    return 0;
> +}
> +
> +static void end_frame(AVFilterLink *link)
> +{

inlink

> +    TransContext *trans = link->dst->priv;
> +    AVFilterBufferRef *in  = link->cur_buf;
> +    AVFilterBufferRef *out = link->dst->outputs[0]->out_buf;
> +    AVFilterBufferRef *pic = link->cur_buf;

pic is redundant

> +    AVFilterLink *output = link->dst->outputs[0];
> +    int i, j, plane;
> +
> +    /* luma plane */
> +    for(i = 0; i < pic->video->h; i ++)

nit: for_( here and below

> +        for(j = 0; j < pic->video->w; j ++)
> +            *(out->data[0] +   j *out->linesize[0] + i) =
> +                *(in->data[0]+ i * in->linesize[0] + j);
> +
> +    /* chroma planes */
> +    for(plane = 1; plane < 3; plane ++) {
> +        for(i = 0; i < pic->video->h >> trans->vsub; i++) {
> +            for(j = 0; j < pic->video->w >> trans->hsub; j++)
> +                *(out->data[plane] +   j *out->linesize[plane] + i) =
> +                    *(in->data[plane]+ i * in->linesize[plane] + j);
> +        }
> +    }
> +
> +    avfilter_unref_buffer(in);
> +    avfilter_draw_slice(output, 0, out->video->h, 1);
> +    avfilter_end_frame(output);
> +    avfilter_unref_buffer(out);
> +}
> +
> +static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)

inlink

> +{
> +    AVFilterLink *out = link->dst->outputs[0];

outlink

> +
> +    out->out_buf      = avfilter_get_video_buffer(out, AV_PERM_WRITE, out->w, out->h);
> +    out->out_buf->pts = picref->pts;
> +
> +    if (picref->video->pixel_aspect.num == 0) {
> +        out->out_buf->video->pixel_aspect = picref->video->pixel_aspect;
> +    } else {
> +        out->out_buf->video->pixel_aspect.num = picref->video->pixel_aspect.den;
> +        out->out_buf->video->pixel_aspect.den = picref->video->pixel_aspect.num;
> +    }
> +
> +    avfilter_start_frame(out, avfilter_ref_buffer(out->out_buf, ~0));
> +}
> +

> +AVFilter avfilter_vf_transpose =
> +{

nit: "avfilter_vf_transpose = {" on the same line

> +    .name      = "transpose",
> +

missing .description

> +    .priv_size = sizeof(TransContext),
> +
> +    .query_formats = query_formats,
> +
> +    .inputs    = (AVFilterPad[]) {{ .name            = "default",
> +                                    .type            = AVMEDIA_TYPE_VIDEO,
> +                                    .start_frame     = start_frame,
> +                                    .end_frame       = end_frame,
> +                                    .config_props    = config_props_input,
> +                                    .min_perms       = AV_PERM_READ, },
> +                                  { .name = NULL}},
> +    .outputs   = (AVFilterPad[]) {{ .name            = "default",
> +                                    .config_props    = config_props_output,
> +                                    .type            = AVMEDIA_TYPE_VIDEO, },
> +                                  { .name = NULL}},
> +};

Missing docs in doc/filters.texi.
-- 
FFmpeg = Faithful and Faithful Martial Portable Embarassing Gigant



More information about the ffmpeg-devel mailing list