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

Clément Bœsch u at pkh.me
Fri Oct 4 20:11:15 CEST 2013


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.

>      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

> +                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 ;

> +
> +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

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


> +    };

trailing ;

> +
> +    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

>  
>      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.

-- 
Clément B.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20131004/93de8c6a/attachment.asc>


More information about the ffmpeg-devel mailing list