---
libavfilter/af_volume.c | 74 +++++++++++++++++++++++++++++++++--------------
1 files changed, 52 insertions(+), 22 deletions(-)
diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c
index 230dfd7..7a6cefb 100644
--- a/libavfilter/af_volume.c
+++ b/libavfilter/af_volume.c
@@ -26,6 +26,7 @@
#include "libavutil/audioconvert.h"
#include "libavutil/common.h"
#include "libavutil/eval.h"
+#include "libavutil/float_dsp.h"
#include "libavutil/opt.h"
#include "audio.h"
#include "avfilter.h"
@@ -41,8 +42,9 @@ static const char *precision_str[] = {
"fixed", "float", "double"
};
-typedef struct {
+typedef struct VolumeContext {
const AVClass *class;
+ AVFloatDSPContext fdsp;
char *volume_str;
enum PrecisionType precision;
double volume;
@@ -50,8 +52,11 @@ typedef struct {
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);
+ void (*scale_samples_int)(struct VolumeContext *vol, uint8_t *data,
+ int nb_samples, int volume);
+ void (*scale_samples_dbl)(struct VolumeContext *vol, uint8_t *data,
+ int nb_samples, double volume);
+ int samples_align;
} VolumeContext;
#define OFFSET(x) offsetof(VolumeContext, x)
@@ -188,7 +193,8 @@ static int query_formats(AVFilterContext *ctx)
return 0;
}
-static inline void scale_samples_u8(uint8_t *data, int nb_samples, int volume)
+static inline void scale_samples_u8(VolumeContext *vol, uint8_t *data,
+ int nb_samples, int volume)
{
int i;
uint8_t *smp = data;
@@ -205,7 +211,8 @@ static inline void scale_samples_u8_small(VolumeContext
*vol, uint8_t *data,
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)
+static inline void scale_samples_s16(VolumeContext *vol, uint8_t *data,
+ int nb_samples, int volume)
{
int i;
int16_t *smp = (int16_t *)data;
@@ -222,7 +229,8 @@ static inline void scale_samples_s16_small(VolumeContext
*vol, uint8_t *data,
smp[i] = av_clip_int16((smp[i] * volume + 128) >> 8);
}
-static inline void scale_samples_s32(uint8_t *data, int nb_samples, int volume)
+static inline void scale_samples_s32(VolumeContext *vol, uint8_t *data,
+ int nb_samples, int volume)
{
int i;
int32_t *smp = (int32_t *)data;
@@ -230,18 +238,15 @@ static inline void scale_samples_s32(uint8_t *data, int
nb_samples, int volume)
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)
+static inline void scale_samples_flt(VolumeContext *vol, 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;
+ vol->fdsp.vector_fmul_scalar(smp, smp, volume, nb_samples);
}
-static inline void scale_samples_dbl(uint8_t *data, int nb_samples,
- double volume)
+static inline void scale_samples_dbl(VolumeContext *vol, uint8_t *data,
+ int nb_samples, double volume)
{
int i;
double *smp = (double *)data;
@@ -269,6 +274,8 @@ static void volume_init(VolumeContext *vol, enum
AVSampleFormat sample_fmt)
break;
case AV_SAMPLE_FMT_FLT:
vol->scale_samples_dbl = scale_samples_flt;
+ avpriv_float_dsp_init(&vol->fdsp, 0);
+ vol->samples_align = 4;
break;
case AV_SAMPLE_FMT_DBL:
vol->scale_samples_dbl = scale_samples_dbl;
@@ -285,6 +292,7 @@ static int config_output(AVFilterLink *outlink)
vol->channels = av_get_channel_layout_nb_channels(inlink->channel_layout);
vol->planes = av_sample_fmt_is_planar(inlink->format) ? vol->channels :
1;
+ vol->samples_align = 1;
if (vol->precision != PRECISION_FIXED || vol->volume_i != 256)
volume_init(vol, av_get_packed_sample_fmt(inlink->format));
@@ -296,20 +304,42 @@ static int filter_samples(AVFilterLink *inlink,
AVFilterBufferRef *insamples)
VolumeContext *vol = inlink->dst->priv;
AVFilterLink *outlink = inlink->dst->outputs[0];
int nb_samples = insamples->audio->nb_samples;
- int p;
-
- if (!av_sample_fmt_is_planar(insamples->format))
- nb_samples *= vol->channels;
+ int plane_samples;
+ int p, ret;
+
+ if (av_sample_fmt_is_planar(insamples->format))
+ plane_samples = nb_samples;
+ else
+ plane_samples = nb_samples * vol->channels;
+
+ /* if input buffer doesn't have enough padding for the optimized function,
+ get a new buffer that is large enough */
+ if (insamples->linesize[0] < FFALIGN(plane_samples, vol->samples_align) *
+ av_get_bytes_per_sample(insamples->format)) {
+ AVFilterBufferRef *tmp = ff_get_audio_buffer(outlink, AV_PERM_WRITE,
+ FFALIGN(nb_samples, 4));
+ if (!tmp)
+ return AVERROR(ENOMEM);
+
+ ret = av_samples_copy(tmp->extended_data, insamples->extended_data,
+ 0, 0, nb_samples, vol->channels, inlink->format);
+ if (ret < 0)
+ return ret;
+
+ avfilter_unref_buffer(insamples);
+ insamples = tmp;
+ }
+ plane_samples = FFALIGN(plane_samples, vol->samples_align);
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);
+ vol->scale_samples_int(vol, insamples->extended_data[p],
+ plane_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);
+ vol->scale_samples_dbl(vol, insamples->extended_data[p],
+ plane_samples, vol->volume);
}
}
--
1.7.1
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel