[FFmpeg-devel] [PATCH] audio conversion clipping/overflows

Ronald S. Bultje rsbultje
Sat Mar 27 17:19:56 CET 2010


Hi,

On Tue, Mar 16, 2010 at 12:02 PM, Michael Niedermayer <michaelni at gmx.at> wrote:
> On Tue, Mar 16, 2010 at 11:35:27AM -0400, Ronald S. Bultje wrote:
>> Fixed in attached. Output is same. I'm still not sure if the
>> interleaving-loops or history-related memcpy()s can be prevented, but
>> am open to suggestions on how to achieve the same result without
>> memcpy()s/loops.
>
> AVFrame get_buffer/release_buffer like we do for video can surely prevent
> the copies in severak ways.
> return pointer to internal buffer or require get_buffer to allocate suffiient
> space prior to [0]

Yeah, I think this is a bad idea so (as you might've noticed from my
patches) I'm trying to change this for the better and directly write
into the output buffer.

My only problem case right now is atrac1 and wmaprodec, which do
in-place interleaving. I'm not qualified to improve that, someone with
actual DSP knowledge should do that.

Rest is now simpler (assuming all patches are accepted), see attached.

Ronald
-------------- next part --------------
Index: ffmpeg-svn/libavcodec/audioconvert.c
===================================================================
--- ffmpeg-svn.orig/libavcodec/audioconvert.c	2010-03-27 10:48:32.000000000 -0400
+++ ffmpeg-svn/libavcodec/audioconvert.c	2010-03-27 12:08:33.000000000 -0400
@@ -226,14 +226,20 @@
         else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_S32,  *(const int32_t*)pi)
         else CONV(SAMPLE_FMT_FLT, float  , SAMPLE_FMT_S32,  *(const int32_t*)pi*(1.0 / (1<<31)))
         else CONV(SAMPLE_FMT_DBL, double , SAMPLE_FMT_S32,  *(const int32_t*)pi*(1.0 / (1<<31)))
-        else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_FLT, lrintf(*(const float*)pi * (1<<7)) + 0x80)
-        else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_FLT, lrintf(*(const float*)pi * (1<<15)))
-        else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_FLT, lrintf(*(const float*)pi * (1<<31)))
+        else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_FLT,
+                  av_clip_uint8(lrintf(*(const float*)pi * (1<<7)) + 0x80))
+        else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_FLT,
+                  av_clip_int16(lrintf(*(const float*)pi * (1<<15))))
+        else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_FLT,
+                  av_clipl_int32(llrintf(*(const float*)pi * (1<<31))))
         else CONV(SAMPLE_FMT_FLT, float  , SAMPLE_FMT_FLT, *(const float*)pi)
         else CONV(SAMPLE_FMT_DBL, double , SAMPLE_FMT_FLT, *(const float*)pi)
-        else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_DBL, lrint(*(const double*)pi * (1<<7)) + 0x80)
-        else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_DBL, lrint(*(const double*)pi * (1<<15)))
-        else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_DBL, lrint(*(const double*)pi * (1<<31)))
+        else CONV(SAMPLE_FMT_U8 , uint8_t, SAMPLE_FMT_DBL,
+                  av_clip_uint8(lrint(*(const double*)pi * (1<<7)) + 0x80))
+        else CONV(SAMPLE_FMT_S16, int16_t, SAMPLE_FMT_DBL,
+                  av_clip_int16(lrint(*(const double*)pi * (1<<15))))
+        else CONV(SAMPLE_FMT_S32, int32_t, SAMPLE_FMT_DBL,
+                  av_clipl_int32(llrint(*(const double*)pi * (1<<31))))
         else CONV(SAMPLE_FMT_FLT, float  , SAMPLE_FMT_DBL, *(const double*)pi)
         else CONV(SAMPLE_FMT_DBL, double , SAMPLE_FMT_DBL, *(const double*)pi)
         else return -1;
Index: ffmpeg-svn/libavutil/common.h
===================================================================
--- ffmpeg-svn.orig/libavutil/common.h	2010-03-27 10:48:32.000000000 -0400
+++ ffmpeg-svn/libavutil/common.h	2010-03-27 12:08:33.000000000 -0400
@@ -145,6 +145,17 @@
 }
 
 /**
+ * Clips a signed 64-bit integer value into the -2147483648,2147483647 range.
+ * @param a value to clip
+ * @return clipped value
+ */
+static inline av_const int32_t av_clipl_int32(int64_t a)
+{
+    if ((a+2147483648) & ~2147483647) return (a>>63) ^ 2147483647;
+    else                              return a;
+}
+
+/**
  * Clips a float value into the amin-amax range.
  * @param a value to clip
  * @param amin minimum value of the clip range
Index: ffmpeg-svn/libavcodec/amrnbdec.c
===================================================================
--- ffmpeg-svn.orig/libavcodec/amrnbdec.c	2010-03-27 11:48:37.000000000 -0400
+++ ffmpeg-svn/libavcodec/amrnbdec.c	2010-03-27 12:08:33.000000000 -0400
@@ -796,7 +796,7 @@
                      float fixed_gain, const float *fixed_vector,
                      float *samples, uint8_t overflow)
 {
-    int i, overflow_temp = 0;
+    int i;
     float excitation[AMR_SUBFRAME_SIZE];
 
     // if an overflow has been detected, the pitch vector is scaled down by a
@@ -831,12 +831,10 @@
     // detect overflow
     for (i = 0; i < AMR_SUBFRAME_SIZE; i++)
         if (fabsf(samples[i]) > AMR_SAMPLE_BOUND) {
-            overflow_temp = 1;
-            samples[i] = av_clipf(samples[i], -AMR_SAMPLE_BOUND,
-                                               AMR_SAMPLE_BOUND);
+            return 1;
         }
 
-    return overflow_temp;
+    return 0;
 }
 
 /// @}
@@ -1048,10 +1046,6 @@
                                              highpass_poles, highpass_gain,
                                              p->high_pass_mem, AMR_BLOCK_SIZE);
 
-    for (i = 0; i < AMR_BLOCK_SIZE; i++)
-        buf_out[i] = av_clipf(buf_out[i] * AMR_SAMPLE_SCALE,
-                              -1.0, 32767.0 / 32768.0);
-
     /* Update averaged lsf vector (used for fixed gain smoothing).
      *
      * Note that lsf_avg should not incorporate the current frame's LSFs
Index: ffmpeg-svn/libavcodec/qcelpdata.h
===================================================================
--- ffmpeg-svn.orig/libavcodec/qcelpdata.h	2010-03-27 10:48:32.000000000 -0400
+++ ffmpeg-svn/libavcodec/qcelpdata.h	2010-03-27 12:08:33.000000000 -0400
@@ -425,16 +425,6 @@
 #define QCELP_SCALE 8192.
 
 /**
- * the upper boundary of the clipping, depends on QCELP_SCALE
- */
-#define QCELP_CLIP_UPPER_BOUND (8191.75/8192.)
-
-/**
- * the lower boundary of the clipping, depends on QCELP_SCALE
- */
-#define QCELP_CLIP_LOWER_BOUND -1.
-
-/**
  * table for computing Ga (decoded linear codebook gain magnitude)
  *
  * @note The table could fit in int16_t in x*8 form, but it seems
Index: ffmpeg-svn/libavcodec/ra288.c
===================================================================
--- ffmpeg-svn.orig/libavcodec/ra288.c	2010-03-27 10:48:32.000000000 -0400
+++ ffmpeg-svn/libavcodec/ra288.c	2010-03-27 12:08:33.000000000 -0400
@@ -102,10 +102,6 @@
     gain_block[9] = 10 * log10(sum) - 32;
 
     ff_celp_lp_synthesis_filterf(block, ractx->sp_lpc, buffer, 5, 36);
-
-    /* output */
-    for (i=0; i < 5; i++)
-        block[i] = av_clipf(block[i], -4095./4096., 4095./4096.);
 }
 
 /**
Index: ffmpeg-svn/libavcodec/sipr.c
===================================================================
--- ffmpeg-svn.orig/libavcodec/sipr.c	2010-03-27 11:49:10.000000000 -0400
+++ ffmpeg-svn/libavcodec/sipr.c	2010-03-27 12:08:33.000000000 -0400
@@ -496,9 +496,6 @@
                                              0.939805806,
                                              ctx->highpass_filt_mem,
                                              frame_size);
-
-    ctx->dsp.vector_clipf(out_data, out_data, -1, 32767./(1<<15), frame_size);
-
 }
 
 static av_cold int sipr_decoder_init(AVCodecContext * avctx)
Index: ffmpeg-svn/libavcodec/twinvq.c
===================================================================
--- ffmpeg-svn.orig/libavcodec/twinvq.c	2010-03-27 10:48:32.000000000 -0400
+++ ffmpeg-svn/libavcodec/twinvq.c	2010-03-27 12:08:33.000000000 -0400
@@ -850,9 +850,6 @@
         return buf_size;
     }
 
-    tctx->dsp.vector_clipf(out, out, -32700./(1<<15), 32700./(1<<15),
-                           avctx->channels * mtab->size);
-
     *data_size = mtab->size*avctx->channels*4;
 
     return buf_size;
Index: ffmpeg-svn/libavcodec/wmaprodec.c
===================================================================
--- ffmpeg-svn.orig/libavcodec/wmaprodec.c	2010-03-27 12:08:19.000000000 -0400
+++ ffmpeg-svn/libavcodec/wmaprodec.c	2010-03-27 12:08:33.000000000 -0400
@@ -1348,7 +1348,7 @@
         int incr = s->num_channels;
 
         while (iptr < iend) {
-            *ptr = av_clipf(*iptr++, -1.0, 32767.0 / 32768.0);
+            *ptr = *iptr++;
             ptr += incr;
         }
 
Index: ffmpeg-svn/libavcodec/atrac1.c
===================================================================
--- ffmpeg-svn.orig/libavcodec/atrac1.c	2010-03-27 10:48:32.000000000 -0400
+++ ffmpeg-svn/libavcodec/atrac1.c	2010-03-27 12:08:33.000000000 -0400
@@ -305,20 +305,15 @@
         at1_subband_synthesis(q, su, q->out_samples[ch]);
     }
 
-    /* round, convert to 16bit and interleave */
+    /* interleave */
     if (q->channels == 1) {
         /* mono */
-        q->dsp.vector_clipf(samples, q->out_samples[0], -32700.0 / (1 << 15),
-                            32700.0 / (1 << 15), AT1_SU_SAMPLES);
+        memcpy(samples, q->out_samples[0], AT1_SU_SAMPLES * 4);
     } else {
         /* stereo */
         for (i = 0; i < AT1_SU_SAMPLES; i++) {
-            samples[i * 2]     = av_clipf(q->out_samples[0][i],
-                                          -32700.0 / (1 << 15),
-                                           32700.0 / (1 << 15));
-            samples[i * 2 + 1] = av_clipf(q->out_samples[1][i],
-                                          -32700.0 / (1 << 15),
-                                           32700.0 / (1 << 15));
+            samples[i * 2]     = q->out_samples[0][i];
+            samples[i * 2 + 1] = q->out_samples[1][i];
         }
     }
 
Index: ffmpeg-svn/libavcodec/qcelpdec.c
===================================================================
--- ffmpeg-svn.orig/libavcodec/qcelpdec.c	2010-03-27 12:08:16.000000000 -0400
+++ ffmpeg-svn/libavcodec/qcelpdec.c	2010-03-27 12:08:33.000000000 -0400
@@ -838,10 +838,6 @@
     // postfilter, as per TIA/EIA/IS-733 2.4.8.6
     postfilter(q, outbuffer, lpc);
 
-    for(i=0; i<160; i++)
-        outbuffer[i] = av_clipf(outbuffer[i], QCELP_CLIP_LOWER_BOUND,
-                                QCELP_CLIP_UPPER_BOUND);
-
     memcpy(q->prev_lspf, quantized_lspf, sizeof(q->prev_lspf));
     q->prev_bitrate = q->bitrate;
 
Index: ffmpeg-svn/libavcodec/wmavoice.c
===================================================================
--- ffmpeg-svn.orig/libavcodec/wmavoice.c	2010-03-27 10:48:32.000000000 -0400
+++ ffmpeg-svn/libavcodec/wmavoice.c	2010-03-27 12:08:33.000000000 -0400
@@ -1117,8 +1117,7 @@
         av_log_missing_feature(ctx, "APF", 0);
         s->do_apf = 0;
     } //else
-        for (n = 0; n < 160; n++)
-            samples[n] = av_clipf(synth[n], -1.0, 1.0);
+        memcpy(samples, synth, 160 * sizeof(synth[0]));
 
     /* Cache values for next frame */
     s->frame_cntr++;
Index: ffmpeg-svn/libavcodec/sipr16k.c
===================================================================
--- ffmpeg-svn.orig/libavcodec/sipr16k.c	2010-03-27 11:54:12.000000000 -0400
+++ ffmpeg-svn/libavcodec/sipr16k.c	2010-03-27 12:08:33.000000000 -0400
@@ -264,9 +264,6 @@
     postfilter(out_data, synth, ctx->iir_mem, ctx->filt_mem, ctx->mem_preemph);
 
     memcpy(ctx->iir_mem, Az[1], LP_FILTER_ORDER_16k * sizeof(float));
-
-    ctx->dsp.vector_clipf(out_data, out_data, -1, 32767./(1<<15), frame_size);
-
 }
 
 void ff_sipr_init_16k(SiprContext *ctx)



More information about the ffmpeg-devel mailing list