[FFmpeg-devel] [PATCH] lavfi: Weston 3 Field Deinterlacing Filter

Clément Bœsch u at pkh.me
Thu Sep 5 08:15:58 CEST 2013


On Thu, Sep 05, 2013 at 01:50:44AM +0000, Paul B Mahol wrote:
[...]
> +typedef struct W3FDIFContext {
> +    const AVClass *class;
> +    int filter;           ///< 0 is simple, 1 is more complex
> +    int linesize[4];      ///< bytes of pixel data per line for each plane
> +    int planeheight[4];   ///< height of each plane
> +    int field;            ///< which field are we on, 0 or 1
> +    int eof;
> +    int nb_planes;
> +    double ts_unit;
> +
> +    AVFrame *prev, *cur, *next;  ///< previous, current, next frames

> +    int32_t* work_line;   ///< line we are calculating

nitstyle: int32_t *work_line

> +
> +} W3FDIFContext;
> +
> +#define OFFSET(x) offsetof(W3FDIFContext, x)
> +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
> +#define CONST(name, val, unit) { name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=val}, 0, 0, FLAGS, unit }
> +
> +static const AVOption w3fdif_options[] = {
> +    { "filter", "specify the filter", OFFSET(filter), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "filter"},
> +    CONST("simple",  0, "filter"),
> +    CONST("complex", 1, "filter"),

> +    {NULL},

trailing comma

> +};
> +
> +AVFILTER_DEFINE_CLASS(w3fdif);
> +
> +static int query_formats(AVFilterContext *ctx)
> +{
> +    static const enum AVPixelFormat pix_fmts[] = {
> +        AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P,
> +        AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P,
> +        AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ422P,AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ411P,
> +        AV_PIX_FMT_GRAY8,
> +        AV_PIX_FMT_NONE
> +    };
> +
> +    ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
> +
> +    return 0;
> +}
> +
> +static int config_input(AVFilterLink *inlink)
> +{
> +    W3FDIFContext *s = inlink->dst->priv;
> +    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
> +    int ret;
> +
> +    if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0)
> +        return ret;
> +
> +    s->planeheight[1] = s->planeheight[2] = FF_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
> +    s->planeheight[0] = s->planeheight[3] = inlink->h;
> +
> +    s->nb_planes = av_pix_fmt_count_planes(inlink->format);

> +    s->work_line = av_calloc(s->linesize[0], sizeof(uint32_t));

sizeof(*s->work_line)

> +    if (!s->work_line)
> +        return AVERROR(ENOMEM);
> +
> +    return 0;
> +}
> +
> +static int config_output(AVFilterLink *outlink)
> +{
> +    AVFilterLink *inlink = outlink->src->inputs[0];
> +    W3FDIFContext *s = outlink->src->priv;
> +
> +    outlink->time_base.num = inlink->time_base.num;
> +    outlink->time_base.den = inlink->time_base.den * 2;
> +    outlink->frame_rate.num = inlink->frame_rate.num * 2;
> +    outlink->frame_rate.den = inlink->frame_rate.den;
> +    outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP;
> +    s->ts_unit = av_q2d(av_inv_q(av_mul_q(outlink->frame_rate, outlink->time_base)));
> +
> +    return 0;
> +}
> +
> +/** filter coefficients from PH-2071, scaled by 256*256
> + *
> + *  each set of coefficients have a sets for low-frequencies and high-frequencies
> + *  n_coef_lf[] and n_coef_hf[] are the number of coefs for simple and more-complex
> + *  it is important for later that n_coef_lf[] is even and n_coef_hf[] is odd
> + *  coef_lf[][] and coef_hf[][] are the coefficients for low-frequencies and high-
> + *                              frequencies for simple and more-complex mode */
> +static const int8_t  n_coef_lf[2]    = { 2, 4 };
> +static const int32_t   coef_lf[2][4] = {{ 32768, 32768,     0,     0},
> +                                        { -1704, 34472, 34472, -1704}};
> +static const int8_t  n_coef_hf[2]    = { 3, 5 };
> +static const int32_t   coef_hf[2][5] = {{ -4096,  8192, -4096,     0,     0},
> +                                        {  2032, -7602, 11140, -7602,  2032}};
> +
> +static void deinterlace_plane(AVFilterContext *ctx, AVFrame *out,
> +                              const AVFrame *cur, const AVFrame *adj,
> +                              const int filter, const int plane)
> +{
> +    W3FDIFContext *s = ctx->priv;
> +    uint8_t *in_line, *in_lines_cur[5], *in_lines_adj[5];
> +    uint8_t *out_line, *out_pixel;
> +    int32_t *work_line, *work_pixel;
> +    uint8_t *cur_data = cur->data[plane];

> +    uint8_t *adj_data = cur->data[plane];

adj->data[plane] ?

> +    uint8_t *dst_data = out->data[plane];
> +    const int linesize = s->linesize[plane];
> +    const int height   = s->planeheight[plane];
> +    const int cur_line_stride = cur->linesize[plane];
> +    const int adj_line_stride = adj->linesize[plane];
> +    const int dst_line_stride = out->linesize[plane];
> +    int i, j, y_in, y_out;
> +

> +    /** copy unchanged the lines of the field */

nitstyle: extra '*' in the comment

> +    y_out = s->field == cur->top_field_first;
> +
> +    in_line  = cur_data + (y_out * cur_line_stride);
> +    out_line = dst_data + (y_out * dst_line_stride);
> +
> +    while (y_out < height) {
> +        memcpy(out_line, in_line, linesize);
> +        y_out += 2;
> +        in_line  += cur_line_stride * 2;
> +        out_line += dst_line_stride * 2;
> +    }
> +
> +    /** interpolate other other lines of the field */
> +    y_out = s->field != cur->top_field_first;
> +
> +    out_line = dst_data + (y_out * dst_line_stride);
> +
> +    while (y_out < height) {
> +        /** clear workspace */

> +        memset(s->work_line, 0, sizeof(uint32_t) * linesize);

sizeof(*s->work_line)

[...]
> +        /** save scaled result to the output frame, scaling down by 256 * 256 */
> +        work_pixel = s->work_line;
> +        out_pixel = out_line;
> +        for (j = 0; j < linesize; j++) {

> +            *out_pixel = (*work_pixel > (255*256*256) ? (255*256*256) : (*work_pixel < 0 ? 0 : *work_pixel)) >> 16;

*out_pixel = av_clip(*work_pixel, 0, 255*256*256) >> 16;

> +            out_pixel++;
> +            work_pixel++;
> +        }
> +        /** move on to next line */
> +        y_out += 2;
> +        out_line += dst_line_stride * 2;
> +    }
> +}
> +
[...]
> +AVFilter avfilter_vf_w3fdif = {
> +    .name          = "w3fdif",
> +    .description   = NULL_IF_CONFIG_SMALL("Martin Weston three field deinterlace."),
> +    .priv_size     = sizeof(W3FDIFContext),
> +    .priv_class    = &w3fdif_class,
> +    .uninit        = uninit,
> +    .query_formats = query_formats,
> +    .inputs        = w3fdif_inputs,
> +    .outputs       = w3fdif_outputs,
> +};

Now it would be really awesome if that filter could deinterlace only the
frames marked as interlaced, just like yadif (see deint option). This
would make possible to use it with fieldmatch, and so that would be
awesome.

No other comment from me, thanks

-- 
Clément B.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130905/be814979/attachment.asc>


More information about the ffmpeg-devel mailing list