Merge commit '59ee9f78b0cc4fb84ae606fa317d8102ad32a627'
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 12 Oct 2012 15:04:58 +0000 (17:04 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 12 Oct 2012 15:04:58 +0000 (17:04 +0200)
* commit '59ee9f78b0cc4fb84ae606fa317d8102ad32a627':
  lavfi: do not use av_pix_fmt_descriptors directly.

Conflicts:
libavfilter/buffersrc.c
libavfilter/drawutils.c
libavfilter/filtfmts.c
libavfilter/vf_ass.c
libavfilter/vf_boxblur.c
libavfilter/vf_drawtext.c
libavfilter/vf_lut.c
libavfilter/vf_pad.c
libavfilter/vf_scale.c
libavfilter/vf_showinfo.c
libavfilter/vf_transpose.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
25 files changed:
1  2 
libavfilter/avfilter.c
libavfilter/buffersrc.c
libavfilter/drawutils.c
libavfilter/formats.c
libavfilter/vf_boxblur.c
libavfilter/vf_crop.c
libavfilter/vf_cropdetect.c
libavfilter/vf_delogo.c
libavfilter/vf_drawbox.c
libavfilter/vf_fade.c
libavfilter/vf_fieldorder.c
libavfilter/vf_gradfun.c
libavfilter/vf_hflip.c
libavfilter/vf_hqdn3d.c
libavfilter/vf_lut.c
libavfilter/vf_overlay.c
libavfilter/vf_pixdesctest.c
libavfilter/vf_scale.c
libavfilter/vf_showinfo.c
libavfilter/vf_slicify.c
libavfilter/vf_transpose.c
libavfilter/vf_unsharp.c
libavfilter/vf_vflip.c
libavfilter/vf_yadif.c
libavfilter/video.c

@@@ -305,13 -208,13 +305,13 @@@ int avfilter_config_links(AVFilterConte
      return 0;
  }
  
 -void ff_dlog_link(void *ctx, AVFilterLink *link, int end)
 +void ff_tlog_link(void *ctx, AVFilterLink *link, int end)
  {
      if (link->type == AVMEDIA_TYPE_VIDEO) {
 -        av_dlog(ctx,
 -                "link[%p s:%dx%d fmt:%-16s %-16s->%-16s]%s",
 +        ff_tlog(ctx,
 +                "link[%p s:%dx%d fmt:%s %s->%s]%s",
                  link, link->w, link->h,
-                 av_pix_fmt_descriptors[link->format].name,
+                 av_get_pix_fmt_name(link->format),
                  link->src ? link->src->filter->name : "",
                  link->dst ? link->dst->filter->name : "",
                  end ? "\n" : "");
@@@ -185,64 -163,39 +185,64 @@@ AVFILTER_DEFINE_CLASS(buffer)
  static av_cold int init_video(AVFilterContext *ctx, const char *args)
  {
      BufferSourceContext *c = ctx->priv;
 -    char pix_fmt_str[128];
 -    int n = 0;
 +    char pix_fmt_str[128], sws_param[256] = "", *colon, *equal;
 +    int ret, n = 0;
  
 -    if (!args ||
 -        (n = sscanf(args, "%d:%d:%127[^:]:%d:%d:%d:%d", &c->w, &c->h, pix_fmt_str,
 -                    &c->time_base.num, &c->time_base.den,
 -                    &c->pixel_aspect.num, &c->pixel_aspect.den)) != 7) {
 -        av_log(ctx, AV_LOG_ERROR, "Expected 7 arguments, but %d found in '%s'\n", n, args);
 +    c->class = &buffer_class;
 +
 +    if (!args) {
 +        av_log(ctx, AV_LOG_ERROR, "Arguments required\n");
          return AVERROR(EINVAL);
      }
 -    if ((c->pix_fmt = av_get_pix_fmt(pix_fmt_str)) == AV_PIX_FMT_NONE) {
 -        char *tail;
 -        c->pix_fmt = strtol(pix_fmt_str, &tail, 10);
 -        if (*tail || c->pix_fmt < 0 || c->pix_fmt >= AV_PIX_FMT_NB) {
 -            av_log(ctx, AV_LOG_ERROR, "Invalid pixel format string '%s'\n", pix_fmt_str);
 -            return AVERROR(EINVAL);
 -        }
 +    colon = strchr(args, ':');
 +    equal = strchr(args, '=');
 +    if (equal && (!colon || equal < colon)) {
 +        av_opt_set_defaults(c);
 +        ret = av_set_options_string(c, args, "=", ":");
 +        if (ret < 0)
 +            goto fail;
 +    } else {
 +    if ((n = sscanf(args, "%d:%d:%127[^:]:%d:%d:%d:%d:%255c", &c->w, &c->h, pix_fmt_str,
 +                    &c->time_base.num, &c->time_base.den,
 +                    &c->pixel_aspect.num, &c->pixel_aspect.den, sws_param)) < 7) {
 +        av_log(ctx, AV_LOG_ERROR, "Expected at least 7 arguments, but only %d found in '%s'\n", n, args);
 +        ret = AVERROR(EINVAL);
 +        goto fail;
      }
 +    av_log(ctx, AV_LOG_WARNING, "Flat options syntax is deprecated, use key=value pairs\n");
  
 -    if (!(c->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*))))
 -        return AVERROR(ENOMEM);
 +    if ((ret = ff_parse_pixel_format(&c->pix_fmt, pix_fmt_str, ctx)) < 0)
 +        goto fail;
 +    c->sws_param = av_strdup(sws_param);
 +    if (!c->sws_param) {
 +        ret = AVERROR(ENOMEM);
 +        goto fail;
 +    }
 +    }
  
 -    av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s\n", c->w, c->h, av_get_pix_fmt_name(c->pix_fmt));
 +    if (!(c->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*)))) {
 +        ret = AVERROR(ENOMEM);
 +        goto fail;
 +    }
 +
 +    av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s tb:%d/%d fr:%d/%d sar:%d/%d sws_param:%s\n",
-            c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name,
++           c->w, c->h, av_get_pix_fmt_name(c->pix_fmt),
 +           c->time_base.num, c->time_base.den, c->frame_rate.num, c->frame_rate.den,
 +           c->pixel_aspect.num, c->pixel_aspect.den, (char *)av_x_if_null(c->sws_param, ""));
 +    c->warning_limit = 100;
      return 0;
 +
 +fail:
 +    av_opt_free(c);
 +    return ret;
  }
  
 -#define OFFSET(x) offsetof(BufferSourceContext, x)
 -#define A AV_OPT_FLAG_AUDIO_PARAM
 -static const AVOption audio_options[] = {
 -    { "time_base",      NULL, OFFSET(time_base),           AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, INT_MAX, A },
 -    { "sample_rate",    NULL, OFFSET(sample_rate),         AV_OPT_TYPE_INT,      { .i64 = 0 }, 0, INT_MAX, A },
 -    { "sample_fmt",     NULL, OFFSET(sample_fmt_str),      AV_OPT_TYPE_STRING,             .flags = A },
 -    { "channel_layout", NULL, OFFSET(channel_layout_str),  AV_OPT_TYPE_STRING,             .flags = A },
 +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM
 +static const AVOption abuffer_options[] = {
 +    { "time_base",      NULL, OFFSET(time_base),           AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, INT_MAX, FLAGS },
 +    { "sample_rate",    NULL, OFFSET(sample_rate),         AV_OPT_TYPE_INT,      { .i64 = 0 }, 0, INT_MAX, FLAGS },
 +    { "sample_fmt",     NULL, OFFSET(sample_fmt_str),      AV_OPT_TYPE_STRING, .flags = FLAGS },
 +    { "channel_layout", NULL, OFFSET(channel_layout_str),  AV_OPT_TYPE_STRING, .flags = FLAGS },
      { NULL },
  };
  
@@@ -41,24 -42,10 +41,24 @@@ int ff_fill_rgba_map(uint8_t *rgba_map
      case AV_PIX_FMT_RGBA:
      case AV_PIX_FMT_RGB24: rgba_map[RED  ] = 0; rgba_map[GREEN] = 1; rgba_map[BLUE ] = 2; rgba_map[ALPHA] = 3; break;
      case AV_PIX_FMT_BGRA:
 +    case AV_PIX_FMT_BGR0:
      case AV_PIX_FMT_BGR24: rgba_map[BLUE ] = 0; rgba_map[GREEN] = 1; rgba_map[RED  ] = 2; rgba_map[ALPHA] = 3; break;
 -    default:
 -        *is_packed_rgba = 0;
 +    default:                    /* unsupported */
 +        return AVERROR(EINVAL);
      }
-     const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[pix_fmt];
 +    return 0;
 +}
 +
 +int ff_fill_line_with_color(uint8_t *line[4], int pixel_step[4], int w, uint8_t dst_color[4],
 +                            enum AVPixelFormat pix_fmt, uint8_t rgba_color[4],
 +                            int *is_packed_rgba, uint8_t rgba_map_ptr[4])
 +{
 +    uint8_t rgba_map[4] = {0};
 +    int i;
++    const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(pix_fmt);
 +    int hsub = pix_desc->log2_chroma_w;
 +
 +    *is_packed_rgba = ff_fill_rgba_map(rgba_map, pix_fmt) >= 0;
  
      if (*is_packed_rgba) {
          pixel_step[0] = (av_get_bits_per_pixel(pix_desc))>>3;
@@@ -131,423 -118,3 +131,423 @@@ void ff_copy_rectangle(uint8_t *dst[4]
          }
      }
  }
-     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[format];
 +
 +int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
 +{
-         desc = &av_pix_fmt_descriptors[f];
++    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format);
 +    const AVComponentDescriptor *c;
 +    unsigned i, nb_planes = 0;
 +    int pixelstep[MAX_PLANES] = { 0 };
 +
 +    if (!desc->name)
 +        return AVERROR(EINVAL);
 +    if (desc->flags & ~(PIX_FMT_PLANAR | PIX_FMT_RGB | PIX_FMT_PSEUDOPAL))
 +        return AVERROR(ENOSYS);
 +    for (i = 0; i < desc->nb_components; i++) {
 +        c = &desc->comp[i];
 +        /* for now, only 8-bits formats */
 +        if (c->depth_minus1 != 8 - 1)
 +            return AVERROR(ENOSYS);
 +        if (c->plane >= MAX_PLANES)
 +            return AVERROR(ENOSYS);
 +        /* strange interleaving */
 +        if (pixelstep[c->plane] != 0 &&
 +            pixelstep[c->plane] != c->step_minus1 + 1)
 +            return AVERROR(ENOSYS);
 +        pixelstep[c->plane] = c->step_minus1 + 1;
 +        if (pixelstep[c->plane] >= 8)
 +            return AVERROR(ENOSYS);
 +        nb_planes = FFMAX(nb_planes, c->plane + 1);
 +    }
 +    if ((desc->log2_chroma_w || desc->log2_chroma_h) && nb_planes < 3)
 +        return AVERROR(ENOSYS); /* exclude NV12 and NV21 */
 +    memset(draw, 0, sizeof(*draw));
 +    draw->desc      = desc;
 +    draw->format    = format;
 +    draw->nb_planes = nb_planes;
 +    memcpy(draw->pixelstep, pixelstep, sizeof(draw->pixelstep));
 +    if (nb_planes >= 3 && !(desc->flags & PIX_FMT_RGB)) {
 +        draw->hsub[1] = draw->hsub[2] = draw->hsub_max = desc->log2_chroma_w;
 +        draw->vsub[1] = draw->vsub[2] = draw->vsub_max = desc->log2_chroma_h;
 +    }
 +    for (i = 0; i < ((desc->nb_components - 1) | 1); i++)
 +        draw->comp_mask[desc->comp[i].plane] |=
 +            1 << (desc->comp[i].offset_plus1 - 1);
 +    return 0;
 +}
 +
 +void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
 +{
 +    unsigned i;
 +    uint8_t rgba_map[4];
 +
 +    if (rgba != color->rgba)
 +        memcpy(color->rgba, rgba, sizeof(color->rgba));
 +    if ((draw->desc->flags & PIX_FMT_RGB) && draw->nb_planes == 1 &&
 +        ff_fill_rgba_map(rgba_map, draw->format) >= 0) {
 +        for (i = 0; i < 4; i++)
 +            color->comp[0].u8[rgba_map[i]] = rgba[i];
 +    } else if (draw->nb_planes == 3 || draw->nb_planes == 4) {
 +        /* assume YUV */
 +        color->comp[0].u8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
 +        color->comp[1].u8[0] = RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);
 +        color->comp[2].u8[0] = RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);
 +        color->comp[3].u8[0] = rgba[3];
 +    } else if (draw->format == AV_PIX_FMT_GRAY8 || draw->format == AV_PIX_FMT_GRAY8A) {
 +        color->comp[0].u8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
 +        color->comp[1].u8[0] = rgba[3];
 +    } else {
 +        av_log(NULL, AV_LOG_WARNING,
 +               "Color conversion not implemented for %s\n", draw->desc->name);
 +        memset(color, 128, sizeof(*color));
 +    }
 +}
 +
 +static uint8_t *pointer_at(FFDrawContext *draw, uint8_t *data[], int linesize[],
 +                           int plane, int x, int y)
 +{
 +    return data[plane] +
 +           (y >> draw->vsub[plane]) * linesize[plane] +
 +           (x >> draw->hsub[plane]) * draw->pixelstep[plane];
 +}
 +
 +void ff_copy_rectangle2(FFDrawContext *draw,
 +                        uint8_t *dst[], int dst_linesize[],
 +                        uint8_t *src[], int src_linesize[],
 +                        int dst_x, int dst_y, int src_x, int src_y,
 +                        int w, int h)
 +{
 +    int plane, y, wp, hp;
 +    uint8_t *p, *q;
 +
 +    for (plane = 0; plane < draw->nb_planes; plane++) {
 +        p = pointer_at(draw, src, src_linesize, plane, src_x, src_y);
 +        q = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
 +        wp = (w >> draw->hsub[plane]) * draw->pixelstep[plane];
 +        hp = (h >> draw->vsub[plane]);
 +        for (y = 0; y < hp; y++) {
 +            memcpy(q, p, wp);
 +            p += src_linesize[plane];
 +            q += dst_linesize[plane];
 +        }
 +    }
 +}
 +
 +void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color,
 +                       uint8_t *dst[], int dst_linesize[],
 +                       int dst_x, int dst_y, int w, int h)
 +{
 +    int plane, x, y, wp, hp;
 +    uint8_t *p0, *p;
 +
 +    for (plane = 0; plane < draw->nb_planes; plane++) {
 +        p0 = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
 +        wp = (w >> draw->hsub[plane]);
 +        hp = (h >> draw->vsub[plane]);
 +        if (!hp)
 +            return;
 +        p = p0;
 +        /* copy first line from color */
 +        for (x = 0; x < wp; x++) {
 +            memcpy(p, color->comp[plane].u8, draw->pixelstep[plane]);
 +            p += draw->pixelstep[plane];
 +        }
 +        wp *= draw->pixelstep[plane];
 +        /* copy next lines from first line */
 +        p = p0 + dst_linesize[plane];
 +        for (y = 1; y < hp; y++) {
 +            memcpy(p, p0, wp);
 +            p += dst_linesize[plane];
 +        }
 +    }
 +}
 +
 +/**
 + * Clip interval [x; x+w[ within [0; wmax[.
 + * The resulting w may be negative if the final interval is empty.
 + * dx, if not null, return the difference between in and out value of x.
 + */
 +static void clip_interval(int wmax, int *x, int *w, int *dx)
 +{
 +    if (dx)
 +        *dx = 0;
 +    if (*x < 0) {
 +        if (dx)
 +            *dx = -*x;
 +        *w += *x;
 +        *x = 0;
 +    }
 +    if (*x + *w > wmax)
 +        *w = wmax - *x;
 +}
 +
 +/**
 + * Decompose w pixels starting at x
 + * into start + (w starting at x) + end
 + * with x and w aligned on multiples of 1<<sub.
 + */
 +static void subsampling_bounds(int sub, int *x, int *w, int *start, int *end)
 +{
 +    int mask = (1 << sub) - 1;
 +
 +    *start = (-*x) & mask;
 +    *x += *start;
 +    *start = FFMIN(*start, *w);
 +    *w -= *start;
 +    *end = *w & mask;
 +    *w >>= sub;
 +}
 +
 +static int component_used(FFDrawContext *draw, int plane, int comp)
 +{
 +    return (draw->comp_mask[plane] >> comp) & 1;
 +}
 +
 +/* If alpha is in the [ 0 ; 0x1010101 ] range,
 +   then alpha * value is in the [ 0 ; 0xFFFFFFFF ] range,
 +   and >> 24 gives a correct rounding. */
 +static void blend_line(uint8_t *dst, unsigned src, unsigned alpha,
 +                       int dx, int w, unsigned hsub, int left, int right)
 +{
 +    unsigned asrc = alpha * src;
 +    unsigned tau = 0x1010101 - alpha;
 +    int x;
 +
 +    src *= alpha;
 +    if (left) {
 +        unsigned suba = (left * alpha) >> hsub;
 +        *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24;
 +        dst += dx;
 +    }
 +    for (x = 0; x < w; x++) {
 +        *dst = (*dst * tau + asrc) >> 24;
 +        dst += dx;
 +    }
 +    if (right) {
 +        unsigned suba = (right * alpha) >> hsub;
 +        *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24;
 +    }
 +}
 +
 +void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color,
 +                        uint8_t *dst[], int dst_linesize[],
 +                        int dst_w, int dst_h,
 +                        int x0, int y0, int w, int h)
 +{
 +    unsigned alpha, nb_planes, nb_comp, plane, comp;
 +    int w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y;
 +    uint8_t *p0, *p;
 +
 +    /* TODO optimize if alpha = 0xFF */
 +    clip_interval(dst_w, &x0, &w, NULL);
 +    clip_interval(dst_h, &y0, &h, NULL);
 +    if (w <= 0 || h <= 0 || !color->rgba[3])
 +        return;
 +    /* 0x10203 * alpha + 2 is in the [ 2 ; 0x1010101 - 2 ] range */
 +    alpha = 0x10203 * color->rgba[3] + 0x2;
 +    nb_planes = (draw->nb_planes - 1) | 1; /* eliminate alpha */
 +    for (plane = 0; plane < nb_planes; plane++) {
 +        nb_comp = draw->pixelstep[plane];
 +        p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);
 +        w_sub = w;
 +        h_sub = h;
 +        x_sub = x0;
 +        y_sub = y0;
 +        subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);
 +        subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
 +        for (comp = 0; comp < nb_comp; comp++) {
 +            if (!component_used(draw, plane, comp))
 +                continue;
 +            p = p0 + comp;
 +            if (top) {
 +                blend_line(p, color->comp[plane].u8[comp], alpha >> 1,
 +                           draw->pixelstep[plane], w_sub,
 +                           draw->hsub[plane], left, right);
 +                p += dst_linesize[plane];
 +            }
 +            for (y = 0; y < h_sub; y++) {
 +                blend_line(p, color->comp[plane].u8[comp], alpha,
 +                           draw->pixelstep[plane], w_sub,
 +                           draw->hsub[plane], left, right);
 +                p += dst_linesize[plane];
 +            }
 +            if (bottom)
 +                blend_line(p, color->comp[plane].u8[comp], alpha >> 1,
 +                           draw->pixelstep[plane], w_sub,
 +                           draw->hsub[plane], left, right);
 +        }
 +    }
 +}
 +
 +static void blend_pixel(uint8_t *dst, unsigned src, unsigned alpha,
 +                        uint8_t *mask, int mask_linesize, int l2depth,
 +                        unsigned w, unsigned h, unsigned shift, unsigned xm0)
 +{
 +    unsigned xm, x, y, t = 0;
 +    unsigned xmshf = 3 - l2depth;
 +    unsigned xmmod = 7 >> l2depth;
 +    unsigned mbits = (1 << (1 << l2depth)) - 1;
 +    unsigned mmult = 255 / mbits;
 +
 +    for (y = 0; y < h; y++) {
 +        xm = xm0;
 +        for (x = 0; x < w; x++) {
 +            t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits)
 +                 * mmult;
 +            xm++;
 +        }
 +        mask += mask_linesize;
 +    }
 +    alpha = (t >> shift) * alpha;
 +    *dst = ((0x1010101 - alpha) * *dst + alpha * src) >> 24;
 +}
 +
 +static void blend_line_hv(uint8_t *dst, int dst_delta,
 +                          unsigned src, unsigned alpha,
 +                          uint8_t *mask, int mask_linesize, int l2depth, int w,
 +                          unsigned hsub, unsigned vsub,
 +                          int xm, int left, int right, int hband)
 +{
 +    int x;
 +
 +    if (left) {
 +        blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
 +                    left, hband, hsub + vsub, xm);
 +        dst += dst_delta;
 +        xm += left;
 +    }
 +    for (x = 0; x < w; x++) {
 +        blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
 +                    1 << hsub, hband, hsub + vsub, xm);
 +        dst += dst_delta;
 +        xm += 1 << hsub;
 +    }
 +    if (right)
 +        blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
 +                    right, hband, hsub + vsub, xm);
 +}
 +
 +void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color,
 +                   uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h,
 +                   uint8_t *mask,  int mask_linesize, int mask_w, int mask_h,
 +                   int l2depth, unsigned endianness, int x0, int y0)
 +{
 +    unsigned alpha, nb_planes, nb_comp, plane, comp;
 +    int xm0, ym0, w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y;
 +    uint8_t *p0, *p, *m;
 +
 +    clip_interval(dst_w, &x0, &mask_w, &xm0);
 +    clip_interval(dst_h, &y0, &mask_h, &ym0);
 +    mask += ym0 * mask_linesize;
 +    if (mask_w <= 0 || mask_h <= 0 || !color->rgba[3])
 +        return;
 +    /* alpha is in the [ 0 ; 0x10203 ] range,
 +       alpha * mask is in the [ 0 ; 0x1010101 - 4 ] range */
 +    alpha = (0x10307 * color->rgba[3] + 0x3) >> 8;
 +    nb_planes = (draw->nb_planes - 1) | 1; /* eliminate alpha */
 +    for (plane = 0; plane < nb_planes; plane++) {
 +        nb_comp = draw->pixelstep[plane];
 +        p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);
 +        w_sub = mask_w;
 +        h_sub = mask_h;
 +        x_sub = x0;
 +        y_sub = y0;
 +        subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);
 +        subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
 +        for (comp = 0; comp < nb_comp; comp++) {
 +            if (!component_used(draw, plane, comp))
 +                continue;
 +            p = p0 + comp;
 +            m = mask;
 +            if (top) {
 +                blend_line_hv(p, draw->pixelstep[plane],
 +                              color->comp[plane].u8[comp], alpha,
 +                              m, mask_linesize, l2depth, w_sub,
 +                              draw->hsub[plane], draw->vsub[plane],
 +                              xm0, left, right, top);
 +                p += dst_linesize[plane];
 +                m += top * mask_linesize;
 +            }
 +            for (y = 0; y < h_sub; y++) {
 +                blend_line_hv(p, draw->pixelstep[plane],
 +                              color->comp[plane].u8[comp], alpha,
 +                              m, mask_linesize, l2depth, w_sub,
 +                              draw->hsub[plane], draw->vsub[plane],
 +                              xm0, left, right, 1 << draw->vsub[plane]);
 +                p += dst_linesize[plane];
 +                m += mask_linesize << draw->vsub[plane];
 +            }
 +            if (bottom)
 +                blend_line_hv(p, draw->pixelstep[plane],
 +                              color->comp[plane].u8[comp], alpha,
 +                              m, mask_linesize, l2depth, w_sub,
 +                              draw->hsub[plane], draw->vsub[plane],
 +                              xm0, left, right, bottom);
 +        }
 +    }
 +}
 +
 +int ff_draw_round_to_sub(FFDrawContext *draw, int sub_dir, int round_dir,
 +                         int value)
 +{
 +    unsigned shift = sub_dir ? draw->vsub_max : draw->hsub_max;
 +
 +    if (!shift)
 +        return value;
 +    if (round_dir >= 0)
 +        value += round_dir ? (1 << shift) - 1 : 1 << (shift - 1);
 +    return (value >> shift) << shift;
 +}
 +
 +AVFilterFormats *ff_draw_supported_pixel_formats(unsigned flags)
 +{
 +    enum AVPixelFormat i, pix_fmts[AV_PIX_FMT_NB + 1];
 +    unsigned n = 0;
 +    FFDrawContext draw;
 +
 +    for (i = 0; i < AV_PIX_FMT_NB; i++)
 +        if (ff_draw_init(&draw, i, flags) >= 0)
 +            pix_fmts[n++] = i;
 +    pix_fmts[n++] = AV_PIX_FMT_NONE;
 +    return ff_make_format_list(pix_fmts);
 +}
 +
 +#ifdef TEST
 +
 +#undef printf
 +
 +int main(void)
 +{
 +    enum AVPixelFormat f;
 +    const AVPixFmtDescriptor *desc;
 +    FFDrawContext draw;
 +    FFDrawColor color;
 +    int r, i;
 +
 +    for (f = 0; f < AV_PIX_FMT_NB; f++) {
++        desc = av_pix_fmt_desc_get(f);
 +        if (!desc->name)
 +            continue;
 +        printf("Testing %s...%*s", desc->name,
 +               (int)(16 - strlen(desc->name)), "");
 +        r = ff_draw_init(&draw, f, 0);
 +        if (r < 0) {
 +            char buf[128];
 +            av_strerror(r, buf, sizeof(buf));
 +            printf("no: %s\n", buf);
 +            continue;
 +        }
 +        ff_draw_color(&draw, &color, (uint8_t[]) { 1, 0, 0, 1 });
 +        for (i = 0; i < sizeof(color); i++)
 +            if (((uint8_t *)&color)[i] != 128)
 +                break;
 +        if (i == sizeof(color)) {
 +            printf("fallback color\n");
 +            continue;
 +        }
 +        printf("ok\n");
 +    }
 +    return 0;
 +}
 +
 +#endif
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -174,8 -212,7 +174,8 @@@ static int config_props(AVFilterLink *i
  {
      AVFilterContext *ctx = inlink->dst;
      LutContext *lut = ctx->priv;
-     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[inlink->format];
+     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
 +    int rgba_map[4]; /* component index -> RGBA color index map */
      int min[4], max[4];
      int val, comp, ret;
  
@@@ -197,10 -113,9 +197,10 @@@ static const enum AVPixelFormat alpha_p
  static int config_input_main(AVFilterLink *inlink)
  {
      OverlayContext *over = inlink->dst->priv;
-     const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[inlink->format];
+     const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
  
 -    av_image_fill_max_pixsteps(over->max_plane_step, NULL, pix_desc);
 +    av_image_fill_max_pixsteps(over->main_pix_step,    NULL, pix_desc);
 +
      over->hsub = pix_desc->log2_chroma_w;
      over->vsub = pix_desc->log2_chroma_h;
  
Simple merge
@@@ -161,8 -154,8 +161,9 @@@ static int config_props(AVFilterLink *o
  {
      AVFilterContext *ctx = outlink->src;
      AVFilterLink *inlink = outlink->src->inputs[0];
 +    enum AVPixelFormat outfmt = outlink->format;
      ScaleContext *scale = ctx->priv;
+     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
      int64_t w, h;
      double var_values[VARS_NB], res;
      char *expr;
      var_values[VAR_IN_H]  = var_values[VAR_IH] = inlink->h;
      var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN;
      var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN;
 -    var_values[VAR_DAR]   = var_values[VAR_A]  = (double) inlink->w / inlink->h;
 +    var_values[VAR_A]     = (double) inlink->w / inlink->h;
      var_values[VAR_SAR]   = inlink->sample_aspect_ratio.num ?
          (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1;
-     var_values[VAR_HSUB]  = 1<<av_pix_fmt_descriptors[inlink->format].log2_chroma_w;
-     var_values[VAR_VSUB]  = 1<<av_pix_fmt_descriptors[inlink->format].log2_chroma_h;
 +    var_values[VAR_DAR]   = var_values[VAR_A] * var_values[VAR_SAR];
+     var_values[VAR_HSUB]  = 1 << desc->log2_chroma_w;
+     var_values[VAR_VSUB]  = 1 << desc->log2_chroma_h;
  
      /* evaluate width and height */
      av_expr_parse_and_eval(&res, (expr = scale->w_expr),
      outlink->h = h;
  
      /* TODO: make algorithm configurable */
 -    av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s -> w:%d h:%d fmt:%s flags:0x%0x\n",
 -           inlink ->w, inlink ->h, av_get_pix_fmt_name(inlink->format),
 -           outlink->w, outlink->h, av_get_pix_fmt_name(outlink->format),
 -           scale->flags);
  
-     scale->input_is_pal = av_pix_fmt_descriptors[inlink->format].flags & PIX_FMT_PAL ||
-                           av_pix_fmt_descriptors[inlink->format].flags & PIX_FMT_PSEUDOPAL;
+     scale->input_is_pal = desc->flags & PIX_FMT_PAL ||
+                           desc->flags & PIX_FMT_PSEUDOPAL;
 +    if (outfmt == AV_PIX_FMT_PAL8) outfmt = AV_PIX_FMT_BGR8;
-     scale->output_is_pal = av_pix_fmt_descriptors[outfmt].flags & PIX_FMT_PAL ||
-                            av_pix_fmt_descriptors[outfmt].flags & PIX_FMT_PSEUDOPAL;
++    scale->output_is_pal = av_pix_fmt_desc_get(outfmt)->flags & PIX_FMT_PAL ||
++                           av_pix_fmt_desc_get(outfmt)->flags & PIX_FMT_PSEUDOPAL;
  
      if (scale->sws)
          sws_freeContext(scale->sws);
              return AVERROR(EINVAL);
      }
  
 -
 -    if (inlink->sample_aspect_ratio.num)
 -        outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h*inlink->w,
 -                                                             outlink->w*inlink->h},
 -                                                inlink->sample_aspect_ratio);
 -    else
 +    if (inlink->sample_aspect_ratio.num){
 +        outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h * inlink->w, outlink->w * inlink->h}, inlink->sample_aspect_ratio);
 +    } else
          outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
  
-            inlink ->w, inlink ->h, av_pix_fmt_descriptors[ inlink->format].name,
 +    av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s sar:%d/%d -> w:%d h:%d fmt:%s sar:%d/%d flags:0x%0x\n",
-            outlink->w, outlink->h, av_pix_fmt_descriptors[outlink->format].name,
++           inlink ->w, inlink ->h, av_get_pix_fmt_name( inlink->format),
 +           inlink->sample_aspect_ratio.num, inlink->sample_aspect_ratio.den,
++           outlink->w, outlink->h, av_get_pix_fmt_name(outlink->format),
 +           outlink->sample_aspect_ratio.num, outlink->sample_aspect_ratio.den,
 +           scale->flags);
      return 0;
  
  fail:
@@@ -281,24 -262,9 +282,25 @@@ static int start_frame(AVFilterLink *li
      ScaleContext *scale = link->dst->priv;
      AVFilterLink *outlink = link->dst->outputs[0];
      AVFilterBufferRef *outpicref, *for_next_filter;
+     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
      int ret = 0;
  
 +    if(   picref->video->w != link->w
 +       || picref->video->h != link->h
 +       || picref->format   != link->format) {
 +        int ret;
 +        snprintf(scale->w_expr, sizeof(scale->w_expr)-1, "%d", outlink->w);
 +        snprintf(scale->h_expr, sizeof(scale->h_expr)-1, "%d", outlink->h);
 +
 +        link->dst->inputs[0]->format = picref->format;
 +        link->dst->inputs[0]->w      = picref->video->w;
 +        link->dst->inputs[0]->h      = picref->video->h;
 +
 +        if ((ret = config_props(outlink)) < 0)
 +            av_assert0(0); //what to do here ?
 +    }
 +
 +
      if (!scale->sws) {
          outpicref = avfilter_ref_buffer(picref, ~0);
          if (!outpicref)
          return ff_start_frame(outlink, outpicref);
      }
  
-     scale->hsub = av_pix_fmt_descriptors[link->format].log2_chroma_w;
-     scale->vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h;
+     scale->hsub = desc->log2_chroma_w;
+     scale->vsub = desc->log2_chroma_h;
  
 -    outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
 +    outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE|AV_PERM_ALIGN, outlink->w, outlink->h);
      if (!outpicref)
          return AVERROR(ENOMEM);
  
@@@ -63,13 -63,13 +64,13 @@@ static int end_frame(AVFilterLink *inli
      }
  
      av_log(ctx, AV_LOG_INFO,
 -           "n:%d pts:%"PRId64" pts_time:%f pos:%"PRId64" "
 +           "n:%d pts:%s pts_time:%s pos:%"PRId64" "
             "fmt:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c "
 -           "checksum:%u plane_checksum:[%u %u %u %u]\n",
 +           "checksum:%08X plane_checksum:[%08X",
             showinfo->frame,
 -           picref->pts, picref->pts * av_q2d(inlink->time_base), picref->pos,
 +           av_ts2str(picref->pts), av_ts2timestr(picref->pts, &inlink->time_base), picref->pos,
-            av_pix_fmt_descriptors[picref->format].name,
+            desc->name,
 -           picref->video->pixel_aspect.num, picref->video->pixel_aspect.den,
 +           picref->video->sample_aspect_ratio.num, picref->video->sample_aspect_ratio.den,
             picref->video->w, picref->video->h,
             !picref->video->interlaced     ? 'P' :         /* Progressive  */
             picref->video->top_field_first ? 'T' : 'B',    /* Top / Bottom */
Simple merge
@@@ -116,29 -98,13 +116,30 @@@ static int config_props_output(AVFilter
      AVFilterContext *ctx = outlink->src;
      TransContext *trans = ctx->priv;
      AVFilterLink *inlink = ctx->inputs[0];
-     const AVPixFmtDescriptor *pixdesc = &av_pix_fmt_descriptors[outlink->format];
+     const AVPixFmtDescriptor *desc_out = av_pix_fmt_desc_get(outlink->format);
+     const AVPixFmtDescriptor *desc_in  = av_pix_fmt_desc_get(inlink->format);
  
-     trans->hsub = av_pix_fmt_descriptors[inlink->format].log2_chroma_w;
-     trans->vsub = av_pix_fmt_descriptors[inlink->format].log2_chroma_h;
 +    if (trans->dir&4) {
 +        av_log(ctx, AV_LOG_WARNING,
 +               "dir values greater than 3 are deprecated, use the passthrough option instead\n");
 +        trans->dir &= 3;
 +        trans->passthrough = TRANSPOSE_PT_TYPE_LANDSCAPE;
 +    }
 +
 +    if ((inlink->w >= inlink->h && trans->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) ||
 +        (inlink->w <= inlink->h && trans->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) {
 +        av_log(ctx, AV_LOG_VERBOSE,
 +               "w:%d h:%d -> w:%d h:%d (passthrough mode)\n",
 +               inlink->w, inlink->h, inlink->w, inlink->h);
 +        return 0;
 +    } else {
 +        trans->passthrough = TRANSPOSE_PT_TYPE_NONE;
 +    }
 +
+     trans->hsub = desc_in->log2_chroma_w;
+     trans->vsub = desc_in->log2_chroma_h;
  
-     av_image_fill_max_pixsteps(trans->pixsteps, NULL, pixdesc);
+     av_image_fill_max_pixsteps(trans->pixsteps, NULL, desc_out);
  
      outlink->w = inlink->h;
      outlink->h = inlink->w;
Simple merge
Simple merge
@@@ -190,9 -187,9 +190,9 @@@ static int return_frame(AVFilterContex
      }
  
      if (!yadif->csp)
-         yadif->csp = &av_pix_fmt_descriptors[link->format];
+         yadif->csp = av_pix_fmt_desc_get(link->format);
      if (yadif->csp->comp[0].depth_minus1 / 8 == 1)
 -        yadif->filter_line = filter_line_c_16bit;
 +        yadif->filter_line = (void*)filter_line_c_16bit;
  
      filter(ctx, yadif->out, tff ^ !is_second, tff);
  
Simple merge