LCOV - code coverage report
Current view: top level - libavfilter - af_silenceremove.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 165 271 60.9 %
Date: 2017-12-15 11:05:35 Functions: 10 12 83.3 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2001 Heikki Leinonen
       3             :  * Copyright (c) 2001 Chris Bagwell
       4             :  * Copyright (c) 2003 Donnie Smith
       5             :  * Copyright (c) 2014 Paul B Mahol
       6             :  *
       7             :  * This file is part of FFmpeg.
       8             :  *
       9             :  * FFmpeg is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public
      11             :  * License as published by the Free Software Foundation; either
      12             :  * version 2.1 of the License, or (at your option) any later version.
      13             :  *
      14             :  * FFmpeg is distributed in the hope that it will be useful,
      15             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public
      20             :  * License along with FFmpeg; if not, write to the Free Software
      21             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      22             :  */
      23             : 
      24             : #include <float.h> /* DBL_MAX */
      25             : 
      26             : #include "libavutil/opt.h"
      27             : #include "libavutil/timestamp.h"
      28             : #include "audio.h"
      29             : #include "formats.h"
      30             : #include "avfilter.h"
      31             : #include "internal.h"
      32             : 
      33             : enum SilenceMode {
      34             :     SILENCE_TRIM,
      35             :     SILENCE_TRIM_FLUSH,
      36             :     SILENCE_COPY,
      37             :     SILENCE_COPY_FLUSH,
      38             :     SILENCE_STOP
      39             : };
      40             : 
      41             : typedef struct SilenceRemoveContext {
      42             :     const AVClass *class;
      43             : 
      44             :     enum SilenceMode mode;
      45             : 
      46             :     int start_periods;
      47             :     int64_t start_duration;
      48             :     double start_threshold;
      49             : 
      50             :     int stop_periods;
      51             :     int64_t stop_duration;
      52             :     double stop_threshold;
      53             : 
      54             :     double *start_holdoff;
      55             :     size_t start_holdoff_offset;
      56             :     size_t start_holdoff_end;
      57             :     int    start_found_periods;
      58             : 
      59             :     double *stop_holdoff;
      60             :     size_t stop_holdoff_offset;
      61             :     size_t stop_holdoff_end;
      62             :     int    stop_found_periods;
      63             : 
      64             :     double window_ratio;
      65             :     double *window;
      66             :     double *window_current;
      67             :     double *window_end;
      68             :     int window_size;
      69             :     double sum;
      70             : 
      71             :     int leave_silence;
      72             :     int restart;
      73             :     int64_t next_pts;
      74             : 
      75             :     int detection;
      76             :     void (*update)(struct SilenceRemoveContext *s, double sample);
      77             :     double(*compute)(struct SilenceRemoveContext *s, double sample);
      78             : } SilenceRemoveContext;
      79             : 
      80             : #define OFFSET(x) offsetof(SilenceRemoveContext, x)
      81             : #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM
      82             : static const AVOption silenceremove_options[] = {
      83             :     { "start_periods",   NULL, OFFSET(start_periods),   AV_OPT_TYPE_INT,      {.i64=0},     0,    9000, FLAGS },
      84             :     { "start_duration",  NULL, OFFSET(start_duration),  AV_OPT_TYPE_DURATION, {.i64=0},     0,    9000, FLAGS },
      85             :     { "start_threshold", NULL, OFFSET(start_threshold), AV_OPT_TYPE_DOUBLE,   {.dbl=0},     0, DBL_MAX, FLAGS },
      86             :     { "stop_periods",    NULL, OFFSET(stop_periods),    AV_OPT_TYPE_INT,      {.i64=0}, -9000,    9000, FLAGS },
      87             :     { "stop_duration",   NULL, OFFSET(stop_duration),   AV_OPT_TYPE_DURATION, {.i64=0},     0,    9000, FLAGS },
      88             :     { "stop_threshold",  NULL, OFFSET(stop_threshold),  AV_OPT_TYPE_DOUBLE,   {.dbl=0},     0, DBL_MAX, FLAGS },
      89             :     { "leave_silence",   NULL, OFFSET(leave_silence),   AV_OPT_TYPE_BOOL,     {.i64=0},     0,       1, FLAGS },
      90             :     { "detection",       NULL, OFFSET(detection),       AV_OPT_TYPE_INT,      {.i64=1},     0,       1, FLAGS, "detection" },
      91             :     {   "peak",          0,    0,                       AV_OPT_TYPE_CONST,    {.i64=0},     0,       0, FLAGS, "detection" },
      92             :     {   "rms",           0,    0,                       AV_OPT_TYPE_CONST,    {.i64=1},     0,       0, FLAGS, "detection" },
      93             :     { "window",          NULL, OFFSET(window_ratio),    AV_OPT_TYPE_DOUBLE,   {.dbl=0.02},  0,      10, FLAGS },
      94             :     { NULL }
      95             : };
      96             : 
      97             : AVFILTER_DEFINE_CLASS(silenceremove);
      98             : 
      99           0 : static double compute_peak(SilenceRemoveContext *s, double sample)
     100             : {
     101             :     double new_sum;
     102             : 
     103           0 :     new_sum  = s->sum;
     104           0 :     new_sum -= *s->window_current;
     105           0 :     new_sum += fabs(sample);
     106             : 
     107           0 :     return new_sum / s->window_size;
     108             : }
     109             : 
     110           0 : static void update_peak(SilenceRemoveContext *s, double sample)
     111             : {
     112           0 :     s->sum -= *s->window_current;
     113           0 :     *s->window_current = fabs(sample);
     114           0 :     s->sum += *s->window_current;
     115             : 
     116           0 :     s->window_current++;
     117           0 :     if (s->window_current >= s->window_end)
     118           0 :         s->window_current = s->window;
     119           0 : }
     120             : 
     121        1364 : static double compute_rms(SilenceRemoveContext *s, double sample)
     122             : {
     123             :     double new_sum;
     124             : 
     125        1364 :     new_sum  = s->sum;
     126        1364 :     new_sum -= *s->window_current;
     127        1364 :     new_sum += sample * sample;
     128             : 
     129        1364 :     return sqrt(new_sum / s->window_size);
     130             : }
     131             : 
     132        1364 : static void update_rms(SilenceRemoveContext *s, double sample)
     133             : {
     134        1364 :     s->sum -= *s->window_current;
     135        1364 :     *s->window_current = sample * sample;
     136        1364 :     s->sum += *s->window_current;
     137             : 
     138        1364 :     s->window_current++;
     139        1364 :     if (s->window_current >= s->window_end)
     140           0 :         s->window_current = s->window;
     141        1364 : }
     142             : 
     143           1 : static av_cold int init(AVFilterContext *ctx)
     144             : {
     145           1 :     SilenceRemoveContext *s = ctx->priv;
     146             : 
     147           1 :     if (s->stop_periods < 0) {
     148           1 :         s->stop_periods = -s->stop_periods;
     149           1 :         s->restart = 1;
     150             :     }
     151             : 
     152           1 :     switch (s->detection) {
     153           0 :     case 0:
     154           0 :         s->update = update_peak;
     155           0 :         s->compute = compute_peak;
     156           0 :         break;
     157           1 :     case 1:
     158           1 :         s->update = update_rms;
     159           1 :         s->compute = compute_rms;
     160           1 :         break;
     161             :     };
     162             : 
     163           1 :     return 0;
     164             : }
     165             : 
     166         342 : static void clear_window(SilenceRemoveContext *s)
     167             : {
     168         342 :     memset(s->window, 0, s->window_size * sizeof(*s->window));
     169             : 
     170         342 :     s->window_current = s->window;
     171         342 :     s->window_end = s->window + s->window_size;
     172         342 :     s->sum = 0;
     173         342 : }
     174             : 
     175           1 : static int config_input(AVFilterLink *inlink)
     176             : {
     177           1 :     AVFilterContext *ctx = inlink->dst;
     178           1 :     SilenceRemoveContext *s = ctx->priv;
     179             : 
     180           1 :     s->window_size = FFMAX((inlink->sample_rate * s->window_ratio), 1) * inlink->channels;
     181           1 :     s->window = av_malloc_array(s->window_size, sizeof(*s->window));
     182           1 :     if (!s->window)
     183           0 :         return AVERROR(ENOMEM);
     184             : 
     185           1 :     clear_window(s);
     186             : 
     187           1 :     s->start_duration = av_rescale(s->start_duration, inlink->sample_rate,
     188             :                                    AV_TIME_BASE);
     189           1 :     if (s->start_duration < 0) {
     190           0 :         av_log(ctx, AV_LOG_WARNING, "start duration must be non-negative\n");
     191           0 :         s->start_duration = -s->start_duration;
     192             :     }
     193             : 
     194           1 :     s->stop_duration  = av_rescale(s->stop_duration, inlink->sample_rate,
     195             :                                    AV_TIME_BASE);
     196           1 :     if (s->stop_duration < 0) {
     197           0 :         av_log(ctx, AV_LOG_WARNING, "stop duration must be non-negative\n");
     198           0 :         s->stop_duration = -s->stop_duration;
     199             :     }
     200             : 
     201           1 :     s->start_holdoff = av_malloc_array(FFMAX(s->start_duration, 1),
     202             :                                        sizeof(*s->start_holdoff) *
     203           1 :                                        inlink->channels);
     204           1 :     if (!s->start_holdoff)
     205           0 :         return AVERROR(ENOMEM);
     206             : 
     207           1 :     s->start_holdoff_offset = 0;
     208           1 :     s->start_holdoff_end    = 0;
     209           1 :     s->start_found_periods  = 0;
     210             : 
     211           1 :     s->stop_holdoff = av_malloc_array(FFMAX(s->stop_duration, 1),
     212             :                                       sizeof(*s->stop_holdoff) *
     213           1 :                                       inlink->channels);
     214           1 :     if (!s->stop_holdoff)
     215           0 :         return AVERROR(ENOMEM);
     216             : 
     217           1 :     s->stop_holdoff_offset = 0;
     218           1 :     s->stop_holdoff_end    = 0;
     219           1 :     s->stop_found_periods  = 0;
     220             : 
     221           1 :     if (s->start_periods)
     222           0 :         s->mode = SILENCE_TRIM;
     223             :     else
     224           1 :         s->mode = SILENCE_COPY;
     225             : 
     226           1 :     return 0;
     227             : }
     228             : 
     229         341 : static void flush(SilenceRemoveContext *s,
     230             :                   AVFrame *out, AVFilterLink *outlink,
     231             :                   int *nb_samples_written, int *ret)
     232             : {
     233         341 :     if (*nb_samples_written) {
     234           0 :         out->nb_samples = *nb_samples_written / outlink->channels;
     235             : 
     236           0 :         out->pts = s->next_pts;
     237           0 :         s->next_pts += av_rescale_q(out->nb_samples,
     238           0 :                                     (AVRational){1, outlink->sample_rate},
     239             :                                     outlink->time_base);
     240             : 
     241           0 :         *ret = ff_filter_frame(outlink, out);
     242           0 :         *nb_samples_written = 0;
     243             :     } else {
     244         341 :         av_frame_free(&out);
     245             :     }
     246         341 : }
     247             : 
     248           1 : static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     249             : {
     250           1 :     AVFilterContext *ctx = inlink->dst;
     251           1 :     AVFilterLink *outlink = ctx->outputs[0];
     252           1 :     SilenceRemoveContext *s = ctx->priv;
     253           1 :     int i, j, threshold, ret = 0;
     254             :     int nbs, nb_samples_read, nb_samples_written;
     255           1 :     double *obuf, *ibuf = (double *)in->data[0];
     256             :     AVFrame *out;
     257             : 
     258           1 :     nb_samples_read = nb_samples_written = 0;
     259             : 
     260           1 :     switch (s->mode) {
     261             :     case SILENCE_TRIM:
     262         341 : silence_trim:
     263         341 :         nbs = in->nb_samples - nb_samples_read / inlink->channels;
     264         341 :         if (!nbs)
     265           0 :             break;
     266             : 
     267         341 :         for (i = 0; i < nbs; i++) {
     268         341 :             threshold = 0;
     269        1023 :             for (j = 0; j < inlink->channels; j++) {
     270         682 :                 threshold |= s->compute(s, ibuf[j]) > s->start_threshold;
     271             :             }
     272             : 
     273         341 :             if (threshold) {
     274        1023 :                 for (j = 0; j < inlink->channels; j++) {
     275         682 :                     s->update(s, *ibuf);
     276         682 :                     s->start_holdoff[s->start_holdoff_end++] = *ibuf++;
     277             :                 }
     278         341 :                 nb_samples_read += inlink->channels;
     279             : 
     280         341 :                 if (s->start_holdoff_end >= s->start_duration * inlink->channels) {
     281         341 :                     if (++s->start_found_periods >= s->start_periods) {
     282         341 :                         s->mode = SILENCE_TRIM_FLUSH;
     283         341 :                         goto silence_trim_flush;
     284             :                     }
     285             : 
     286           0 :                     s->start_holdoff_offset = 0;
     287           0 :                     s->start_holdoff_end = 0;
     288             :                 }
     289             :             } else {
     290           0 :                 s->start_holdoff_end = 0;
     291             : 
     292           0 :                 for (j = 0; j < inlink->channels; j++)
     293           0 :                     s->update(s, ibuf[j]);
     294             : 
     295           0 :                 ibuf += inlink->channels;
     296           0 :                 nb_samples_read += inlink->channels;
     297             :             }
     298             :         }
     299           0 :         break;
     300             : 
     301             :     case SILENCE_TRIM_FLUSH:
     302         341 : silence_trim_flush:
     303         341 :         nbs  = s->start_holdoff_end - s->start_holdoff_offset;
     304         341 :         nbs -= nbs % inlink->channels;
     305         341 :         if (!nbs)
     306           0 :             break;
     307             : 
     308         341 :         out = ff_get_audio_buffer(inlink, nbs / inlink->channels);
     309         341 :         if (!out) {
     310           0 :             av_frame_free(&in);
     311           0 :             return AVERROR(ENOMEM);
     312             :         }
     313             : 
     314         341 :         memcpy(out->data[0], &s->start_holdoff[s->start_holdoff_offset],
     315             :                nbs * sizeof(double));
     316             : 
     317         341 :         out->pts = s->next_pts;
     318         341 :         s->next_pts += av_rescale_q(out->nb_samples,
     319         341 :                                     (AVRational){1, outlink->sample_rate},
     320             :                                     outlink->time_base);
     321             : 
     322         341 :         s->start_holdoff_offset += nbs;
     323             : 
     324         341 :         ret = ff_filter_frame(outlink, out);
     325             : 
     326         341 :         if (s->start_holdoff_offset == s->start_holdoff_end) {
     327         341 :             s->start_holdoff_offset = 0;
     328         341 :             s->start_holdoff_end = 0;
     329         341 :             s->mode = SILENCE_COPY;
     330         341 :             goto silence_copy;
     331             :         }
     332           0 :         break;
     333             : 
     334             :     case SILENCE_COPY:
     335         342 : silence_copy:
     336         342 :         nbs = in->nb_samples - nb_samples_read / inlink->channels;
     337         342 :         if (!nbs)
     338           1 :             break;
     339             : 
     340         341 :         out = ff_get_audio_buffer(inlink, nbs);
     341         341 :         if (!out) {
     342           0 :             av_frame_free(&in);
     343           0 :             return AVERROR(ENOMEM);
     344             :         }
     345         341 :         obuf = (double *)out->data[0];
     346             : 
     347         341 :         if (s->stop_periods) {
     348         341 :             for (i = 0; i < nbs; i++) {
     349         341 :                 threshold = 1;
     350        1023 :                 for (j = 0; j < inlink->channels; j++)
     351         682 :                     threshold &= s->compute(s, ibuf[j]) > s->stop_threshold;
     352             : 
     353         341 :                 if (threshold && s->stop_holdoff_end && !s->leave_silence) {
     354           0 :                     s->mode = SILENCE_COPY_FLUSH;
     355           0 :                     flush(s, out, outlink, &nb_samples_written, &ret);
     356           0 :                     goto silence_copy_flush;
     357         341 :                 } else if (threshold) {
     358           0 :                     for (j = 0; j < inlink->channels; j++) {
     359           0 :                         s->update(s, *ibuf);
     360           0 :                         *obuf++ = *ibuf++;
     361             :                     }
     362           0 :                     nb_samples_read    += inlink->channels;
     363           0 :                     nb_samples_written += inlink->channels;
     364         341 :                 } else if (!threshold) {
     365        1023 :                     for (j = 0; j < inlink->channels; j++) {
     366         682 :                         s->update(s, *ibuf);
     367         682 :                         if (s->leave_silence) {
     368           0 :                             *obuf++ = *ibuf;
     369           0 :                             nb_samples_written++;
     370             :                         }
     371             : 
     372         682 :                         s->stop_holdoff[s->stop_holdoff_end++] = *ibuf++;
     373             :                     }
     374         341 :                     nb_samples_read += inlink->channels;
     375             : 
     376         341 :                     if (s->stop_holdoff_end >= s->stop_duration * inlink->channels) {
     377         341 :                         if (++s->stop_found_periods >= s->stop_periods) {
     378         341 :                             s->stop_holdoff_offset = 0;
     379         341 :                             s->stop_holdoff_end = 0;
     380             : 
     381         341 :                             if (!s->restart) {
     382           0 :                                 s->mode = SILENCE_STOP;
     383           0 :                                 flush(s, out, outlink, &nb_samples_written, &ret);
     384           0 :                                 goto silence_stop;
     385             :                             } else {
     386         341 :                                 s->stop_found_periods = 0;
     387         341 :                                 s->start_found_periods = 0;
     388         341 :                                 s->start_holdoff_offset = 0;
     389         341 :                                 s->start_holdoff_end = 0;
     390         341 :                                 clear_window(s);
     391         341 :                                 s->mode = SILENCE_TRIM;
     392         341 :                                 flush(s, out, outlink, &nb_samples_written, &ret);
     393         341 :                                 goto silence_trim;
     394             :                             }
     395             :                         }
     396           0 :                         s->mode = SILENCE_COPY_FLUSH;
     397           0 :                         flush(s, out, outlink, &nb_samples_written, &ret);
     398           0 :                         goto silence_copy_flush;
     399             :                     }
     400             :                 }
     401             :             }
     402           0 :             flush(s, out, outlink, &nb_samples_written, &ret);
     403             :         } else {
     404           0 :             memcpy(obuf, ibuf, sizeof(double) * nbs * inlink->channels);
     405             : 
     406           0 :             out->pts = s->next_pts;
     407           0 :             s->next_pts += av_rescale_q(out->nb_samples,
     408           0 :                                         (AVRational){1, outlink->sample_rate},
     409             :                                         outlink->time_base);
     410             : 
     411           0 :             ret = ff_filter_frame(outlink, out);
     412             :         }
     413           0 :         break;
     414             : 
     415             :     case SILENCE_COPY_FLUSH:
     416           0 : silence_copy_flush:
     417           0 :         nbs  = s->stop_holdoff_end - s->stop_holdoff_offset;
     418           0 :         nbs -= nbs % inlink->channels;
     419           0 :         if (!nbs)
     420           0 :             break;
     421             : 
     422           0 :         out = ff_get_audio_buffer(inlink, nbs / inlink->channels);
     423           0 :         if (!out) {
     424           0 :             av_frame_free(&in);
     425           0 :             return AVERROR(ENOMEM);
     426             :         }
     427             : 
     428           0 :         memcpy(out->data[0], &s->stop_holdoff[s->stop_holdoff_offset],
     429             :                nbs * sizeof(double));
     430           0 :         s->stop_holdoff_offset += nbs;
     431             : 
     432           0 :         out->pts = s->next_pts;
     433           0 :         s->next_pts += av_rescale_q(out->nb_samples,
     434           0 :                                     (AVRational){1, outlink->sample_rate},
     435             :                                     outlink->time_base);
     436             : 
     437           0 :         ret = ff_filter_frame(outlink, out);
     438             : 
     439           0 :         if (s->stop_holdoff_offset == s->stop_holdoff_end) {
     440           0 :             s->stop_holdoff_offset = 0;
     441           0 :             s->stop_holdoff_end = 0;
     442           0 :             s->mode = SILENCE_COPY;
     443           0 :             goto silence_copy;
     444             :         }
     445           0 :         break;
     446             :     case SILENCE_STOP:
     447           0 : silence_stop:
     448           0 :         break;
     449             :     }
     450             : 
     451           1 :     av_frame_free(&in);
     452             : 
     453           1 :     return ret;
     454             : }
     455             : 
     456           1 : static int request_frame(AVFilterLink *outlink)
     457             : {
     458           1 :     AVFilterContext *ctx = outlink->src;
     459           1 :     SilenceRemoveContext *s = ctx->priv;
     460             :     int ret;
     461             : 
     462           1 :     ret = ff_request_frame(ctx->inputs[0]);
     463           2 :     if (ret == AVERROR_EOF && (s->mode == SILENCE_COPY_FLUSH ||
     464           1 :                                s->mode == SILENCE_COPY)) {
     465           1 :         int nbs = s->stop_holdoff_end - s->stop_holdoff_offset;
     466           1 :         if (nbs) {
     467             :             AVFrame *frame;
     468             : 
     469           0 :             frame = ff_get_audio_buffer(outlink, nbs / outlink->channels);
     470           0 :             if (!frame)
     471           0 :                 return AVERROR(ENOMEM);
     472             : 
     473           0 :             memcpy(frame->data[0], &s->stop_holdoff[s->stop_holdoff_offset],
     474             :                    nbs * sizeof(double));
     475             : 
     476           0 :             frame->pts = s->next_pts;
     477           0 :             s->next_pts += av_rescale_q(frame->nb_samples,
     478           0 :                                         (AVRational){1, outlink->sample_rate},
     479             :                                         outlink->time_base);
     480             : 
     481           0 :             ret = ff_filter_frame(outlink, frame);
     482             :         }
     483           1 :         s->mode = SILENCE_STOP;
     484             :     }
     485           1 :     return ret;
     486             : }
     487             : 
     488           1 : static int query_formats(AVFilterContext *ctx)
     489             : {
     490           1 :     AVFilterFormats *formats = NULL;
     491           1 :     AVFilterChannelLayouts *layouts = NULL;
     492             :     static const enum AVSampleFormat sample_fmts[] = {
     493             :         AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_NONE
     494             :     };
     495             :     int ret;
     496             : 
     497           1 :     layouts = ff_all_channel_counts();
     498           1 :     if (!layouts)
     499           0 :         return AVERROR(ENOMEM);
     500           1 :     ret = ff_set_common_channel_layouts(ctx, layouts);
     501           1 :     if (ret < 0)
     502           0 :         return ret;
     503             : 
     504           1 :     formats = ff_make_format_list(sample_fmts);
     505           1 :     if (!formats)
     506           0 :         return AVERROR(ENOMEM);
     507           1 :     ret = ff_set_common_formats(ctx, formats);
     508           1 :     if (ret < 0)
     509           0 :         return ret;
     510             : 
     511           1 :     formats = ff_all_samplerates();
     512           1 :     if (!formats)
     513           0 :         return AVERROR(ENOMEM);
     514           1 :     return ff_set_common_samplerates(ctx, formats);
     515             : }
     516             : 
     517           1 : static av_cold void uninit(AVFilterContext *ctx)
     518             : {
     519           1 :     SilenceRemoveContext *s = ctx->priv;
     520             : 
     521           1 :     av_freep(&s->start_holdoff);
     522           1 :     av_freep(&s->stop_holdoff);
     523           1 :     av_freep(&s->window);
     524           1 : }
     525             : 
     526             : static const AVFilterPad silenceremove_inputs[] = {
     527             :     {
     528             :         .name         = "default",
     529             :         .type         = AVMEDIA_TYPE_AUDIO,
     530             :         .config_props = config_input,
     531             :         .filter_frame = filter_frame,
     532             :     },
     533             :     { NULL }
     534             : };
     535             : 
     536             : static const AVFilterPad silenceremove_outputs[] = {
     537             :     {
     538             :         .name          = "default",
     539             :         .type          = AVMEDIA_TYPE_AUDIO,
     540             :         .request_frame = request_frame,
     541             :     },
     542             :     { NULL }
     543             : };
     544             : 
     545             : AVFilter ff_af_silenceremove = {
     546             :     .name          = "silenceremove",
     547             :     .description   = NULL_IF_CONFIG_SMALL("Remove silence."),
     548             :     .priv_size     = sizeof(SilenceRemoveContext),
     549             :     .priv_class    = &silenceremove_class,
     550             :     .init          = init,
     551             :     .uninit        = uninit,
     552             :     .query_formats = query_formats,
     553             :     .inputs        = silenceremove_inputs,
     554             :     .outputs       = silenceremove_outputs,
     555             : };

Generated by: LCOV version 1.13