---
This is an updated patch which removes some unrelated hunks and also makes it
easier to add block switching support to the ac3_fixed encoder once we have
a fixed-point iir filter.

Still depends on the channel coupling patch.

 doc/encoders.texi         |    7 +
 libavcodec/ac3enc.c       |  297 +++++++++++++++++++++++++++++++++++++++++++-
 libavcodec/ac3enc_fixed.c |    4 +-
 libavcodec/ac3enc_float.c |   24 +++-
 libavcodec/iirfilter.c    |    6 +
 libavcodec/iirfilter.h    |   10 ++
 6 files changed, 336 insertions(+), 12 deletions(-)

diff --git a/doc/encoders.texi b/doc/encoders.texi
index 3f6b4c9..aa3871a 100644
--- a/doc/encoders.texi
+++ b/doc/encoders.texi
@@ -357,6 +357,13 @@ HDCD A/D Converter
 
 @table @option
 
+@item -block_switching @var{boolean}
+Block Switching. Enables/Disables switching from long blocks to short blocks
+based on transient detection. This allows the encoder to determine when it is
+best to use short blocks for transient signals. This option is enabled by
+default, and it is recommended that it be left as enabled except for testing
+purposes or to increase encoding speed.
+
 @item -stereo_rematrixing @var{boolean}
 Stereo Rematrixing. Enables/Disables use of rematrixing for stereo input. This
 is an optional AC-3 feature that increases quality by selectively encoding
diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c
index f09fdf6..c65d74b 100644
--- a/libavcodec/ac3enc.c
+++ b/libavcodec/ac3enc.c
@@ -42,6 +42,7 @@
 #include "ac3.h"
 #include "audioconvert.h"
 #include "fft.h"
+#include "iirfilter.h"
 
 
 #ifndef CONFIG_AC3ENC_FLOAT
@@ -66,7 +67,9 @@ typedef int64_t CoefSumType;
 
 typedef struct AC3MDCTContext {
     const SampleType *window;           ///< MDCT window function
-    FFTContext fft;                     ///< FFT context for MDCT calculation
+    SampleType *rot_tmp;                ///< temp buffer for pre-rotated samples
+    CoefType   *coef_tmp;               ///< temp buffer for 256-point MDCT coefs
+    FFTContext fft[2];                  ///< FFT context for MDCT calculation
 } AC3MDCTContext;
 
 /**
@@ -97,6 +100,7 @@ typedef struct AC3EncOptions {
 
     /* other encoding options */
     int allow_per_frame_metadata;
+    int block_switching;
     int stereo_rematrixing;
     int channel_coupling;
     int cpl_start;
@@ -117,6 +121,7 @@ typedef struct AC3Block {
     uint16_t **qmant;                           ///< quantized mantissas
     uint8_t  **cpl_coord_exp;                   ///< coupling coord exponents           (cplcoexp)
     uint8_t  **cpl_coord_mant;                  ///< coupling coord mantissas           (cplcomant)
+    uint8_t  blk_switch[AC3_MAX_CHANNELS][2];   ///< block switch flags [0]=current [1]=previous
     uint8_t  coeff_shift[AC3_MAX_CHANNELS];     ///< fixed-point coefficient shift values
     uint8_t  new_rematrixing_strategy;          ///< send new rematrixing flags in this block
     int      num_rematrixing_bands;             ///< number of rematrixing bands
@@ -180,6 +185,11 @@ typedef struct AC3EncodeContext {
     int start_freq[AC3_MAX_CHANNELS];       ///< start frequency bin                    (strtmant)
     int cpl_end_freq;                       ///< coupling channel end frequency bin
 
+    int blksw_enabled;                      ///< block switching enabled
+    struct FFIIRFilterCoeffs *blksw_coefs;  ///< block switch filter coefficients
+    struct FFIIRFilterState *blksw_state[2][AC3_MAX_CHANNELS]; /// block switch filter states
+    struct FFIIRFilterState *temp_state;    ///< block switch filter temp state
+
     int cpl_on;                             ///< coupling turned on for this frame
     int cpl_enabled;                        ///< coupling enabled for all frames
     int num_cpl_subbands;                   ///< number of coupling subbands            (ncplsubnd)
@@ -202,6 +212,7 @@ typedef struct AC3EncodeContext {
     int exponent_bits;                      ///< number of bits used for exponents
 
     SampleType **planar_samples;
+    SampleType *filtered_samples;
     uint8_t *bap_buffer;
     uint8_t *bap1_buffer;
     CoefType *mdct_coef_buffer;
@@ -286,6 +297,7 @@ static const AVOption options[] = {
     {"standard", "Standard (default)", 0, FF_OPT_TYPE_CONST, 0, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"},
     {"hdcd",     "HDCD",               0, FF_OPT_TYPE_CONST, 1, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"},
 /* Other Encoding Options */
+{"block_switching", "Block Switching", OFFSET(block_switching), FF_OPT_TYPE_INT, 1, 0, 1, AC3ENC_PARAM},
 {"stereo_rematrixing", "Stereo Rematrixing", OFFSET(stereo_rematrixing), FF_OPT_TYPE_INT, 1, 0, 1, AC3ENC_PARAM},
 {"channel_coupling",   "Channel Coupling",   OFFSET(channel_coupling),   FF_OPT_TYPE_INT, 1, 0, 1, AC3ENC_PARAM, "channel_coupling"},
     {"auto", "Selected by the Encoder", 0, FF_OPT_TYPE_CONST, -1, INT_MIN, INT_MAX, AC3ENC_PARAM, "channel_coupling"},
@@ -471,6 +483,237 @@ static void deinterleave_input_samples(AC3EncodeContext *s,
 
 
 /**
+ * Uninitialize block switching.
+ */
+static av_cold void block_switch_end(AC3EncodeContext *s)
+{
+/* block switching is not done for the fixed-point encoder because we do not
+   currently have a fixed-point IIR filter */
+#if CONFIG_AC3ENC_FLOAT
+    int ch;
+    ff_iir_filter_free_coeffs(s->blksw_coefs);
+    ff_iir_filter_free_state(s->temp_state);
+    for (ch = 0; ch < s->fbw_channels; ch++) {
+        ff_iir_filter_free_state(s->blksw_state[0][ch]);
+        ff_iir_filter_free_state(s->blksw_state[1][ch]);
+    }
+#endif
+}
+
+
+/**
+ * Initialize block switching.
+ */
+static av_cold int block_switch_init(AVCodecContext *avctx, AC3EncodeContext *s)
+{
+/* block switching is not done for the fixed-point encoder because we do not
+   currently have a fixed-point IIR filter */
+#if CONFIG_AC3ENC_FLOAT
+    int ch;
+
+    /* initialize high-pass filter with cutoff of 8kHz */
+    s->blksw_coefs = ff_iir_filter_init_coeffs(avctx, FF_FILTER_TYPE_BIQUAD,
+                                               FF_FILTER_MODE_HIGHPASS, 2,
+                                               2.0 * 8000.0 / s->sample_rate,
+                                               0, 0);
+
+    if (!s->blksw_coefs)
+        return -1;
+
+    s->temp_state = ff_iir_filter_init_state(2);
+    if (!s->temp_state) {
+        block_switch_end(s);
+        return AVERROR(ENOMEM);
+    }
+    for (ch = 0; ch < s->fbw_channels; ch++) {
+        s->blksw_state[0][ch] = ff_iir_filter_init_state(2);
+        s->blksw_state[1][ch] = ff_iir_filter_init_state(2);
+        if (!s->blksw_state[0][ch] || !s->blksw_state[1][ch]) {
+            block_switch_end(s);
+            return AVERROR(ENOMEM);
+        }
+    }
+#endif
+
+    return 0;
+}
+
+
+/**
+ * Find the maximum magnitude in an array of samples.
+ */
+static float sample_absmax(const SampleType *src, int n)
+{
+    SampleType max = 0;
+    n--;
+    while (n >= 0) {
+        SampleType v = FFABS(src[n]);
+        if (v > max)
+            max = v;
+        n--;
+    }
+    return max;
+}
+
+
+/**
+ * Build tree of peak magnitudes for each segment in 3 levels of time division.
+ * level 1 = 256 samples x 1
+ * level 2 = 128 samples x 2
+ * level 3 =  64 samples x 4
+ */
+static inline void build_peak_tree(const SampleType *src,
+                                   SampleType peak_tree[10])
+{
+    /* level 3 peak values */
+    peak_tree[6] = sample_absmax(src      , 64);
+    peak_tree[7] = sample_absmax(src +  64, 64);
+    peak_tree[8] = sample_absmax(src + 128, 64);
+    peak_tree[9] = sample_absmax(src + 192, 64);
+    /* level 2 peak values */
+    peak_tree[4] = FFMAX(peak_tree[8], peak_tree[9]);
+    peak_tree[3] = FFMAX(peak_tree[6], peak_tree[7]);
+    /* level 1 peak value */
+    peak_tree[1] = FFMAX(peak_tree[3], peak_tree[4]);
+}
+
+
+/**
+ * Saves last segment of each level for comparison with the first segment in
+ * each level in the next block.
+ */
+static inline void save_peak_tree(SampleType peak_tree[10])
+{
+    peak_tree[5] = peak_tree[9];
+    peak_tree[2] = peak_tree[4];
+    peak_tree[0] = peak_tree[1];
+}
+
+
+#if CONFIG_AC3ENC_FLOAT
+#define SILENCE_THRESHOLD  0.0030517578125f
+#define LVL1_THRESHOLD     0.100f
+#define LVL2_THRESHOLD     0.075f
+#define LVL3_THRESHOLD     0.050f
+#else
+#define SILENCE_THRESHOLD  100
+#define LVL1_THRESHOLD     3277
+#define LVL2_THRESHOLD     2458
+#define LVL3_THRESHOLD     1638
+#endif
+
+/**
+ * Detect transients to determine block switching flags.
+ */
+static void block_switch_detection(AC3EncodeContext *s)
+{
+    int ch, blk;
+    int av_unused(i);
+    const SampleType *input_samples;
+    SampleType peak_tree[10] = {0,};
+
+    /* block switching is not done for the fixed-point encoder because we do
+       not currently have a fixed-point IIR filter */
+    av_assert0(CONFIG_AC3ENC_FLOAT);
+
+    for (ch = 0; ch < s->fbw_channels; ch++) {
+        /* filter input samples, cascaded biquad high-pass @ 8kHz */
+        input_samples  = s->planar_samples[ch];
+#if CONFIG_AC3ENC_FLOAT
+        for (i = 0; i < 2; i++) {
+            SampleType *output_samples = s->filtered_samples;
+
+            ff_iir_filter_flt(s->blksw_coefs, s->blksw_state[i][ch], AC3_FRAME_SIZE,
+                              input_samples, 1, output_samples, 1);
+            input_samples  += AC3_FRAME_SIZE;
+            output_samples += AC3_FRAME_SIZE;
+            ff_iir_filter_copy_state(s->temp_state, s->blksw_state[i][ch], 2);
+            ff_iir_filter_flt(s->blksw_coefs, s->temp_state, AC3_BLOCK_SIZE,
+                              input_samples, 1, output_samples, 1);
+
+            input_samples = s->filtered_samples;
+        }
+#endif
+
+        /* first half of first block */
+        build_peak_tree(input_samples, peak_tree);
+        save_peak_tree(peak_tree);
+        input_samples += AC3_BLOCK_SIZE;
+
+        /* second half of each block */
+        for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+            AC3Block *block = &s->blocks[blk];
+
+            /* set current block flag */
+            build_peak_tree(input_samples, peak_tree);
+            block->blk_switch[ch][0] = 0;
+            if (peak_tree[1] > SILENCE_THRESHOLD &&
+                   (((peak_tree[1] * LVL1_THRESHOLD) > peak_tree[0]) ||
+                    ((peak_tree[3] * LVL2_THRESHOLD) > peak_tree[2]) ||
+                    ((peak_tree[4] * LVL2_THRESHOLD) > peak_tree[3]) ||
+                    ((peak_tree[6] * LVL3_THRESHOLD) > peak_tree[5]) ||
+                    ((peak_tree[7] * LVL3_THRESHOLD) > peak_tree[6]) ||
+                    ((peak_tree[8] * LVL3_THRESHOLD) > peak_tree[7]) ||
+                    ((peak_tree[9] * LVL3_THRESHOLD) > peak_tree[8]))) {
+                block->blk_switch[ch][0] = 1;
+            }
+            save_peak_tree(peak_tree);
+
+            /* set previous block flag */
+            block->blk_switch[ch][1] = 0;
+            if (!blk)
+                block->blk_switch[ch][1] = s->blocks[5].blk_switch[ch][0];
+            else
+                block->blk_switch[ch][1] = s->blocks[blk-1].blk_switch[ch][0];
+
+            input_samples += AC3_BLOCK_SIZE;
+        }
+    }
+}
+
+
+/**
+ * Calculate two 256-point MDCTs
+ * @param out 256 output frequency coefficients
+ * @param in  512 windowed input audio samples
+ */
+static void mdct256(AC3MDCTContext *mdct, CoefType *out, const SampleType *in)
+{
+/* block switching is not done for the fixed-point encoder because we do not
+   currently have a fixed-point IIR filter */
+#if CONFIG_AC3ENC_FLOAT
+    CoefType *coef_a = mdct->coef_tmp;
+    CoefType *coef_b = mdct->coef_tmp + 128;
+    SampleType *rot  = mdct->rot_tmp;
+    int i;
+
+    /* part 1 pre-rotation (-N/4) */
+    memcpy(rot, in+64, 192 * sizeof(*in));
+    for (i = 0; i < 64; i++)
+        rot[i+192] = -in[i];
+
+    /* part 1 MDCT */
+    mdct->fft[1].mdct_calcw(&mdct->fft[1], coef_a, rot);
+
+    /* part 2 pre-rotation (N/4) */
+    in += 256;
+    for (i = 0; i < 64; i++)
+        rot[i] = -in[i+192];
+    memcpy(rot+64, in, 192 * sizeof(*in));
+
+    /* part 2 MDCT */
+    mdct->fft[1].mdct_calcw(&mdct->fft[1], coef_b, rot);
+
+    /* coefficient interleaving */
+    for (i = 0; i < 128; i++) {
+        out[2*i  ] = coef_a[i];
+        out[2*i+1] = coef_b[i];
+    }
+#endif
+}
+
+
+/**
  * Apply the MDCT to input samples to generate frequency coefficients.
  * This applies the KBD window and normalizes the input to reduce precision
  * loss due to fixed-point calculations.
@@ -488,8 +731,13 @@ static void apply_mdct(AC3EncodeContext *s)
 
             block->coeff_shift[ch+1] = normalize_samples(s);
 
-            s->mdct.fft.mdct_calcw(&s->mdct.fft, block->mdct_coef[ch+1],
-                                   s->windowed_samples);
+            if (block->blk_switch[ch][0]) {
+                mdct256(&s->mdct, block->mdct_coef[ch+1], s->windowed_samples);
+            } else {
+                s->mdct.fft[0].mdct_calcw(&s->mdct.fft[0],
+                                          block->mdct_coef[ch+1],
+                                          s->windowed_samples);
+            }
         }
     }
 }
@@ -504,7 +752,8 @@ static void compute_coupling_strategy(AC3EncodeContext *s)
     for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
         AC3Block *block = &s->blocks[blk];
         for (ch = 1; ch <= s->fbw_channels; ch++)
-            block->channel_in_cpl[ch] = s->cpl_on;
+            block->channel_in_cpl[ch] = s->cpl_on &&
+                !(block->blk_switch[ch-1][0] || block->blk_switch[ch-1][1]);
     }
 
     /* enable coupling for each block if at least 2 channels have coupling
@@ -628,6 +877,11 @@ static void apply_channel_coupling(AC3EncodeContext *s)
                 new_coords = 1;
                 last_coord_blk = blk;
             }
+            /* for stereo, encode coordinates more often */
+            if (s->fbw_channels == 2 && blk > 2 && last_coord_blk < (blk-2)) {
+                new_coords = 1;
+                last_coord_blk = blk;
+            }
         }
         s->blocks[blk].new_cpl_coords = new_coords;
     }
@@ -892,6 +1146,8 @@ static void compute_exp_strategy(AC3EncodeContext *s)
                 exp_strategy[blk] = EXP_NEW;
             else if (ch > CPL_CH && exp_diff > EXP_DIFF_THRESHOLD)
                 exp_strategy[blk] = EXP_NEW;
+            if (ch > CPL_CH && s->blocks[blk].blk_switch[ch-1][0] || s->blocks[blk].blk_switch[ch-1][1])
+                exp_strategy[blk] = EXP_NEW;
         }
 
         /* now select the encoding strategy type : if exponents are often
@@ -901,12 +1157,16 @@ static void compute_exp_strategy(AC3EncodeContext *s)
             blk1 = blk + 1;
             while (blk1 < AC3_MAX_BLOCKS && exp_strategy[blk1] == EXP_REUSE)
                 blk1++;
+            if (ch > CPL_CH && s->blocks[blk].blk_switch[ch-1][0] || s->blocks[blk].blk_switch[ch-1][1]) {
+                exp_strategy[blk] = EXP_D45;
+            } else {
             switch (blk1 - blk) {
             case 1:  exp_strategy[blk] = EXP_D45; break;
             case 2:
             case 3:  exp_strategy[blk] = EXP_D25; break;
             default: exp_strategy[blk] = EXP_D15; break;
             }
+            }
             blk = blk1;
         }
     }
@@ -1752,11 +2012,14 @@ static void output_audio_block(AC3EncodeContext *s, int blk)
 
     /* block switching */
     for (ch = 0; ch < s->fbw_channels; ch++)
-        put_bits(&s->pb, 1, 0);
+        put_bits(&s->pb, 1, block->blk_switch[ch][0]);
 
     /* dither flags */
-    for (ch = 0; ch < s->fbw_channels; ch++)
-        put_bits(&s->pb, 1, 1);
+    for (ch = 0; ch < s->fbw_channels; ch++) {
+        /* disable zero-bit dithering for each short block and the next block */
+        int dith_flag = !(block->blk_switch[ch][0] || block->blk_switch[ch][1]);
+        put_bits(&s->pb, 1, dith_flag);
+    }
 
     /* dynamic range codes */
     put_bits(&s->pb, 1, 0);
@@ -2281,6 +2544,9 @@ static int ac3_encode_frame(AVCodecContext *avctx, unsigned char *frame,
 
     deinterleave_input_samples(s, samples);
 
+    if (s->blksw_enabled)
+        block_switch_detection(s);
+
     apply_mdct(s);
 
     s->cpl_on = s->cpl_enabled;
@@ -2324,6 +2590,7 @@ static av_cold int ac3_encode_close(AVCodecContext *avctx)
     for (ch = 0; ch < s->channels; ch++)
         av_freep(&s->planar_samples[ch]);
     av_freep(&s->planar_samples);
+    av_freep(&s->filtered_samples);
     av_freep(&s->bap_buffer);
     av_freep(&s->bap1_buffer);
     av_freep(&s->mdct_coef_buffer);
@@ -2349,6 +2616,8 @@ static av_cold int ac3_encode_close(AVCodecContext *avctx)
 
     mdct_end(&s->mdct);
 
+    block_switch_end(s);
+
     av_freep(&avctx->coded_frame);
     return 0;
 }
@@ -2471,6 +2740,8 @@ static av_cold int validate_options(AVCodecContext *avctx, AC3EncodeContext *s)
     if (ret)
         return ret;
 
+    s->blksw_enabled = s->options.block_switching && CONFIG_AC3ENC_FLOAT;
+
     s->rematrixing_enabled = s->options.stereo_rematrixing &&
                              (s->channel_mode == AC3_CHMODE_STEREO);
 
@@ -2591,6 +2862,14 @@ static av_cold int allocate_buffers(AVCodecContext *avctx)
         FF_ALLOC_OR_GOTO(avctx, s->cpl_coord_mant_buffer, AC3_MAX_BLOCKS * channels *
                          16 * sizeof(*s->cpl_coord_mant_buffer), alloc_fail);
     }
+    if (s->blksw_enabled) {
+        /* block switching is not done for the fixed-point encoder because we
+           do not currently have a fixed-point IIR filter */
+        av_assert0(CONFIG_AC3ENC_FLOAT);
+        FF_ALLOCZ_OR_GOTO(avctx, s->filtered_samples,
+                          (AC3_FRAME_SIZE+AC3_BLOCK_SIZE) *
+                          sizeof(*s->filtered_samples), alloc_fail);
+    }
     for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
         AC3Block *block = &s->blocks[blk];
         FF_ALLOC_OR_GOTO(avctx, block->bap, channels * sizeof(*block->bap),
@@ -2696,6 +2975,10 @@ static av_cold int ac3_encode_init(AVCodecContext *avctx)
 
     set_bandwidth(s);
 
+    ret = block_switch_init(avctx, s);
+    if (ret)
+        goto init_fail;
+
     exponent_init(s);
 
     bit_alloc_init(s);
diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c
index ff24f8d..6a9cd7f 100644
--- a/libavcodec/ac3enc_fixed.c
+++ b/libavcodec/ac3enc_fixed.c
@@ -36,7 +36,7 @@
  */
 static av_cold void mdct_end(AC3MDCTContext *mdct)
 {
-    ff_fft_end(&mdct->fft);
+    ff_fft_end(&mdct->fft[0]);
 }
 
 
@@ -47,7 +47,7 @@ static av_cold void mdct_end(AC3MDCTContext *mdct)
 static av_cold int mdct_init(AVCodecContext *avctx, AC3MDCTContext *mdct,
                              int nbits)
 {
-    int ret = ff_mdct_init(&mdct->fft, nbits, 0, 1.0);
+    int ret = ff_mdct_init(&mdct->fft[0], nbits, 0, 1.0);
     mdct->window = ff_ac3_window;
     return ret;
 }
diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c
index 3a438c2..717750d 100644
--- a/libavcodec/ac3enc_float.c
+++ b/libavcodec/ac3enc_float.c
@@ -36,7 +36,10 @@
  */
 static av_cold void mdct_end(AC3MDCTContext *mdct)
 {
-    ff_mdct_end(&mdct->fft);
+    av_freep(&mdct->rot_tmp);
+    av_freep(&mdct->coef_tmp);
+    ff_mdct_end(&mdct->fft[0]);
+    ff_mdct_end(&mdct->fft[1]);
     av_freep(&mdct->window);
 }
 
@@ -49,7 +52,7 @@ static av_cold int mdct_init(AVCodecContext *avctx, AC3MDCTContext *mdct,
                              int nbits)
 {
     float *window;
-    int i, n, n2;
+    int i, n, n2, ret;
 
     n  = 1 << nbits;
     n2 = n >> 1;
@@ -64,7 +67,22 @@ static av_cold int mdct_init(AVCodecContext *avctx, AC3MDCTContext *mdct,
         window[n-1-i] = window[i];
     mdct->window = window;
 
-    return ff_mdct_init(&mdct->fft, nbits, 0, -2.0 / n);
+    FF_ALLOC_OR_GOTO(avctx, mdct->rot_tmp,  n2 * sizeof(*mdct->rot_tmp),
+                     mdct_alloc_fail);
+    FF_ALLOC_OR_GOTO(avctx, mdct->coef_tmp, n2 * sizeof(*mdct->coef_tmp),
+                     mdct_alloc_fail);
+
+    ret = ff_mdct_init(&mdct->fft[0], nbits,   0, -2.0 / n) ||
+          ff_mdct_init(&mdct->fft[1], nbits-1, 0, -2.0 / n2);
+    if (ret) {
+        mdct_end(mdct);
+        return ret;
+    }
+
+    return 0;
+mdct_alloc_fail:
+    mdct_end(mdct);
+    return AVERROR(ENOMEM);
 }
 
 
diff --git a/libavcodec/iirfilter.c b/libavcodec/iirfilter.c
index 56d17d2..2d12551 100644
--- a/libavcodec/iirfilter.c
+++ b/libavcodec/iirfilter.c
@@ -205,6 +205,12 @@ av_cold struct FFIIRFilterState* ff_iir_filter_init_state(int order)
     return s;
 }
 
+void ff_iir_filter_copy_state(struct FFIIRFilterState *dst,
+                              struct FFIIRFilterState *src, int order)
+{
+    memcpy(dst, src, sizeof(FFIIRFilterState) + sizeof(src->x[0]) * (order - 1));
+}
+
 #define CONV_S16(dest, source) dest = av_clip_int16(lrintf(source));
 
 #define CONV_FLT(dest, source) dest = source;
diff --git a/libavcodec/iirfilter.h b/libavcodec/iirfilter.h
index bc65a96..5ead44a 100644
--- a/libavcodec/iirfilter.h
+++ b/libavcodec/iirfilter.h
@@ -77,6 +77,16 @@ struct FFIIRFilterCoeffs* ff_iir_filter_init_coeffs(void *avc,
 struct FFIIRFilterState* ff_iir_filter_init_state(int order);
 
 /**
+ * Copy filter state.
+ *
+ * @param dst   destination state
+ * @param src   source state
+ * @param order filter order
+ */
+void ff_iir_filter_copy_state(struct FFIIRFilterState *dst,
+                              struct FFIIRFilterState *src, int order);
+
+/**
  * Free filter coefficients.
  *
  * @param coeffs pointer allocated with ff_iir_filter_init_coeffs()
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to