[FFmpeg-devel] [PATCH] avfilter/af_silencedetect: support more sample formats

Paul B Mahol onemda at gmail.com
Fri Oct 4 20:34:24 CEST 2013


On 10/4/13, Clement Boesch <u at pkh.me> wrote:
> Thanks for this patch.
>
> On Fri, Oct 04, 2013 at 06:00:33PM +0000, Paul B Mahol wrote:
>> Signed-off-by: Paul B Mahol <onemda at gmail.com>
>> ---
>>  libavfilter/af_silencedetect.c | 112
>> +++++++++++++++++++++++++++++------------
>>  1 file changed, 79 insertions(+), 33 deletions(-)
>>
>> diff --git a/libavfilter/af_silencedetect.c
>> b/libavfilter/af_silencedetect.c
>> index a9b9358..a510912 100644
>> --- a/libavfilter/af_silencedetect.c
>> +++ b/libavfilter/af_silencedetect.c
>> @@ -32,13 +32,17 @@
>>  #include "avfilter.h"
>>  #include "internal.h"
>>
>> -typedef struct {
>> +typedef struct SilenceDetectContext {
>
> Unrelated, and I don't like it, so please drop.

I need this, otherwise I get warnings.

>
>>      const AVClass *class;
>>      double noise;               ///< noise amplitude ratio
>>      double duration;            ///< minimum duration of silence until
>> notification
>>      int64_t nb_null_samples;    ///< current number of continuous zero
>> samples
>>      int64_t start;              ///< if silence is detected, this value
>> contains the time of the first zero sample
>>      int last_sample_rate;       ///< last sample rate to check for sample
>> rate changes
>> +
>> +    void (*silencedetect)(struct SilenceDetectContext *s, AVFrame
>> *insamples,
>> +                          int nb_samples, int64_t nb_samples_notify,
>> +                          AVRational time_base);
>>  } SilenceDetectContext;
>>
>>  #define OFFSET(x) offsetof(SilenceDetectContext, x)
>> @@ -59,9 +63,76 @@ static char *get_metadata_val(AVFrame *insamples, const
>> char *key)
>>      return e && e->value ? e->value : NULL;
>>  }
>>
>> +static av_always_inline void update(SilenceDetectContext *s, AVFrame
>> *insamples,
>> +                                    int is_silence, int64_t
>> nb_samples_notify,
>> +                                    AVRational time_base)
>> +{
>> +    if (is_silence) {
>> +        if (!s->start) {
>> +            s->nb_null_samples++;
>> +            if (s->nb_null_samples >= nb_samples_notify) {
>> +                s->start = insamples->pts - (int64_t)(s->duration /
>> av_q2d(time_base) + .5);
>
>> +                av_dict_set(&insamples->metadata, "lavfi.silence_start",
>> +                        av_ts2timestr(s->start, &time_base), 0);
>
> setlocal cinoptions=(0
>
> same several times below

Done.

>
>> +                av_log(s, AV_LOG_INFO, "silence_start: %s\n",
>> +                        get_metadata_val(insamples,
>> "lavfi.silence_start"));
>> +            }
>> +        }
>> +    } else {
>> +        if (s->start) {
>> +            av_dict_set(&insamples->metadata, "lavfi.silence_end",
>> +                    av_ts2timestr(insamples->pts, &time_base), 0);
>> +            av_dict_set(&insamples->metadata, "lavfi.silence_duration",
>> +                    av_ts2timestr(insamples->pts - s->start, &time_base),
>> 0);
>> +            av_log(s, AV_LOG_INFO,
>> +                    "silence_end: %s | silence_duration: %s\n",
>> +                    get_metadata_val(insamples, "lavfi.silence_end"),
>> +                    get_metadata_val(insamples,
>> "lavfi.silence_duration"));
>> +        }
>> +        s->nb_null_samples = s->start = 0;
>> +    }
>> +}
>> +
>> +#define SILENCE_DETECT(name, type)
>>        \
>> +static void silencedetect_##name(SilenceDetectContext *s, AVFrame
>> *insamples,    \
>> +                                 int nb_samples, int64_t
>> nb_samples_notify,      \
>> +                                 AVRational time_base)
>>        \
>> +{
>>        \
>> +    type *p = (type *)insamples->data[0];
>>        \
>> +    const type noise = s->noise;
>>        \
>> +    int i;
>>        \
>> +
>>        \
>> +    for (i = 0; i < nb_samples; i++, p++)
>>        \
>> +        update(s, insamples, *p < noise && *p > -noise,
>>        \
>> +               nb_samples_notify, time_base);
>>        \
>> +}
>> +
>
>> +SILENCE_DETECT(dbl, double);
>> +SILENCE_DETECT(flt, float);
>> +SILENCE_DETECT(s32, int32_t);
>> +SILENCE_DETECT(s16, int16_t);
>
> you can/should drop the trailing ;

Done.

>
>> +
>> +static int config_input(AVFilterLink *inlink)
>> +{
>> +    AVFilterContext *ctx = inlink->dst;
>> +    SilenceDetectContext *s = ctx->priv;
>> +
>> +    switch (inlink->format) {
>> +    case AV_SAMPLE_FMT_DBL: s->silencedetect = silencedetect_dbl; break;
>> +    case AV_SAMPLE_FMT_FLT: s->silencedetect = silencedetect_flt; break;
>> +    case AV_SAMPLE_FMT_S32:
>> +        s->noise *= INT32_MAX;
>> +        s->silencedetect = silencedetect_s32; break;
>
> please move the break below

Done.

>
>> +    case AV_SAMPLE_FMT_S16:
>> +        s->noise *= INT16_MAX;
>> +        s->silencedetect = silencedetect_s16; break;
>
>
>> +    };
>
> trailing ;

Done.

>
>> +
>> +    return 0;
>> +}
>> +
>>  static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
>>  {
>> -    int i;
>>      SilenceDetectContext *s         = inlink->dst->priv;
>>      const int nb_channels           = inlink->channels;
>>      const int srate                 = inlink->sample_rate;
>> @@ -73,38 +144,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
>> *insamples)
>>          s->nb_null_samples = srate * s->nb_null_samples /
>> s->last_sample_rate;
>>      s->last_sample_rate = srate;
>>
>> -    // TODO: support more sample formats
>>      // TODO: document metadata
>> -    if (insamples->format == AV_SAMPLE_FMT_DBL) {
>> -        double *p = (double *)insamples->data[0];
>> -
>> -        for (i = 0; i < nb_samples; i++, p++) {
>> -            if (*p < s->noise && *p > -s->noise) {
>> -                if (!s->start) {
>> -                    s->nb_null_samples++;
>> -                    if (s->nb_null_samples >= nb_samples_notify) {
>> -                        s->start = insamples->pts - (int64_t)(s->duration
>> / av_q2d(inlink->time_base) + .5);
>> -                        av_dict_set(&insamples->metadata,
>> "lavfi.silence_start",
>> -                                    av_ts2timestr(s->start,
>> &inlink->time_base), 0);
>> -                        av_log(s, AV_LOG_INFO, "silence_start: %s\n",
>> -                               get_metadata_val(insamples,
>> "lavfi.silence_start"));
>> -                    }
>> -                }
>> -            } else {
>> -                if (s->start) {
>> -                    av_dict_set(&insamples->metadata,
>> "lavfi.silence_end",
>> -                                av_ts2timestr(insamples->pts,
>> &inlink->time_base), 0);
>> -                    av_dict_set(&insamples->metadata,
>> "lavfi.silence_duration",
>> -                                av_ts2timestr(insamples->pts - s->start,
>> &inlink->time_base), 0);
>> -                    av_log(s, AV_LOG_INFO,
>> -                           "silence_end: %s | silence_duration: %s\n",
>> -                           get_metadata_val(insamples,
>> "lavfi.silence_end"),
>> -                           get_metadata_val(insamples,
>> "lavfi.silence_duration"));
>> -                }
>> -                s->nb_null_samples = s->start = 0;
>> -            }
>> -        }
>> -    }
>
>> +    s->silencedetect(s, insamples, nb_samples, nb_samples_notify,
>> +                          inlink->time_base);
>
> align

Done.

>
>>
>>      return ff_filter_frame(inlink->dst->outputs[0], insamples);
>>  }
>> @@ -115,6 +157,9 @@ static int query_formats(AVFilterContext *ctx)
>>      AVFilterChannelLayouts *layouts = NULL;
>>      static const enum AVSampleFormat sample_fmts[] = {
>>          AV_SAMPLE_FMT_DBL,
>> +        AV_SAMPLE_FMT_FLT,
>> +        AV_SAMPLE_FMT_S32,
>> +        AV_SAMPLE_FMT_S16,
>>          AV_SAMPLE_FMT_NONE
>>      };
>>
>> @@ -140,6 +185,7 @@ static const AVFilterPad silencedetect_inputs[] = {
>>      {
>>          .name         = "default",
>>          .type         = AVMEDIA_TYPE_AUDIO,
>> +        .config_props = config_input,
>>          .filter_frame = filter_frame,
>>      },
>>      { NULL }
>
> It looks fine; I'm assuming you tried with the FATE sample and compared
> the results.

Fate sample use float amd with this one fate passed.

>
> --
> Clement B.
>


More information about the ffmpeg-devel mailing list