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

Reply via email to