---
libavfilter/af_volume.c | 157 +++++++++++++++++++++++++++++++----------------
1 files changed, 105 insertions(+), 52 deletions(-)
diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c
index 4ce8def..e88d9ca 100644
--- a/libavfilter/af_volume.c
+++ b/libavfilter/af_volume.c
@@ -47,6 +47,11 @@ typedef struct {
enum PrecisionType precision;
double volume;
int volume_i;
+ int channels;
+ int planes;
+
+ void (*scale_samples_int)(uint8_t *data, int nb_samples, int volume);
+ void (*scale_samples_dbl)(uint8_t *data, int nb_samples, double volume);
} VolumeContext;
#define OFFSET(x) offsetof(VolumeContext, x)
@@ -140,22 +145,27 @@ static int query_formats(AVFilterContext *ctx)
VolumeContext *vol = ctx->priv;
AVFilterFormats *formats = NULL;
AVFilterChannelLayouts *layouts;
- enum AVSampleFormat sample_fmts[][4] = {
+ enum AVSampleFormat sample_fmts[][7] = {
/* PRECISION_FIXED */
{
AV_SAMPLE_FMT_U8,
+ AV_SAMPLE_FMT_U8P,
AV_SAMPLE_FMT_S16,
+ AV_SAMPLE_FMT_S16P,
AV_SAMPLE_FMT_S32,
+ AV_SAMPLE_FMT_S32P,
AV_SAMPLE_FMT_NONE
},
/* PRECISION_FLOAT */
{
AV_SAMPLE_FMT_FLT,
+ AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE
},
/* PRECISION_DOUBLE */
{
AV_SAMPLE_FMT_DBL,
+ AV_SAMPLE_FMT_DBLP,
AV_SAMPLE_FMT_NONE
}
};
@@ -178,65 +188,107 @@ static int query_formats(AVFilterContext *ctx)
return 0;
}
+static inline void scale_samples_u8(uint8_t *data, int nb_samples, int volume)
+{
+ int i;
+ uint8_t *smp = data;
+ for (i = 0; i < nb_samples; i++)
+ smp[i] = av_clip_uint8((((smp[i] - 128) * volume + 128) >> 8) + 128);
+}
+
+static inline void scale_samples_s16(uint8_t *data, int nb_samples, int volume)
+{
+ int i;
+ int16_t *smp = (int16_t *)data;
+ for (i = 0; i < nb_samples; i++)
+ smp[i] = av_clip_int16(((int64_t)smp[i] * volume + 128) >> 8);
+}
+
+static inline void scale_samples_s32(uint8_t *data, int nb_samples, int volume)
+{
+ int i;
+ int32_t *smp = (int32_t *)data;
+ for (i = 0; i < nb_samples; i++)
+ smp[i] = av_clipl_int32((((int64_t)smp[i] * volume + 128) >> 8));
+}
+
+static inline void scale_samples_flt(uint8_t *data, int nb_samples,
+ double volume)
+{
+ int i;
+ float vol = volume;
+ float *smp = (float *)data;
+ for (i = 0; i < nb_samples; i++)
+ smp[i] *= vol;
+}
+
+static inline void scale_samples_dbl(uint8_t *data, int nb_samples,
+ double volume)
+{
+ int i;
+ double *smp = (double *)data;
+ for (i = 0; i < nb_samples; i++)
+ smp[i] *= volume;
+}
+
+static void volume_init(VolumeContext *vol, enum AVSampleFormat sample_fmt)
+{
+ switch (sample_fmt) {
+ case AV_SAMPLE_FMT_U8:
+ vol->scale_samples_int = scale_samples_u8;
+ break;
+ case AV_SAMPLE_FMT_S16:
+ vol->scale_samples_int = scale_samples_s16;
+ break;
+ case AV_SAMPLE_FMT_S32:
+ vol->scale_samples_int = scale_samples_s32;
+ break;
+ case AV_SAMPLE_FMT_FLT:
+ vol->scale_samples_dbl = scale_samples_flt;
+ break;
+ case AV_SAMPLE_FMT_DBL:
+ vol->scale_samples_dbl = scale_samples_dbl;
+ break;
+ }
+}
+
+static int config_output(AVFilterLink *outlink)
+{
+ AVFilterContext *ctx = outlink->src;
+ VolumeContext *vol = ctx->priv;
+ AVFilterLink *inlink = ctx->inputs[0];
+
+ vol->channels = av_get_channel_layout_nb_channels(inlink->channel_layout);
+ vol->planes = av_sample_fmt_is_planar(inlink->format) ? vol->channels :
1;
+
+ if (vol->precision != PRECISION_FIXED || vol->volume_i != 256)
+ volume_init(vol, av_get_packed_sample_fmt(inlink->format));
+
+ return 0;
+}
+
static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
{
VolumeContext *vol = inlink->dst->priv;
AVFilterLink *outlink = inlink->dst->outputs[0];
- const int nb_samples = insamples->audio->nb_samples *
- av_get_channel_layout_nb_channels(insamples->audio->channel_layout);
- const double volume = vol->volume;
- const int volume_i = vol->volume_i;
- int i;
+ int nb_samples = insamples->audio->nb_samples;
+ int p;
- if (vol->precision != PRECISION_FIXED || vol->volume_i != 256) {
- switch (insamples->format) {
- case AV_SAMPLE_FMT_U8:
- {
- uint8_t *p = insamples->data[0];
- for (i = 0; i < nb_samples; i++) {
- int v = (((*p - 128) * volume_i + 128) >> 8) + 128;
- *p++ = av_clip_uint8(v);
- }
- break;
- }
- case AV_SAMPLE_FMT_S16:
- {
- int16_t *p = (int16_t *)insamples->data[0];
- for (i = 0; i < nb_samples; i++) {
- int v = ((int64_t)*p * volume_i + 128) >> 8;
- *p++ = av_clip_int16(v);
- }
- break;
- }
- case AV_SAMPLE_FMT_S32:
- {
- int32_t *p = (int32_t *)insamples->data[0];
- for (i = 0; i < nb_samples; i++) {
- int64_t v = (((int64_t)*p * volume_i + 128) >> 8);
- *p++ = av_clipl_int32(v);
- }
- break;
- }
- case AV_SAMPLE_FMT_FLT:
- {
- float *p = (float *)insamples->data[0];
- float scale = (float)volume;
- for (i = 0; i < nb_samples; i++) {
- *p++ *= scale;
- }
- break;
- }
- case AV_SAMPLE_FMT_DBL:
- {
- double *p = (double *)insamples->data[0];
- for (i = 0; i < nb_samples; i++) {
- *p *= volume;
- p++;
- }
- break;
+ if (!av_sample_fmt_is_planar(insamples->format))
+ nb_samples *= vol->channels;
+
+ if (vol->precision == PRECISION_FIXED && vol->scale_samples_int) {
+ for (p = 0; p < vol->planes; p++) {
+ vol->scale_samples_int(insamples->extended_data[p], nb_samples,
+ vol->volume_i);
}
+ } else if (vol->scale_samples_dbl) {
+ for (p = 0; p < vol->planes; p++) {
+ vol->scale_samples_dbl(insamples->extended_data[p], nb_samples,
+ vol->volume);
}
}
+
return ff_filter_samples(outlink, insamples);
}
@@ -254,6 +306,7 @@ static const AVFilterPad avfilter_af_volume_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
+ .config_props = config_output,
},
{ NULL }
};
--
1.7.1
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel