avcodec/dolby_e: use av_clip_uintp2()
[ffmpeg.git] / libavcodec / ac3enc_template.c
index 943a55a..be65987 100644 (file)
@@ -4,20 +4,20 @@
  * Copyright (c) 2006-2011 Justin Ruggles <justin.ruggles@gmail.com>
  * Copyright (c) 2006-2010 Prakash Punnoor <prakash@punnoor.de>
  *
- * This file is part of Libav.
+ * This file is part of FFmpeg.
  *
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 
 #include <stdint.h>
 
+#include "libavutil/attributes.h"
+#include "libavutil/internal.h"
 
-/* prototypes for static functions in ac3enc_fixed.c and ac3enc_float.c */
-
-static void scale_coefficients(AC3EncodeContext *s);
-
-static void apply_window(DSPContext *dsp, SampleType *output,
-                         const SampleType *input, const SampleType *window,
-                         unsigned int len);
-
-static int normalize_samples(AC3EncodeContext *s);
-
-static void clip_coefficients(DSPContext *dsp, CoefType *coef, unsigned int len);
+#include "audiodsp.h"
+#include "internal.h"
+#include "ac3enc.h"
+#include "eac3enc.h"
 
 
 int AC3_NAME(allocate_sample_buffers)(AC3EncodeContext *s)
@@ -48,7 +43,7 @@ int AC3_NAME(allocate_sample_buffers)(AC3EncodeContext *s)
 
     FF_ALLOC_OR_GOTO(s->avctx, s->windowed_samples, AC3_WINDOW_SIZE *
                      sizeof(*s->windowed_samples), alloc_fail);
-    FF_ALLOC_OR_GOTO(s->avctx, s->planar_samples, s->channels * sizeof(*s->planar_samples),
+    FF_ALLOC_ARRAY_OR_GOTO(s->avctx, s->planar_samples, s->channels, sizeof(*s->planar_samples),
                      alloc_fail);
     for (ch = 0; ch < s->channels; ch++) {
         FF_ALLOCZ_OR_GOTO(s->avctx, s->planar_samples[ch],
@@ -62,36 +57,29 @@ alloc_fail:
 }
 
 
-/**
- * Deinterleave input samples.
- * Channels are reordered from Libav's default order to AC-3 order.
+/*
+ * Copy input samples.
+ * Channels are reordered from FFmpeg's default order to AC-3 order.
  */
-static void deinterleave_input_samples(AC3EncodeContext *s,
-                                       const SampleType *samples)
+static void copy_input_samples(AC3EncodeContext *s, SampleType **samples)
 {
-    int ch, i;
+    int ch;
 
-    /* deinterleave and remap input samples */
+    /* copy and remap input samples */
     for (ch = 0; ch < s->channels; ch++) {
-        const SampleType *sptr;
-        int sinc;
-
         /* copy last 256 samples of previous frame to the start of the current frame */
         memcpy(&s->planar_samples[ch][0], &s->planar_samples[ch][AC3_BLOCK_SIZE * s->num_blocks],
                AC3_BLOCK_SIZE * sizeof(s->planar_samples[0][0]));
 
-        /* deinterleave */
-        sinc = s->channels;
-        sptr = samples + s->channel_map[ch];
-        for (i = AC3_BLOCK_SIZE; i < AC3_BLOCK_SIZE * (s->num_blocks + 1); i++) {
-            s->planar_samples[ch][i] = *sptr;
-            sptr += sinc;
-        }
+        /* copy new samples for current frame */
+        memcpy(&s->planar_samples[ch][AC3_BLOCK_SIZE],
+               samples[s->channel_map[ch]],
+               AC3_BLOCK_SIZE * s->num_blocks * sizeof(s->planar_samples[0][0]));
     }
 }
 
 
-/**
+/*
  * 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.
@@ -105,11 +93,16 @@ static void apply_mdct(AC3EncodeContext *s)
             AC3Block *block = &s->blocks[blk];
             const SampleType *input_samples = &s->planar_samples[ch][blk * AC3_BLOCK_SIZE];
 
-            apply_window(&s->dsp, s->windowed_samples, input_samples,
-                         s->mdct_window, AC3_WINDOW_SIZE);
+#if CONFIG_AC3ENC_FLOAT
+            s->fdsp->vector_fmul(s->windowed_samples, input_samples,
+                                s->mdct_window, AC3_WINDOW_SIZE);
+#else
+            s->ac3dsp.apply_window_int16(s->windowed_samples, input_samples,
+                                         s->mdct_window, AC3_WINDOW_SIZE);
 
             if (s->fixed_point)
                 block->coeff_shift[ch+1] = normalize_samples(s);
+#endif
 
             s->mdct.mdct_calcw(&s->mdct, block->mdct_coef[ch+1],
                                s->windowed_samples);
@@ -118,37 +111,25 @@ static void apply_mdct(AC3EncodeContext *s)
 }
 
 
-/**
- * Calculate a single coupling coordinate.
- */
-static inline float calc_cpl_coord(float energy_ch, float energy_cpl)
-{
-    float coord = 0.125;
-    if (energy_cpl > 0)
-        coord *= sqrtf(energy_ch / energy_cpl);
-    return FFMIN(coord, COEF_MAX);
-}
-
-
-/**
+/*
  * Calculate coupling channel and coupling coordinates.
- * TODO: Currently this is only used for the floating-point encoder. I was
- *       able to make it work for the fixed-point encoder, but quality was
- *       generally lower in most cases than not using coupling. If a more
- *       adaptive coupling strategy were to be implemented it might be useful
- *       at that time to use coupling for the fixed-point encoder as well.
  */
 static void apply_channel_coupling(AC3EncodeContext *s)
 {
+    LOCAL_ALIGNED_16(CoefType, cpl_coords,      [AC3_MAX_BLOCKS], [AC3_MAX_CHANNELS][16]);
 #if CONFIG_AC3ENC_FLOAT
-    LOCAL_ALIGNED_16(float,   cpl_coords,       [AC3_MAX_BLOCKS], [AC3_MAX_CHANNELS][16]);
     LOCAL_ALIGNED_16(int32_t, fixed_cpl_coords, [AC3_MAX_BLOCKS], [AC3_MAX_CHANNELS][16]);
-    int blk, ch, bnd, i, j;
+#else
+    int32_t (*fixed_cpl_coords)[AC3_MAX_CHANNELS][16] = cpl_coords;
+#endif
+    int av_uninit(blk), ch, bnd, i, j;
     CoefSumType energy[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][16] = {{{0}}};
     int cpl_start, num_cpl_coefs;
 
     memset(cpl_coords,       0, AC3_MAX_BLOCKS * sizeof(*cpl_coords));
-    memset(fixed_cpl_coords, 0, AC3_MAX_BLOCKS * sizeof(*fixed_cpl_coords));
+#if CONFIG_AC3ENC_FLOAT
+    memset(fixed_cpl_coords, 0, AC3_MAX_BLOCKS * sizeof(*cpl_coords));
+#endif
 
     /* align start to 16-byte boundary. align length to multiple of 32.
         note: coupling start bin % 4 will always be 1 */
@@ -172,11 +153,7 @@ static void apply_channel_coupling(AC3EncodeContext *s)
         }
 
         /* coefficients must be clipped in order to be encoded */
-        clip_coefficients(&s->dsp, cpl_coef, num_cpl_coefs);
-
-        /* scale coupling coefficients from float to 24-bit fixed-point */
-        s->ac3dsp.float_to_fixed24(&block->fixed_coef[CPL_CH][cpl_start],
-                                   cpl_coef, num_cpl_coefs);
+        clip_coefficients(&s->adsp, cpl_coef, num_cpl_coefs);
     }
 
     /* calculate energy in each band in coupling channel and each fbw channel */
@@ -240,11 +217,11 @@ static void apply_channel_coupling(AC3EncodeContext *s)
                     } else {
                         CoefSumType coord_diff = 0;
                         for (bnd = 0; bnd < s->num_cpl_bands; bnd++) {
-                            coord_diff += fabs(cpl_coords[blk-1][ch][bnd] -
-                                               cpl_coords[blk  ][ch][bnd]);
+                            coord_diff += FFABS(cpl_coords[blk-1][ch][bnd] -
+                                                cpl_coords[blk  ][ch][bnd]);
                         }
                         coord_diff /= s->num_cpl_bands;
-                        if (coord_diff > 0.03)
+                        if (coord_diff > NEW_CPL_COORD_THRESHOLD)
                             block->new_cpl_coords[ch] = 1;
                     }
                 }
@@ -272,7 +249,7 @@ static void apply_channel_coupling(AC3EncodeContext *s)
                 energy_cpl = energy[blk][CPL_CH][bnd];
                 energy_ch = energy[blk][ch][bnd];
                 blk1 = blk+1;
-                while (!s->blocks[blk1].new_cpl_coords[ch] && blk1 < s->num_blocks) {
+                while (blk1 < s->num_blocks && !s->blocks[blk1].new_cpl_coords[ch]) {
                     if (s->blocks[blk1].cpl_in_use) {
                         energy_cpl += energy[blk1][CPL_CH][bnd];
                         energy_ch += energy[blk1][ch][bnd];
@@ -291,9 +268,11 @@ static void apply_channel_coupling(AC3EncodeContext *s)
         if (!block->cpl_in_use)
             continue;
 
+#if CONFIG_AC3ENC_FLOAT
         s->ac3dsp.float_to_fixed24(fixed_cpl_coords[blk][1],
                                    cpl_coords[blk][1],
                                    s->fbw_channels * 16);
+#endif
         s->ac3dsp.extract_exponents(block->cpl_coord_exp[1],
                                     fixed_cpl_coords[blk][1],
                                     s->fbw_channels * 16);
@@ -337,18 +316,17 @@ static void apply_channel_coupling(AC3EncodeContext *s)
 
     if (CONFIG_EAC3_ENCODER && s->eac3)
         ff_eac3_set_cpl_states(s);
-#endif /* CONFIG_AC3ENC_FLOAT */
 }
 
 
-/**
+/*
  * Determine rematrixing flags for each block and band.
  */
 static void compute_rematrixing_strategy(AC3EncodeContext *s)
 {
     int nb_coefs;
-    int blk, bnd, i;
-    AC3Block *block, *av_uninit(block0);
+    int blk, bnd;
+    AC3Block *block, *block0 = NULL;
 
     if (s->channel_mode != AC3_CHMODE_STEREO)
         return;
@@ -357,11 +335,6 @@ static void compute_rematrixing_strategy(AC3EncodeContext *s)
         block = &s->blocks[blk];
         block->new_rematrixing_strategy = !blk;
 
-        if (!s->rematrixing_enabled) {
-            block0 = block;
-            continue;
-        }
-
         block->num_rematrixing_bands = 4;
         if (block->cpl_in_use) {
             block->num_rematrixing_bands -= (s->start_freq[CPL_CH] <= 61);
@@ -371,21 +344,18 @@ static void compute_rematrixing_strategy(AC3EncodeContext *s)
         }
         nb_coefs = FFMIN(block->end_freq[1], block->end_freq[2]);
 
+        if (!s->rematrixing_enabled) {
+            block0 = block;
+            continue;
+        }
+
         for (bnd = 0; bnd < block->num_rematrixing_bands; bnd++) {
-            /* calculate calculate sum of squared coeffs for one band in one block */
+            /* calculate sum of squared coeffs for one band in one block */
             int start = ff_ac3_rematrix_band_tab[bnd];
             int end   = FFMIN(nb_coefs, ff_ac3_rematrix_band_tab[bnd+1]);
-            CoefSumType sum[4] = {0,};
-            for (i = start; i < end; i++) {
-                CoefType lt = block->mdct_coef[1][i];
-                CoefType rt = block->mdct_coef[2][i];
-                CoefType md = lt + rt;
-                CoefType sd = lt - rt;
-                MAC_COEF(sum[0], lt, lt);
-                MAC_COEF(sum[1], rt, rt);
-                MAC_COEF(sum[2], md, md);
-                MAC_COEF(sum[3], sd, sd);
-            }
+            CoefSumType sum[4];
+            sum_square_butterfly(s, sum, block->mdct_coef[1] + start,
+                                 block->mdct_coef[2] + start, end - start);
 
             /* compare sums to determine if rematrixing will be used for this band */
             if (FFMIN(sum[2], sum[3]) < FFMIN(sum[0], sum[1]))
@@ -404,14 +374,10 @@ static void compute_rematrixing_strategy(AC3EncodeContext *s)
 }
 
 
-/**
- * Encode a single AC-3 frame.
- */
-int AC3_NAME(encode_frame)(AVCodecContext *avctx, unsigned char *frame,
-                           int buf_size, void *data)
+int AC3_NAME(encode_frame)(AVCodecContext *avctx, AVPacket *avpkt,
+                           const AVFrame *frame, int *got_packet_ptr)
 {
     AC3EncodeContext *s = avctx->priv_data;
-    const SampleType *samples = data;
     int ret;
 
     if (s->options.allow_per_frame_metadata) {
@@ -423,14 +389,14 @@ int AC3_NAME(encode_frame)(AVCodecContext *avctx, unsigned char *frame,
     if (s->bit_alloc.sr_code == 1 || s->eac3)
         ff_ac3_adjust_frame_size(s);
 
-    deinterleave_input_samples(s, samples);
+    copy_input_samples(s, (SampleType **)frame->extended_data);
 
     apply_mdct(s);
 
     if (s->fixed_point)
         scale_coefficients(s);
 
-    clip_coefficients(&s->dsp, s->blocks[0].mdct_coef[1],
+    clip_coefficients(&s->adsp, s->blocks[0].mdct_coef[1],
                       AC3_MAX_COEFS * s->num_blocks * s->channels);
 
     s->cpl_on = s->cpl_enabled;
@@ -458,7 +424,13 @@ int AC3_NAME(encode_frame)(AVCodecContext *avctx, unsigned char *frame,
 
     ff_ac3_quantize_mantissas(s);
 
-    ff_ac3_output_frame(s, frame);
+    if ((ret = ff_alloc_packet2(avctx, avpkt, s->frame_size, 0)) < 0)
+        return ret;
+    ff_ac3_output_frame(s, avpkt->data);
 
-    return s->frame_size;
+    if (frame->pts != AV_NOPTS_VALUE)
+        avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->initial_padding);
+
+    *got_packet_ptr = 1;
+    return 0;
 }