* Audio silence detector
*/
-#include "libavutil/audioconvert.h"
+#include <float.h> /* DBL_MAX */
+
+#include "libavutil/channel_layout.h"
#include "libavutil/opt.h"
#include "libavutil/timestamp.h"
#include "audio.h"
typedef struct {
const AVClass *class;
- char *noise_str; ///< noise option string
double noise; ///< noise amplitude ratio
double duration; ///< minimum duration of silence until notification
int64_t nb_null_samples; ///< current number of continuous zero samples
#define OFFSET(x) offsetof(SilenceDetectContext, x)
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM
static const AVOption silencedetect_options[] = {
- { "n", "set noise tolerance", OFFSET(noise_str), AV_OPT_TYPE_STRING, {.str="-60dB"}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "noise", "set noise tolerance", OFFSET(noise_str), AV_OPT_TYPE_STRING, {.str="-60dB"}, CHAR_MIN, CHAR_MAX, FLAGS },
+ { "n", "set noise tolerance", OFFSET(noise), AV_OPT_TYPE_DOUBLE, {.dbl=0.001}, 0, DBL_MAX, FLAGS },
+ { "noise", "set noise tolerance", OFFSET(noise), AV_OPT_TYPE_DOUBLE, {.dbl=0.001}, 0, DBL_MAX, FLAGS },
{ "d", "set minimum duration in seconds", OFFSET(duration), AV_OPT_TYPE_DOUBLE, {.dbl=2.}, 0, 24*60*60, FLAGS },
{ "duration", "set minimum duration in seconds", OFFSET(duration), AV_OPT_TYPE_DOUBLE, {.dbl=2.}, 0, 24*60*60, FLAGS },
{ NULL },
static av_cold int init(AVFilterContext *ctx, const char *args)
{
int ret;
- char *tail;
SilenceDetectContext *silence = ctx->priv;
silence->class = &silencedetect_class;
if ((ret = av_set_options_string(silence, args, "=", ":")) < 0)
return ret;
- silence->noise = strtod(silence->noise_str, &tail);
- if (!strcmp(tail, "dB")) {
- silence->noise = pow(10, silence->noise/20);
- } else if (*tail) {
- av_log(ctx, AV_LOG_ERROR, "Invalid value '%s' for noise parameter.\n",
- silence->noise_str);
- return AVERROR(EINVAL);
- }
av_opt_free(silence);
return 0;
return e && e->value ? e->value : NULL;
}
-static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *insamples)
{
int i;
SilenceDetectContext *silence = inlink->dst->priv;
}
}
- return ff_filter_samples(inlink->dst->outputs[0], insamples);
+ return ff_filter_frame(inlink->dst->outputs[0], insamples);
}
static int query_formats(AVFilterContext *ctx)
return 0;
}
+static const AVFilterPad silencedetect_inputs[] = {
+ {
+ .name = "default",
+ .type = AVMEDIA_TYPE_AUDIO,
+ .get_audio_buffer = ff_null_get_audio_buffer,
+ .filter_frame = filter_frame,
+ },
+ { NULL }
+};
+
+static const AVFilterPad silencedetect_outputs[] = {
+ {
+ .name = "default",
+ .type = AVMEDIA_TYPE_AUDIO,
+ },
+ { NULL }
+};
+
AVFilter avfilter_af_silencedetect = {
.name = "silencedetect",
.description = NULL_IF_CONFIG_SMALL("Detect silence."),
.priv_size = sizeof(SilenceDetectContext),
.init = init,
.query_formats = query_formats,
-
- .inputs = (const AVFilterPad[]) {
- { .name = "default",
- .type = AVMEDIA_TYPE_AUDIO,
- .get_audio_buffer = ff_null_get_audio_buffer,
- .filter_samples = filter_samples, },
- { .name = NULL }
- },
- .outputs = (const AVFilterPad[]) {
- { .name = "default",
- .type = AVMEDIA_TYPE_AUDIO, },
- { .name = NULL }
- },
- .priv_class = &silencedetect_class,
+ .inputs = silencedetect_inputs,
+ .outputs = silencedetect_outputs,
+ .priv_class = &silencedetect_class,
};