Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Wed, 5 Mar 2014 12:51:09 +0000 (13:51 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Wed, 5 Mar 2014 12:51:44 +0000 (13:51 +0100)
* qatar/master:
  avfilter: Add missing emms_c when needed

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavfilter/af_volume.c
libavfilter/vf_hqdn3d.c

diff --combined libavfilter/af_volume.c
@@@ -2,20 -2,20 +2,20 @@@
   * Copyright (c) 2011 Stefano Sabatini
   * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -39,82 -39,53 +39,82 @@@ static const char *precision_str[] = 
      "fixed", "float", "double"
  };
  
 +static const char *const var_names[] = {
 +    "n",                   ///< frame number (starting at zero)
 +    "nb_channels",         ///< number of channels
 +    "nb_consumed_samples", ///< number of samples consumed by the filter
 +    "nb_samples",          ///< number of samples in the current frame
 +    "pos",                 ///< position in the file of the frame
 +    "pts",                 ///< frame presentation timestamp
 +    "sample_rate",         ///< sample rate
 +    "startpts",            ///< PTS at start of stream
 +    "startt",              ///< time at start of stream
 +    "t",                   ///< time in the file of the frame
 +    "tb",                  ///< timebase
 +    "volume",              ///< last set value
 +    NULL
 +};
 +
  #define OFFSET(x) offsetof(VolumeContext, x)
  #define A AV_OPT_FLAG_AUDIO_PARAM
 -
 -static const AVOption options[] = {
 -    { "volume", "Volume adjustment.",
 -            OFFSET(volume), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 0, 0x7fffff, A },
 -    { "precision", "Mathematical precision.",
 -            OFFSET(precision), AV_OPT_TYPE_INT, { .i64 = PRECISION_FLOAT }, PRECISION_FIXED, PRECISION_DOUBLE, A, "precision" },
 -        { "fixed",  "8-bit fixed-point.",     0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FIXED  }, INT_MIN, INT_MAX, A, "precision" },
 -        { "float",  "32-bit floating-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FLOAT  }, INT_MIN, INT_MAX, A, "precision" },
 -        { "double", "64-bit floating-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_DOUBLE }, INT_MIN, INT_MAX, A, "precision" },
 -    { NULL },
 +#define F AV_OPT_FLAG_FILTERING_PARAM
 +
 +static const AVOption volume_options[] = {
 +    { "volume", "set volume adjustment expression",
 +            OFFSET(volume_expr), AV_OPT_TYPE_STRING, { .str = "1.0" }, .flags = A|F },
 +    { "precision", "select mathematical precision",
 +            OFFSET(precision), AV_OPT_TYPE_INT, { .i64 = PRECISION_FLOAT }, PRECISION_FIXED, PRECISION_DOUBLE, A|F, "precision" },
 +        { "fixed",  "select 8-bit fixed-point",     0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FIXED  }, INT_MIN, INT_MAX, A|F, "precision" },
 +        { "float",  "select 32-bit floating-point", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FLOAT  }, INT_MIN, INT_MAX, A|F, "precision" },
 +        { "double", "select 64-bit floating-point", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_DOUBLE }, INT_MIN, INT_MAX, A|F, "precision" },
 +    { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_ONCE}, 0, EVAL_MODE_NB-1, .flags = A|F, "eval" },
 +         { "once",  "eval volume expression once", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_ONCE},  .flags = A|F, .unit = "eval" },
 +         { "frame", "eval volume expression per-frame",                  0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = A|F, .unit = "eval" },
 +    { NULL }
  };
  
 -static const AVClass volume_class = {
 -    .class_name = "volume filter",
 -    .item_name  = av_default_item_name,
 -    .option     = options,
 -    .version    = LIBAVUTIL_VERSION_INT,
 -};
 +AVFILTER_DEFINE_CLASS(volume);
  
 -static av_cold int init(AVFilterContext *ctx)
 +static int set_expr(AVExpr **pexpr, const char *expr, void *log_ctx)
  {
 -    VolumeContext *vol = ctx->priv;
 -
 -    if (vol->precision == PRECISION_FIXED) {
 -        vol->volume_i = (int)(vol->volume * 256 + 0.5);
 -        vol->volume   = vol->volume_i / 256.0;
 -        av_log(ctx, AV_LOG_VERBOSE, "volume:(%d/256)(%f)(%1.2fdB) precision:fixed\n",
 -               vol->volume_i, vol->volume, 20.0*log(vol->volume)/M_LN10);
 -    } else {
 -        av_log(ctx, AV_LOG_VERBOSE, "volume:(%f)(%1.2fdB) precision:%s\n",
 -               vol->volume, 20.0*log(vol->volume)/M_LN10,
 -               precision_str[vol->precision]);
 +    int ret;
 +    AVExpr *old = NULL;
 +
 +    if (*pexpr)
 +        old = *pexpr;
 +    ret = av_expr_parse(pexpr, expr, var_names,
 +                        NULL, NULL, NULL, NULL, 0, log_ctx);
 +    if (ret < 0) {
 +        av_log(log_ctx, AV_LOG_ERROR,
 +               "Error when evaluating the volume expression '%s'\n", expr);
 +        *pexpr = old;
 +        return ret;
      }
  
 +    av_expr_free(old);
      return 0;
  }
  
 +static av_cold int init(AVFilterContext *ctx)
 +{
 +    VolumeContext *vol = ctx->priv;
 +    return set_expr(&vol->volume_pexpr, vol->volume_expr, ctx);
 +}
 +
 +static av_cold void uninit(AVFilterContext *ctx)
 +{
 +    VolumeContext *vol = ctx->priv;
 +    av_expr_free(vol->volume_pexpr);
 +    av_opt_free(vol);
 +}
 +
  static int query_formats(AVFilterContext *ctx)
  {
      VolumeContext *vol = ctx->priv;
      AVFilterFormats *formats = NULL;
      AVFilterChannelLayouts *layouts;
      static const enum AVSampleFormat sample_fmts[][7] = {
 -        /* PRECISION_FIXED */
 -        {
 +        [PRECISION_FIXED] = {
              AV_SAMPLE_FMT_U8,
              AV_SAMPLE_FMT_U8P,
              AV_SAMPLE_FMT_S16,
              AV_SAMPLE_FMT_S32P,
              AV_SAMPLE_FMT_NONE
          },
 -        /* PRECISION_FLOAT */
 -        {
 +        [PRECISION_FLOAT] = {
              AV_SAMPLE_FMT_FLT,
              AV_SAMPLE_FMT_FLTP,
              AV_SAMPLE_FMT_NONE
          },
 -        /* PRECISION_DOUBLE */
 -        {
 +        [PRECISION_DOUBLE] = {
              AV_SAMPLE_FMT_DBL,
              AV_SAMPLE_FMT_DBLP,
              AV_SAMPLE_FMT_NONE
          }
      };
  
 -    layouts = ff_all_channel_layouts();
 +    layouts = ff_all_channel_counts();
      if (!layouts)
          return AVERROR(ENOMEM);
      ff_set_common_channel_layouts(ctx, layouts);
@@@ -199,6 -172,8 +199,6 @@@ static inline void scale_samples_s32(ui
          smp_dst[i] = av_clipl_int32((((int64_t)smp_src[i] * volume + 128) >> 8));
  }
  
 -
 -
  static av_cold void volume_init(VolumeContext *vol)
  {
      vol->samples_align = 1;
          ff_volume_init_x86(vol);
  }
  
 +static int set_volume(AVFilterContext *ctx)
 +{
 +    VolumeContext *vol = ctx->priv;
 +
 +    vol->volume = av_expr_eval(vol->volume_pexpr, vol->var_values, NULL);
 +    if (isnan(vol->volume)) {
 +        if (vol->eval_mode == EVAL_MODE_ONCE) {
 +            av_log(ctx, AV_LOG_ERROR, "Invalid value NaN for volume\n");
 +            return AVERROR(EINVAL);
 +        } else {
 +            av_log(ctx, AV_LOG_WARNING, "Invalid value NaN for volume, setting to 0\n");
 +            vol->volume = 0;
 +        }
 +    }
 +    vol->var_values[VAR_VOLUME] = vol->volume;
 +
 +    av_log(ctx, AV_LOG_VERBOSE, "n:%f t:%f pts:%f precision:%s ",
 +           vol->var_values[VAR_N], vol->var_values[VAR_T], vol->var_values[VAR_PTS],
 +           precision_str[vol->precision]);
 +
 +    if (vol->precision == PRECISION_FIXED) {
 +        vol->volume_i = (int)(vol->volume * 256 + 0.5);
 +        vol->volume   = vol->volume_i / 256.0;
 +        av_log(ctx, AV_LOG_VERBOSE, "volume_i:%d/255 ", vol->volume_i);
 +    }
 +    av_log(ctx, AV_LOG_VERBOSE, "volume:%f volume_dB:%f\n",
 +           vol->volume, 20.0*log(vol->volume)/M_LN10);
 +
 +    volume_init(vol);
 +    return 0;
 +}
 +
  static int config_output(AVFilterLink *outlink)
  {
      AVFilterContext *ctx = outlink->src;
      AVFilterLink *inlink = ctx->inputs[0];
  
      vol->sample_fmt = inlink->format;
 -    vol->channels   = av_get_channel_layout_nb_channels(inlink->channel_layout);
 +    vol->channels   = inlink->channels;
      vol->planes     = av_sample_fmt_is_planar(inlink->format) ? vol->channels : 1;
  
 -    volume_init(vol);
 +    vol->var_values[VAR_N] =
 +    vol->var_values[VAR_NB_CONSUMED_SAMPLES] =
 +    vol->var_values[VAR_NB_SAMPLES] =
 +    vol->var_values[VAR_POS] =
 +    vol->var_values[VAR_PTS] =
 +    vol->var_values[VAR_STARTPTS] =
 +    vol->var_values[VAR_STARTT] =
 +    vol->var_values[VAR_T] =
 +    vol->var_values[VAR_VOLUME] = NAN;
 +
 +    vol->var_values[VAR_NB_CHANNELS] = inlink->channels;
 +    vol->var_values[VAR_TB]          = av_q2d(inlink->time_base);
 +    vol->var_values[VAR_SAMPLE_RATE] = inlink->sample_rate;
 +
 +    av_log(inlink->src, AV_LOG_VERBOSE, "tb:%f sample_rate:%f nb_channels:%f\n",
 +           vol->var_values[VAR_TB],
 +           vol->var_values[VAR_SAMPLE_RATE],
 +           vol->var_values[VAR_NB_CHANNELS]);
 +
 +    return set_volume(ctx);
 +}
  
 -    return 0;
 +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
 +                           char *res, int res_len, int flags)
 +{
 +    VolumeContext *vol = ctx->priv;
 +    int ret = AVERROR(ENOSYS);
 +
 +    if (!strcmp(cmd, "volume")) {
 +        if ((ret = set_expr(&vol->volume_pexpr, args, ctx)) < 0)
 +            return ret;
 +        if (vol->eval_mode == EVAL_MODE_ONCE)
 +            set_volume(ctx);
 +    }
 +
 +    return ret;
  }
  
 +#define D2TS(d)  (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
 +#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
 +#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)*av_q2d(tb))
 +
  static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
  {
 +    AVFilterContext *ctx = inlink->dst;
      VolumeContext *vol    = inlink->dst->priv;
      AVFilterLink *outlink = inlink->dst->outputs[0];
      int nb_samples        = buf->nb_samples;
      AVFrame *out_buf;
 +    int64_t pos;
      int ret;
  
 -    if (vol->volume == 1.0 || vol->volume_i == 256)
 -        return ff_filter_frame(outlink, buf);
 +    if (isnan(vol->var_values[VAR_STARTPTS])) {
 +        vol->var_values[VAR_STARTPTS] = TS2D(buf->pts);
 +        vol->var_values[VAR_STARTT  ] = TS2T(buf->pts, inlink->time_base);
 +    }
 +    vol->var_values[VAR_PTS] = TS2D(buf->pts);
 +    vol->var_values[VAR_T  ] = TS2T(buf->pts, inlink->time_base);
 +    vol->var_values[VAR_N  ] = inlink->frame_count;
 +
 +    pos = av_frame_get_pkt_pos(buf);
 +    vol->var_values[VAR_POS] = pos == -1 ? NAN : pos;
 +    if (vol->eval_mode == EVAL_MODE_FRAME)
 +        set_volume(ctx);
 +
 +    if (vol->volume == 1.0 || vol->volume_i == 256) {
 +        out_buf = buf;
 +        goto end;
 +    }
  
      /* do volume scaling in-place if input buffer is writable */
      if (av_frame_is_writable(buf)) {
          }
      }
  
+     emms_c();
      if (buf != out_buf)
          av_frame_free(&buf);
  
 +end:
 +    vol->var_values[VAR_NB_CONSUMED_SAMPLES] += out_buf->nb_samples;
      return ff_filter_frame(outlink, out_buf);
  }
  
@@@ -422,9 -311,6 +424,9 @@@ AVFilter ff_af_volume = 
      .priv_size      = sizeof(VolumeContext),
      .priv_class     = &volume_class,
      .init           = init,
 +    .uninit         = uninit,
      .inputs         = avfilter_af_volume_inputs,
      .outputs        = avfilter_af_volume_outputs,
 +    .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 +    .process_command = process_command,
  };
diff --combined libavfilter/vf_hqdn3d.c
@@@ -3,20 -3,20 +3,20 @@@
   * Copyright (c) 2010 Baptiste Coudurier
   * Copyright (c) 2012 Loren Merritt
   *
 - * This file is part of Libav, ported from MPlayer.
 + * This file is part of FFmpeg, ported from MPlayer.
   *
 - * Libav is free software; you can redistribute it and/or modify
 + * FFmpeg is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License along
 - * with Libav; if not, write to the Free Software Foundation, Inc.,
 + * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   */
  
@@@ -147,6 -147,7 +147,7 @@@ static void denoise_depth(HQDN3DContex
      else
          denoise_temporal(src, dst, frame_ant,
                           w, h, sstride, dstride, temporal, depth);
+     emms_c();
  }
  
  #define denoise(...) \
@@@ -229,15 -230,15 +230,15 @@@ static int query_formats(AVFilterContex
          AV_PIX_FMT_YUVJ422P,
          AV_PIX_FMT_YUVJ444P,
          AV_PIX_FMT_YUVJ440P,
 -        AV_NE( AV_PIX_FMT_YUV420P9BE, AV_PIX_FMT_YUV420P9LE ),
 -        AV_NE( AV_PIX_FMT_YUV422P9BE, AV_PIX_FMT_YUV422P9LE ),
 -        AV_NE( AV_PIX_FMT_YUV444P9BE, AV_PIX_FMT_YUV444P9LE ),
 -        AV_NE( AV_PIX_FMT_YUV420P10BE, AV_PIX_FMT_YUV420P10LE ),
 -        AV_NE( AV_PIX_FMT_YUV422P10BE, AV_PIX_FMT_YUV422P10LE ),
 -        AV_NE( AV_PIX_FMT_YUV444P10BE, AV_PIX_FMT_YUV444P10LE ),
 -        AV_NE( AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_YUV420P16LE ),
 -        AV_NE( AV_PIX_FMT_YUV422P16BE, AV_PIX_FMT_YUV422P16LE ),
 -        AV_NE( AV_PIX_FMT_YUV444P16BE, AV_PIX_FMT_YUV444P16LE ),
 +        AV_PIX_FMT_YUV420P9,
 +        AV_PIX_FMT_YUV422P9,
 +        AV_PIX_FMT_YUV444P9,
 +        AV_PIX_FMT_YUV420P10,
 +        AV_PIX_FMT_YUV422P10,
 +        AV_PIX_FMT_YUV444P10,
 +        AV_PIX_FMT_YUV420P16,
 +        AV_PIX_FMT_YUV422P16,
 +        AV_PIX_FMT_YUV444P16,
          AV_PIX_FMT_NONE
      };
  
@@@ -276,14 -277,12 +277,14 @@@ static int config_input(AVFilterLink *i
  
  static int filter_frame(AVFilterLink *inlink, AVFrame *in)
  {
 -    HQDN3DContext *s = inlink->dst->priv;
 -    AVFilterLink *outlink = inlink->dst->outputs[0];
 +    AVFilterContext *ctx  = inlink->dst;
 +    HQDN3DContext *s = ctx->priv;
 +    AVFilterLink *outlink = ctx->outputs[0];
 +
      AVFrame *out;
      int direct, c;
  
 -    if (av_frame_is_writable(in)) {
 +    if (av_frame_is_writable(in) && !ctx->is_disabled) {
          direct = 1;
          out = in;
      } else {
          }
  
          av_frame_copy_props(out, in);
 -        out->width  = outlink->w;
 -        out->height = outlink->h;
      }
  
      for (c = 0; c < 3; c++) {
          denoise(s, in->data[c], out->data[c],
                  s->line, &s->frame_prev[c],
 -                in->width  >> (!!c * s->hsub),
 -                in->height >> (!!c * s->vsub),
 +                FF_CEIL_RSHIFT(in->width,  (!!c * s->hsub)),
 +                FF_CEIL_RSHIFT(in->height, (!!c * s->vsub)),
                  in->linesize[c], out->linesize[c],
 -                s->coefs[c?2:0], s->coefs[c?3:1]);
 +                s->coefs[c ? CHROMA_SPATIAL : LUMA_SPATIAL],
 +                s->coefs[c ? CHROMA_TMP     : LUMA_TMP]);
 +    }
 +
 +    if (ctx->is_disabled) {
 +        av_frame_free(&out);
 +        return ff_filter_frame(outlink, in);
      }
  
      if (!direct)
  }
  
  #define OFFSET(x) offsetof(HQDN3DContext, x)
 -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM
 -static const AVOption options[] = {
 +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
 +static const AVOption hqdn3d_options[] = {
      { "luma_spatial",   "spatial luma strength",    OFFSET(strength[LUMA_SPATIAL]),   AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, 0, DBL_MAX, FLAGS },
      { "chroma_spatial", "spatial chroma strength",  OFFSET(strength[CHROMA_SPATIAL]), AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, 0, DBL_MAX, FLAGS },
      { "luma_tmp",       "temporal luma strength",   OFFSET(strength[LUMA_TMP]),       AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, 0, DBL_MAX, FLAGS },
      { "chroma_tmp",     "temporal chroma strength", OFFSET(strength[CHROMA_TMP]),     AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, 0, DBL_MAX, FLAGS },
 -    { NULL },
 +    { NULL }
  };
  
 -static const AVClass hqdn3d_class = {
 -    .class_name = "hqdn3d",
 -    .item_name  = av_default_item_name,
 -    .option     = options,
 -    .version    = LIBAVUTIL_VERSION_INT,
 -};
 +AVFILTER_DEFINE_CLASS(hqdn3d);
  
  static const AVFilterPad avfilter_vf_hqdn3d_inputs[] = {
      {
      { NULL }
  };
  
 +
  static const AVFilterPad avfilter_vf_hqdn3d_outputs[] = {
      {
          .name = "default",
  AVFilter ff_vf_hqdn3d = {
      .name          = "hqdn3d",
      .description   = NULL_IF_CONFIG_SMALL("Apply a High Quality 3D Denoiser."),
 -
      .priv_size     = sizeof(HQDN3DContext),
      .priv_class    = &hqdn3d_class,
      .init          = init,
      .uninit        = uninit,
      .query_formats = query_formats,
 -
 -    .inputs    = avfilter_vf_hqdn3d_inputs,
 -
 -    .outputs   = avfilter_vf_hqdn3d_outputs,
 +    .inputs        = avfilter_vf_hqdn3d_inputs,
 +    .outputs       = avfilter_vf_hqdn3d_outputs,
 +    .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
  };