This imposes a global maximum volume scale of 8388607 to keep
volume_i <= INT_MAX. Also, different functions are used depending on the
scale in order to avoid doing 64-bit multiplication when possible.
---
 libavfilter/af_volume.c |   32 ++++++++++++++++++++++++++++----
 1 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c
index e88d9ca..230dfd7 100644
--- a/libavfilter/af_volume.c
+++ b/libavfilter/af_volume.c
@@ -114,7 +114,7 @@ static av_cold int init(AVFilterContext *ctx, const char 
*args)
             goto init_end;
         }
 
-        if (d < 0 || d > 65536) { /* 65536 = INT_MIN / (128 * 256) */
+        if (d < 0 || d > 8388607) { /* INT_MAX / 256 */
             av_log(ctx, AV_LOG_ERROR,
                    "Negative or too big volume value %f\n", d);
             ret = AVERROR(EINVAL);
@@ -193,6 +193,15 @@ 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(((((int64_t)smp[i] - 128) * volume + 128) >> 8) 
+ 128);
+}
+
+static inline void scale_samples_u8_small(VolumeContext *vol, 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);
 }
 
@@ -204,6 +213,15 @@ static inline void scale_samples_s16(uint8_t *data, int 
nb_samples, int volume)
         smp[i] = av_clip_int16(((int64_t)smp[i] * volume + 128) >> 8);
 }
 
+static inline void scale_samples_s16_small(VolumeContext *vol, 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((smp[i] * volume + 128) >> 8);
+}
+
 static inline void scale_samples_s32(uint8_t *data, int nb_samples, int volume)
 {
     int i;
@@ -233,12 +251,18 @@ static inline void scale_samples_dbl(uint8_t *data, int 
nb_samples,
 
 static void volume_init(VolumeContext *vol, enum AVSampleFormat sample_fmt)
 {
-    switch (sample_fmt) {
+    switch (av_get_packed_sample_fmt(sample_fmt)) {
     case AV_SAMPLE_FMT_U8:
-        vol->scale_samples_int = scale_samples_u8;
+        if (vol->volume_i < 16777216)
+            vol->scale_samples_int = scale_samples_u8_small;
+        else
+            vol->scale_samples_int = scale_samples_u8;
         break;
     case AV_SAMPLE_FMT_S16:
-        vol->scale_samples_int = scale_samples_s16;
+        if (vol->volume_i < 65536)
+            vol->scale_samples_int = scale_samples_s16_small;
+        else
+            vol->scale_samples_int = scale_samples_s16;
         break;
     case AV_SAMPLE_FMT_S32:
         vol->scale_samples_int = scale_samples_s32;
-- 
1.7.1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to