Merge commit 'b1abd2aaf91be249f24cb74db9c205d9e4ca9da6'
authorHendrik Leppkes <h.leppkes@gmail.com>
Mon, 31 Aug 2015 08:07:34 +0000 (10:07 +0200)
committerHendrik Leppkes <h.leppkes@gmail.com>
Mon, 31 Aug 2015 08:07:34 +0000 (10:07 +0200)
* commit 'b1abd2aaf91be249f24cb74db9c205d9e4ca9da6':
  vf_scale: Add an option to pass the scaler params

Merged-by: Hendrik Leppkes <h.leppkes@gmail.com>
1  2 
libavfilter/vf_scale.c

@@@ -81,11 -76,10 +81,12 @@@ typedef struct ScaleContext 
       * New dimensions. Special values are:
       *   0 = original width/height
       *  -1 = keep original aspect
 +     *  -N = try to keep aspect but make sure it is divisible by N
       */
      int w, h;
 +    char *size_str;
      unsigned int flags;         ///sws flags
+     double param[2];            // sws params
  
      int hsub, vsub;             ///< chroma subsampling
      int slice_y;                ///< top of current output slice
@@@ -343,76 -233,25 +344,78 @@@ static int config_props(AVFilterLink *o
  
      if (scale->sws)
          sws_freeContext(scale->sws);
 -    if (inlink->w == outlink->w && inlink->h == outlink->h &&
 -        inlink->format == outlink->format)
 -        scale->sws = NULL;
 +    if (scale->isws[0])
 +        sws_freeContext(scale->isws[0]);
 +    if (scale->isws[1])
 +        sws_freeContext(scale->isws[1]);
 +    scale->isws[0] = scale->isws[1] = scale->sws = NULL;
 +    if (inlink0->w == outlink->w &&
 +        inlink0->h == outlink->h &&
 +        !scale->out_color_matrix &&
 +        scale->in_range == scale->out_range &&
 +        inlink0->format == outlink->format)
 +        ;
      else {
 -        scale->sws = sws_getContext(inlink ->w, inlink ->h, inlink ->format,
 -                                    outlink->w, outlink->h, outlink->format,
 -                                    scale->flags, NULL, NULL, scale->param);
 -        if (!scale->sws)
 -            return AVERROR(EINVAL);
 -    }
 +        struct SwsContext **swscs[3] = {&scale->sws, &scale->isws[0], &scale->isws[1]};
 +        int i;
 +
 +        for (i = 0; i < 3; i++) {
 +            struct SwsContext **s = swscs[i];
 +            *s = sws_alloc_context();
 +            if (!*s)
 +                return AVERROR(ENOMEM);
 +
 +            av_opt_set_int(*s, "srcw", inlink0 ->w, 0);
 +            av_opt_set_int(*s, "srch", inlink0 ->h >> !!i, 0);
 +            av_opt_set_int(*s, "src_format", inlink0->format, 0);
 +            av_opt_set_int(*s, "dstw", outlink->w, 0);
 +            av_opt_set_int(*s, "dsth", outlink->h >> !!i, 0);
 +            av_opt_set_int(*s, "dst_format", outfmt, 0);
 +            av_opt_set_int(*s, "sws_flags", scale->flags, 0);
++            av_opt_set_int(*s, "param0", scale->param[0], 0);
++            av_opt_set_int(*s, "param1", scale->param[1], 0);
 +
 +            if (scale->opts) {
 +                AVDictionaryEntry *e = NULL;
 +                while ((e = av_dict_get(scale->opts, "", e, AV_DICT_IGNORE_SUFFIX))) {
 +                    if ((ret = av_opt_set(*s, e->key, e->value, 0)) < 0)
 +                        return ret;
 +                }
 +            }
 +            /* Override YUV420P settings to have the correct (MPEG-2) chroma positions
 +             * MPEG-2 chroma positions are used by convention
 +             * XXX: support other 4:2:0 pixel formats */
 +            if (inlink0->format == AV_PIX_FMT_YUV420P) {
 +                scale->in_v_chr_pos = (i == 0) ? 128 : (i == 1) ? 64 : 192;
 +            }
  
 +            if (outlink->format == AV_PIX_FMT_YUV420P) {
 +                scale->out_v_chr_pos = (i == 0) ? 128 : (i == 1) ? 64 : 192;
 +            }
 +
 +            av_opt_set_int(*s, "src_h_chr_pos", scale->in_h_chr_pos, 0);
 +            av_opt_set_int(*s, "src_v_chr_pos", scale->in_v_chr_pos, 0);
 +            av_opt_set_int(*s, "dst_h_chr_pos", scale->out_h_chr_pos, 0);
 +            av_opt_set_int(*s, "dst_v_chr_pos", scale->out_v_chr_pos, 0);
  
 -    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 ((ret = sws_init_context(*s, NULL, NULL)) < 0)
 +                return ret;
 +            if (!scale->interlaced)
 +                break;
 +        }
 +    }
 +
 +    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;
  
 +    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",
 +           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:
@@@ -574,73 -295,15 +577,75 @@@ static int filter_frame(AVFilterLink *l
      return ff_filter_frame(outlink, out);
  }
  
 +static int filter_frame_ref(AVFilterLink *link, AVFrame *in)
 +{
 +    AVFilterLink *outlink = link->dst->outputs[1];
 +
 +    return ff_filter_frame(outlink, in);
 +}
 +
 +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
 +                           char *res, int res_len, int flags)
 +{
 +    ScaleContext *scale = ctx->priv;
 +    int ret;
 +
 +    if (   !strcmp(cmd, "width")  || !strcmp(cmd, "w")
 +        || !strcmp(cmd, "height") || !strcmp(cmd, "h")) {
 +
 +        int old_w = scale->w;
 +        int old_h = scale->h;
 +        AVFilterLink *outlink = ctx->outputs[0];
 +
 +        av_opt_set(scale, cmd, args, 0);
 +        if ((ret = config_props(outlink)) < 0) {
 +            scale->w = old_w;
 +            scale->h = old_h;
 +        }
 +    } else
 +        ret = AVERROR(ENOSYS);
 +
 +    return ret;
 +}
 +
 +static const AVClass *child_class_next(const AVClass *prev)
 +{
 +    return prev ? NULL : sws_get_class();
 +}
 +
  #define OFFSET(x) offsetof(ScaleContext, x)
 -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM
 -static const AVOption options[] = {
 -    { "w",     "Output video width",          OFFSET(w_expr),    AV_OPT_TYPE_STRING, { .str = "iw" },       .flags = FLAGS },
 -    { "h",     "Output video height",         OFFSET(h_expr),    AV_OPT_TYPE_STRING, { .str = "ih" },       .flags = FLAGS },
 +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
 +
 +static const AVOption scale_options[] = {
 +    { "w",     "Output video width",          OFFSET(w_expr),    AV_OPT_TYPE_STRING,        .flags = FLAGS },
 +    { "width", "Output video width",          OFFSET(w_expr),    AV_OPT_TYPE_STRING,        .flags = FLAGS },
 +    { "h",     "Output video height",         OFFSET(h_expr),    AV_OPT_TYPE_STRING,        .flags = FLAGS },
 +    { "height","Output video height",         OFFSET(h_expr),    AV_OPT_TYPE_STRING,        .flags = FLAGS },
      { "flags", "Flags to pass to libswscale", OFFSET(flags_str), AV_OPT_TYPE_STRING, { .str = "bilinear" }, .flags = FLAGS },
 -    { NULL },
 +    { "interl", "set interlacing", OFFSET(interlaced), AV_OPT_TYPE_INT, {.i64 = 0 }, -1, 1, FLAGS },
 +    { "size",   "set video size",          OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, FLAGS },
 +    { "s",      "set video size",          OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, FLAGS },
 +    {  "in_color_matrix", "set input YCbCr type",   OFFSET(in_color_matrix),  AV_OPT_TYPE_STRING, { .str = "auto" }, .flags = FLAGS },
 +    { "out_color_matrix", "set output YCbCr type",  OFFSET(out_color_matrix), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS },
 +    {  "in_range", "set input color range",  OFFSET( in_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 2, FLAGS, "range" },
 +    { "out_range", "set output color range", OFFSET(out_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 2, FLAGS, "range" },
 +    { "auto",   NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, 0, FLAGS, "range" },
 +    { "full",   NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_JPEG}, 0, 0, FLAGS, "range" },
 +    { "jpeg",   NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_JPEG}, 0, 0, FLAGS, "range" },
 +    { "mpeg",   NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_MPEG}, 0, 0, FLAGS, "range" },
 +    { "tv",     NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_MPEG}, 0, 0, FLAGS, "range" },
 +    { "pc",     NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_JPEG}, 0, 0, FLAGS, "range" },
 +    { "in_v_chr_pos",   "input vertical chroma position in luma grid/256"  ,   OFFSET(in_v_chr_pos),  AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS },
 +    { "in_h_chr_pos",   "input horizontal chroma position in luma grid/256",   OFFSET(in_h_chr_pos),  AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS },
 +    { "out_v_chr_pos",   "output vertical chroma position in luma grid/256"  , OFFSET(out_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS },
 +    { "out_h_chr_pos",   "output horizontal chroma position in luma grid/256", OFFSET(out_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS },
 +    { "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 2, FLAGS, "force_oar" },
 +    { "disable",  NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "force_oar" },
 +    { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "force_oar" },
 +    { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, "force_oar" },
+     { "param0", "Scaler param 0",             OFFSET(param[0]),  AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT  }, INT_MIN, INT_MAX, FLAGS },
+     { "param1", "Scaler param 1",             OFFSET(param[1]),  AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT  }, INT_MIN, INT_MAX, FLAGS },
 +    { NULL }
  };
  
  static const AVClass scale_class = {