LCOV - code coverage report
Current view: top level - src/libavfilter - af_volume.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 121 212 57.1 %
Date: 2017-01-28 02:43:52 Functions: 9 14 64.3 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2011 Stefano Sabatini
       3             :  * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : /**
      23             :  * @file
      24             :  * audio volume filter
      25             :  */
      26             : 
      27             : #include "libavutil/channel_layout.h"
      28             : #include "libavutil/common.h"
      29             : #include "libavutil/eval.h"
      30             : #include "libavutil/ffmath.h"
      31             : #include "libavutil/float_dsp.h"
      32             : #include "libavutil/intreadwrite.h"
      33             : #include "libavutil/opt.h"
      34             : #include "libavutil/replaygain.h"
      35             : 
      36             : #include "audio.h"
      37             : #include "avfilter.h"
      38             : #include "formats.h"
      39             : #include "internal.h"
      40             : #include "af_volume.h"
      41             : 
      42             : static const char * const precision_str[] = {
      43             :     "fixed", "float", "double"
      44             : };
      45             : 
      46             : static const char *const var_names[] = {
      47             :     "n",                   ///< frame number (starting at zero)
      48             :     "nb_channels",         ///< number of channels
      49             :     "nb_consumed_samples", ///< number of samples consumed by the filter
      50             :     "nb_samples",          ///< number of samples in the current frame
      51             :     "pos",                 ///< position in the file of the frame
      52             :     "pts",                 ///< frame presentation timestamp
      53             :     "sample_rate",         ///< sample rate
      54             :     "startpts",            ///< PTS at start of stream
      55             :     "startt",              ///< time at start of stream
      56             :     "t",                   ///< time in the file of the frame
      57             :     "tb",                  ///< timebase
      58             :     "volume",              ///< last set value
      59             :     NULL
      60             : };
      61             : 
      62             : #define OFFSET(x) offsetof(VolumeContext, x)
      63             : #define A AV_OPT_FLAG_AUDIO_PARAM
      64             : #define F AV_OPT_FLAG_FILTERING_PARAM
      65             : 
      66             : static const AVOption volume_options[] = {
      67             :     { "volume", "set volume adjustment expression",
      68             :             OFFSET(volume_expr), AV_OPT_TYPE_STRING, { .str = "1.0" }, .flags = A|F },
      69             :     { "precision", "select mathematical precision",
      70             :             OFFSET(precision), AV_OPT_TYPE_INT, { .i64 = PRECISION_FLOAT }, PRECISION_FIXED, PRECISION_DOUBLE, A|F, "precision" },
      71             :         { "fixed",  "select 8-bit fixed-point",     0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FIXED  }, INT_MIN, INT_MAX, A|F, "precision" },
      72             :         { "float",  "select 32-bit floating-point", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FLOAT  }, INT_MIN, INT_MAX, A|F, "precision" },
      73             :         { "double", "select 64-bit floating-point", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_DOUBLE }, INT_MIN, INT_MAX, A|F, "precision" },
      74             :     { "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" },
      75             :          { "once",  "eval volume expression once", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_ONCE},  .flags = A|F, .unit = "eval" },
      76             :          { "frame", "eval volume expression per-frame",                  0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = A|F, .unit = "eval" },
      77             :     { "replaygain", "Apply replaygain side data when present",
      78             :             OFFSET(replaygain), AV_OPT_TYPE_INT, { .i64 = REPLAYGAIN_DROP }, REPLAYGAIN_DROP, REPLAYGAIN_ALBUM, A|F, "replaygain" },
      79             :         { "drop",   "replaygain side data is dropped", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_DROP   }, 0, 0, A|F, "replaygain" },
      80             :         { "ignore", "replaygain side data is ignored", 0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_IGNORE }, 0, 0, A|F, "replaygain" },
      81             :         { "track",  "track gain is preferred",         0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_TRACK  }, 0, 0, A|F, "replaygain" },
      82             :         { "album",  "album gain is preferred",         0, AV_OPT_TYPE_CONST, { .i64 = REPLAYGAIN_ALBUM  }, 0, 0, A|F, "replaygain" },
      83             :     { "replaygain_preamp", "Apply replaygain pre-amplification",
      84             :             OFFSET(replaygain_preamp), AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, -15.0, 15.0, A|F },
      85             :     { "replaygain_noclip", "Apply replaygain clipping prevention",
      86             :             OFFSET(replaygain_noclip), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, A|F },
      87             :     { NULL }
      88             : };
      89             : 
      90             : AVFILTER_DEFINE_CLASS(volume);
      91             : 
      92           2 : static int set_expr(AVExpr **pexpr, const char *expr, void *log_ctx)
      93             : {
      94             :     int ret;
      95           2 :     AVExpr *old = NULL;
      96             : 
      97           2 :     if (*pexpr)
      98           0 :         old = *pexpr;
      99           2 :     ret = av_expr_parse(pexpr, expr, var_names,
     100             :                         NULL, NULL, NULL, NULL, 0, log_ctx);
     101           2 :     if (ret < 0) {
     102           0 :         av_log(log_ctx, AV_LOG_ERROR,
     103             :                "Error when evaluating the volume expression '%s'\n", expr);
     104           0 :         *pexpr = old;
     105           0 :         return ret;
     106             :     }
     107             : 
     108           2 :     av_expr_free(old);
     109           2 :     return 0;
     110             : }
     111             : 
     112           2 : static av_cold int init(AVFilterContext *ctx)
     113             : {
     114           2 :     VolumeContext *vol = ctx->priv;
     115             : 
     116           2 :     vol->fdsp = avpriv_float_dsp_alloc(0);
     117           2 :     if (!vol->fdsp)
     118           0 :         return AVERROR(ENOMEM);
     119             : 
     120           2 :     return set_expr(&vol->volume_pexpr, vol->volume_expr, ctx);
     121             : }
     122             : 
     123           2 : static av_cold void uninit(AVFilterContext *ctx)
     124             : {
     125           2 :     VolumeContext *vol = ctx->priv;
     126           2 :     av_expr_free(vol->volume_pexpr);
     127           2 :     av_opt_free(vol);
     128           2 :     av_freep(&vol->fdsp);
     129           2 : }
     130             : 
     131           2 : static int query_formats(AVFilterContext *ctx)
     132             : {
     133           2 :     VolumeContext *vol = ctx->priv;
     134           2 :     AVFilterFormats *formats = NULL;
     135             :     AVFilterChannelLayouts *layouts;
     136             :     static const enum AVSampleFormat sample_fmts[][7] = {
     137             :         [PRECISION_FIXED] = {
     138             :             AV_SAMPLE_FMT_U8,
     139             :             AV_SAMPLE_FMT_U8P,
     140             :             AV_SAMPLE_FMT_S16,
     141             :             AV_SAMPLE_FMT_S16P,
     142             :             AV_SAMPLE_FMT_S32,
     143             :             AV_SAMPLE_FMT_S32P,
     144             :             AV_SAMPLE_FMT_NONE
     145             :         },
     146             :         [PRECISION_FLOAT] = {
     147             :             AV_SAMPLE_FMT_FLT,
     148             :             AV_SAMPLE_FMT_FLTP,
     149             :             AV_SAMPLE_FMT_NONE
     150             :         },
     151             :         [PRECISION_DOUBLE] = {
     152             :             AV_SAMPLE_FMT_DBL,
     153             :             AV_SAMPLE_FMT_DBLP,
     154             :             AV_SAMPLE_FMT_NONE
     155             :         }
     156             :     };
     157             :     int ret;
     158             : 
     159           2 :     layouts = ff_all_channel_counts();
     160           2 :     if (!layouts)
     161           0 :         return AVERROR(ENOMEM);
     162           2 :     ret = ff_set_common_channel_layouts(ctx, layouts);
     163           2 :     if (ret < 0)
     164           0 :         return ret;
     165             : 
     166           2 :     formats = ff_make_format_list(sample_fmts[vol->precision]);
     167           2 :     if (!formats)
     168           0 :         return AVERROR(ENOMEM);
     169           2 :     ret = ff_set_common_formats(ctx, formats);
     170           2 :     if (ret < 0)
     171           0 :         return ret;
     172             : 
     173           2 :     formats = ff_all_samplerates();
     174           2 :     if (!formats)
     175           0 :         return AVERROR(ENOMEM);
     176           2 :     return ff_set_common_samplerates(ctx, formats);
     177             : }
     178             : 
     179           0 : static inline void scale_samples_u8(uint8_t *dst, const uint8_t *src,
     180             :                                     int nb_samples, int volume)
     181             : {
     182             :     int i;
     183           0 :     for (i = 0; i < nb_samples; i++)
     184           0 :         dst[i] = av_clip_uint8(((((int64_t)src[i] - 128) * volume + 128) >> 8) + 128);
     185           0 : }
     186             : 
     187           0 : static inline void scale_samples_u8_small(uint8_t *dst, const uint8_t *src,
     188             :                                           int nb_samples, int volume)
     189             : {
     190             :     int i;
     191           0 :     for (i = 0; i < nb_samples; i++)
     192           0 :         dst[i] = av_clip_uint8((((src[i] - 128) * volume + 128) >> 8) + 128);
     193           0 : }
     194             : 
     195           0 : static inline void scale_samples_s16(uint8_t *dst, const uint8_t *src,
     196             :                                      int nb_samples, int volume)
     197             : {
     198             :     int i;
     199           0 :     int16_t *smp_dst       = (int16_t *)dst;
     200           0 :     const int16_t *smp_src = (const int16_t *)src;
     201           0 :     for (i = 0; i < nb_samples; i++)
     202           0 :         smp_dst[i] = av_clip_int16(((int64_t)smp_src[i] * volume + 128) >> 8);
     203           0 : }
     204             : 
     205         259 : static inline void scale_samples_s16_small(uint8_t *dst, const uint8_t *src,
     206             :                                            int nb_samples, int volume)
     207             : {
     208             :     int i;
     209         259 :     int16_t *smp_dst       = (int16_t *)dst;
     210         259 :     const int16_t *smp_src = (const int16_t *)src;
     211      529459 :     for (i = 0; i < nb_samples; i++)
     212      529200 :         smp_dst[i] = av_clip_int16((smp_src[i] * volume + 128) >> 8);
     213         259 : }
     214             : 
     215           0 : static inline void scale_samples_s32(uint8_t *dst, const uint8_t *src,
     216             :                                      int nb_samples, int volume)
     217             : {
     218             :     int i;
     219           0 :     int32_t *smp_dst       = (int32_t *)dst;
     220           0 :     const int32_t *smp_src = (const int32_t *)src;
     221           0 :     for (i = 0; i < nb_samples; i++)
     222           0 :         smp_dst[i] = av_clipl_int32((((int64_t)smp_src[i] * volume + 128) >> 8));
     223           0 : }
     224             : 
     225           2 : static av_cold void volume_init(VolumeContext *vol)
     226             : {
     227           2 :     vol->samples_align = 1;
     228             : 
     229           2 :     switch (av_get_packed_sample_fmt(vol->sample_fmt)) {
     230             :     case AV_SAMPLE_FMT_U8:
     231           0 :         if (vol->volume_i < 0x1000000)
     232           0 :             vol->scale_samples = scale_samples_u8_small;
     233             :         else
     234           0 :             vol->scale_samples = scale_samples_u8;
     235           0 :         break;
     236             :     case AV_SAMPLE_FMT_S16:
     237           1 :         if (vol->volume_i < 0x10000)
     238           1 :             vol->scale_samples = scale_samples_s16_small;
     239             :         else
     240           0 :             vol->scale_samples = scale_samples_s16;
     241           1 :         break;
     242             :     case AV_SAMPLE_FMT_S32:
     243           0 :         vol->scale_samples = scale_samples_s32;
     244           0 :         break;
     245             :     case AV_SAMPLE_FMT_FLT:
     246           1 :         vol->samples_align = 4;
     247           1 :         break;
     248             :     case AV_SAMPLE_FMT_DBL:
     249           0 :         vol->samples_align = 8;
     250           0 :         break;
     251             :     }
     252             : 
     253             :     if (ARCH_X86)
     254           2 :         ff_volume_init_x86(vol);
     255           2 : }
     256             : 
     257           2 : static int set_volume(AVFilterContext *ctx)
     258             : {
     259           2 :     VolumeContext *vol = ctx->priv;
     260             : 
     261           2 :     vol->volume = av_expr_eval(vol->volume_pexpr, vol->var_values, NULL);
     262           2 :     if (isnan(vol->volume)) {
     263           0 :         if (vol->eval_mode == EVAL_MODE_ONCE) {
     264           0 :             av_log(ctx, AV_LOG_ERROR, "Invalid value NaN for volume\n");
     265           0 :             return AVERROR(EINVAL);
     266             :         } else {
     267           0 :             av_log(ctx, AV_LOG_WARNING, "Invalid value NaN for volume, setting to 0\n");
     268           0 :             vol->volume = 0;
     269             :         }
     270             :     }
     271           2 :     vol->var_values[VAR_VOLUME] = vol->volume;
     272             : 
     273           2 :     av_log(ctx, AV_LOG_VERBOSE, "n:%f t:%f pts:%f precision:%s ",
     274             :            vol->var_values[VAR_N], vol->var_values[VAR_T], vol->var_values[VAR_PTS],
     275           2 :            precision_str[vol->precision]);
     276             : 
     277           2 :     if (vol->precision == PRECISION_FIXED) {
     278           1 :         vol->volume_i = (int)(vol->volume * 256 + 0.5);
     279           1 :         vol->volume   = vol->volume_i / 256.0;
     280           1 :         av_log(ctx, AV_LOG_VERBOSE, "volume_i:%d/255 ", vol->volume_i);
     281             :     }
     282           2 :     av_log(ctx, AV_LOG_VERBOSE, "volume:%f volume_dB:%f\n",
     283           2 :            vol->volume, 20.0*log10(vol->volume));
     284             : 
     285           2 :     volume_init(vol);
     286           2 :     return 0;
     287             : }
     288             : 
     289           2 : static int config_output(AVFilterLink *outlink)
     290             : {
     291           2 :     AVFilterContext *ctx = outlink->src;
     292           2 :     VolumeContext *vol   = ctx->priv;
     293           2 :     AVFilterLink *inlink = ctx->inputs[0];
     294             : 
     295           2 :     vol->sample_fmt = inlink->format;
     296           2 :     vol->channels   = inlink->channels;
     297           2 :     vol->planes     = av_sample_fmt_is_planar(inlink->format) ? vol->channels : 1;
     298             : 
     299           2 :     vol->var_values[VAR_N] =
     300           2 :     vol->var_values[VAR_NB_CONSUMED_SAMPLES] =
     301           2 :     vol->var_values[VAR_NB_SAMPLES] =
     302           2 :     vol->var_values[VAR_POS] =
     303           2 :     vol->var_values[VAR_PTS] =
     304           2 :     vol->var_values[VAR_STARTPTS] =
     305           2 :     vol->var_values[VAR_STARTT] =
     306           2 :     vol->var_values[VAR_T] =
     307           2 :     vol->var_values[VAR_VOLUME] = NAN;
     308             : 
     309           2 :     vol->var_values[VAR_NB_CHANNELS] = inlink->channels;
     310           2 :     vol->var_values[VAR_TB]          = av_q2d(inlink->time_base);
     311           2 :     vol->var_values[VAR_SAMPLE_RATE] = inlink->sample_rate;
     312             : 
     313           2 :     av_log(inlink->src, AV_LOG_VERBOSE, "tb:%f sample_rate:%f nb_channels:%f\n",
     314             :            vol->var_values[VAR_TB],
     315             :            vol->var_values[VAR_SAMPLE_RATE],
     316             :            vol->var_values[VAR_NB_CHANNELS]);
     317             : 
     318           2 :     return set_volume(ctx);
     319             : }
     320             : 
     321           0 : static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
     322             :                            char *res, int res_len, int flags)
     323             : {
     324           0 :     VolumeContext *vol = ctx->priv;
     325           0 :     int ret = AVERROR(ENOSYS);
     326             : 
     327           0 :     if (!strcmp(cmd, "volume")) {
     328           0 :         if ((ret = set_expr(&vol->volume_pexpr, args, ctx)) < 0)
     329           0 :             return ret;
     330           0 :         if (vol->eval_mode == EVAL_MODE_ONCE)
     331           0 :             set_volume(ctx);
     332             :     }
     333             : 
     334           0 :     return ret;
     335             : }
     336             : 
     337             : #define D2TS(d)  (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
     338             : #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
     339             : #define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)*av_q2d(tb))
     340             : 
     341         300 : static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
     342             : {
     343         300 :     AVFilterContext *ctx = inlink->dst;
     344         300 :     VolumeContext *vol    = inlink->dst->priv;
     345         300 :     AVFilterLink *outlink = inlink->dst->outputs[0];
     346         300 :     int nb_samples        = buf->nb_samples;
     347             :     AVFrame *out_buf;
     348             :     int64_t pos;
     349         300 :     AVFrameSideData *sd = av_frame_get_side_data(buf, AV_FRAME_DATA_REPLAYGAIN);
     350             :     int ret;
     351             : 
     352         300 :     if (sd && vol->replaygain != REPLAYGAIN_IGNORE) {
     353           0 :         if (vol->replaygain != REPLAYGAIN_DROP) {
     354           0 :             AVReplayGain *replaygain = (AVReplayGain*)sd->data;
     355           0 :             int32_t gain  = 100000;
     356           0 :             uint32_t peak = 100000;
     357             :             float g, p;
     358             : 
     359           0 :             if (vol->replaygain == REPLAYGAIN_TRACK &&
     360           0 :                 replaygain->track_gain != INT32_MIN) {
     361           0 :                 gain = replaygain->track_gain;
     362             : 
     363           0 :                 if (replaygain->track_peak != 0)
     364           0 :                     peak = replaygain->track_peak;
     365           0 :             } else if (replaygain->album_gain != INT32_MIN) {
     366           0 :                 gain = replaygain->album_gain;
     367             : 
     368           0 :                 if (replaygain->album_peak != 0)
     369           0 :                     peak = replaygain->album_peak;
     370             :             } else {
     371           0 :                 av_log(inlink->dst, AV_LOG_WARNING, "Both ReplayGain gain "
     372             :                        "values are unknown.\n");
     373             :             }
     374           0 :             g = gain / 100000.0f;
     375           0 :             p = peak / 100000.0f;
     376             : 
     377           0 :             av_log(inlink->dst, AV_LOG_VERBOSE,
     378             :                    "Using gain %f dB from replaygain side data.\n", g);
     379             : 
     380           0 :             vol->volume   = ff_exp10((g + vol->replaygain_preamp) / 20);
     381           0 :             if (vol->replaygain_noclip)
     382           0 :                 vol->volume = FFMIN(vol->volume, 1.0 / p);
     383           0 :             vol->volume_i = (int)(vol->volume * 256 + 0.5);
     384             : 
     385           0 :             volume_init(vol);
     386             :         }
     387           0 :         av_frame_remove_side_data(buf, AV_FRAME_DATA_REPLAYGAIN);
     388             :     }
     389             : 
     390         300 :     if (isnan(vol->var_values[VAR_STARTPTS])) {
     391           2 :         vol->var_values[VAR_STARTPTS] = TS2D(buf->pts);
     392           2 :         vol->var_values[VAR_STARTT  ] = TS2T(buf->pts, inlink->time_base);
     393             :     }
     394         300 :     vol->var_values[VAR_PTS] = TS2D(buf->pts);
     395         300 :     vol->var_values[VAR_T  ] = TS2T(buf->pts, inlink->time_base);
     396         300 :     vol->var_values[VAR_N  ] = inlink->frame_count_out;
     397             : 
     398         300 :     pos = av_frame_get_pkt_pos(buf);
     399         300 :     vol->var_values[VAR_POS] = pos == -1 ? NAN : pos;
     400         300 :     if (vol->eval_mode == EVAL_MODE_FRAME)
     401           0 :         set_volume(ctx);
     402             : 
     403         300 :     if (vol->volume == 1.0 || vol->volume_i == 256) {
     404           0 :         out_buf = buf;
     405           0 :         goto end;
     406             :     }
     407             : 
     408             :     /* do volume scaling in-place if input buffer is writable */
     409         300 :     if (av_frame_is_writable(buf)
     410         300 :             && (vol->precision != PRECISION_FIXED || vol->volume_i > 0)) {
     411         300 :         out_buf = buf;
     412             :     } else {
     413           0 :         out_buf = ff_get_audio_buffer(inlink, nb_samples);
     414           0 :         if (!out_buf)
     415           0 :             return AVERROR(ENOMEM);
     416           0 :         ret = av_frame_copy_props(out_buf, buf);
     417           0 :         if (ret < 0) {
     418           0 :             av_frame_free(&out_buf);
     419           0 :             av_frame_free(&buf);
     420           0 :             return ret;
     421             :         }
     422             :     }
     423             : 
     424         300 :     if (vol->precision != PRECISION_FIXED || vol->volume_i > 0) {
     425             :         int p, plane_samples;
     426             : 
     427         300 :         if (av_sample_fmt_is_planar(buf->format))
     428          41 :             plane_samples = FFALIGN(nb_samples, vol->samples_align);
     429             :         else
     430         259 :             plane_samples = FFALIGN(nb_samples * vol->channels, vol->samples_align);
     431             : 
     432         300 :         if (vol->precision == PRECISION_FIXED) {
     433         518 :             for (p = 0; p < vol->planes; p++) {
     434         518 :                 vol->scale_samples(out_buf->extended_data[p],
     435         259 :                                    buf->extended_data[p], plane_samples,
     436             :                                    vol->volume_i);
     437             :             }
     438          41 :         } else if (av_get_packed_sample_fmt(vol->sample_fmt) == AV_SAMPLE_FMT_FLT) {
     439         123 :             for (p = 0; p < vol->planes; p++) {
     440         246 :                 vol->fdsp->vector_fmul_scalar((float *)out_buf->extended_data[p],
     441          82 :                                              (const float *)buf->extended_data[p],
     442          82 :                                              vol->volume, plane_samples);
     443             :             }
     444             :         } else {
     445           0 :             for (p = 0; p < vol->planes; p++) {
     446           0 :                 vol->fdsp->vector_dmul_scalar((double *)out_buf->extended_data[p],
     447           0 :                                              (const double *)buf->extended_data[p],
     448             :                                              vol->volume, plane_samples);
     449             :             }
     450             :         }
     451             :     }
     452             : 
     453         300 :     emms_c();
     454             : 
     455         300 :     if (buf != out_buf)
     456           0 :         av_frame_free(&buf);
     457             : 
     458             : end:
     459         300 :     vol->var_values[VAR_NB_CONSUMED_SAMPLES] += out_buf->nb_samples;
     460         300 :     return ff_filter_frame(outlink, out_buf);
     461             : }
     462             : 
     463             : static const AVFilterPad avfilter_af_volume_inputs[] = {
     464             :     {
     465             :         .name           = "default",
     466             :         .type           = AVMEDIA_TYPE_AUDIO,
     467             :         .filter_frame   = filter_frame,
     468             :     },
     469             :     { NULL }
     470             : };
     471             : 
     472             : static const AVFilterPad avfilter_af_volume_outputs[] = {
     473             :     {
     474             :         .name         = "default",
     475             :         .type         = AVMEDIA_TYPE_AUDIO,
     476             :         .config_props = config_output,
     477             :     },
     478             :     { NULL }
     479             : };
     480             : 
     481             : AVFilter ff_af_volume = {
     482             :     .name           = "volume",
     483             :     .description    = NULL_IF_CONFIG_SMALL("Change input volume."),
     484             :     .query_formats  = query_formats,
     485             :     .priv_size      = sizeof(VolumeContext),
     486             :     .priv_class     = &volume_class,
     487             :     .init           = init,
     488             :     .uninit         = uninit,
     489             :     .inputs         = avfilter_af_volume_inputs,
     490             :     .outputs        = avfilter_af_volume_outputs,
     491             :     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     492             :     .process_command = process_command,
     493             : };

Generated by: LCOV version 1.12