summaryrefslogtreecommitdiff
authorPaul B Mahol <onemda@gmail.com>2013-10-04 17:57:15 (GMT)
committer Paul B Mahol <onemda@gmail.com>2013-10-05 11:59:34 (GMT)
commit9665217a75d92dd4c3a1ad82cf0394bb673797cf (patch)
treefc4329a513d8478b66418fdf0efd0be8394ce96e
parent922596e3dac8a9a8ed6a6738c7085e70dfef8ff3 (diff)
downloadffmpeg-9665217a75d92dd4c3a1ad82cf0394bb673797cf.zip
ffmpeg-9665217a75d92dd4c3a1ad82cf0394bb673797cf.tar.gz
ffmpeg-9665217a75d92dd4c3a1ad82cf0394bb673797cf.tar.bz2
avfilter/af_silencedetect: support more sample formats
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Diffstat
-rw-r--r--libavfilter/af_silencedetect.c114
1 files changed, 81 insertions, 33 deletions
diff --git a/libavfilter/af_silencedetect.c b/libavfilter/af_silencedetect.c
index a9b9358..5dbb964 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 {
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,78 @@ 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);
+ 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) \
+{ \
+ const type *p = (const 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)
+
+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;
+ case AV_SAMPLE_FMT_S16:
+ s->noise *= INT16_MAX;
+ s->silencedetect = silencedetect_s16;
+ break;
+ }
+
+ 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 +146,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);
return ff_filter_frame(inlink->dst->outputs[0], insamples);
}
@@ -115,6 +159,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 +187,7 @@ static const AVFilterPad silencedetect_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
+ .config_props = config_input,
.filter_frame = filter_frame,
},
{ NULL }