]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/ac3dec.c
Enable proper output from the LFE channel, based on patch from Mathias Rauen dear...
[ffmpeg] / libavcodec / ac3dec.c
index 5a12a46bd955872315545451f2312e6c434b908c..ceb04b63000e4d42020c611edca0f8560bff9af7 100644 (file)
@@ -35,6 +35,7 @@
 #include "avcodec.h"
 #include "ac3_parser.h"
 #include "bitstream.h"
+#include "crc.h"
 #include "dsputil.h"
 #include "random.h"
 
@@ -145,7 +146,7 @@ typedef struct {
     uint8_t dba_lengths[AC3_MAX_CHANNELS][8]; ///< delta segment lengths
     uint8_t dba_values[AC3_MAX_CHANNELS][8];  ///< delta values for each segment
 
-    int sampling_rate;                      ///< sample frequency, in Hz
+    int sample_rate;                        ///< sample frequency, in Hz
     int bit_rate;                           ///< stream bit rate, in bits-per-second
     int frame_size;                         ///< current frame size, in bytes
 
@@ -333,11 +334,11 @@ static int ac3_parse_header(AC3DecodeContext *s)
     /* get decoding parameters from header info */
     s->bit_alloc_params.sr_code     = hdr.sr_code;
     s->channel_mode                 = hdr.channel_mode;
-    center_mix_level                  = gain_levels[center_levels[hdr.center_mix_level]];
-    surround_mix_level                = gain_levels[surround_levels[hdr.surround_mix_level]];
-    s->lfe_on                        = hdr.lfe_on;
+    center_mix_level                = gain_levels[center_levels[hdr.center_mix_level]];
+    surround_mix_level              = gain_levels[surround_levels[hdr.surround_mix_level]];
+    s->lfe_on                       = hdr.lfe_on;
     s->bit_alloc_params.sr_shift    = hdr.sr_shift;
-    s->sampling_rate                = hdr.sample_rate;
+    s->sample_rate                  = hdr.sample_rate;
     s->bit_rate                     = hdr.bit_rate;
     s->channels                     = hdr.channels;
     s->fbw_channels                 = s->channels - s->lfe_on;
@@ -577,13 +578,13 @@ static void remove_dithering(AC3DecodeContext *s) {
             else
                 end = s->end_freq[ch];
             for(i=0; i<end; i++) {
-                if(bap[i] == 0)
+                if(!bap[i])
                     coeffs[i] = 0.0f;
             }
             if(s->channel_in_cpl[ch]) {
                 bap = s->bap[CPL_CH];
                 for(; i<s->end_freq[CPL_CH]; i++) {
-                    if(bap[i] == 0)
+                    if(!bap[i])
                         coeffs[i] = 0.0f;
                 }
             }
@@ -719,8 +720,7 @@ static inline void do_imdct(AC3DecodeContext *s)
             do_imdct_256(s, ch);
         } else {
             s->imdct_512.fft.imdct_calc(&s->imdct_512, s->tmp_output,
-                                          s->transform_coeffs[ch],
-                                          s->tmp_imdct);
+                                        s->transform_coeffs[ch], s->tmp_imdct);
         }
         /* For the first half of the block, apply the window, add the delay
            from the previous block, and send to output */
@@ -729,34 +729,33 @@ static inline void do_imdct(AC3DecodeContext *s)
         /* For the second half of the block, apply the window and store the
            samples to delay, to be combined with the next block */
         s->dsp.vector_fmul_reverse(s->delay[ch-1], s->tmp_output+256,
-                                     s->window, 256);
+                                   s->window, 256);
     }
 }
 
 /**
  * Downmix the output to mono or stereo.
  */
-static void ac3_downmix(float samples[AC3_MAX_CHANNELS][256], int fbw_channels,
-                        int output_mode, float coef[AC3_MAX_CHANNELS][2])
+static void ac3_downmix(AC3DecodeContext *s)
 {
     int i, j;
     float v0, v1, s0, s1;
 
     for(i=0; i<256; i++) {
         v0 = v1 = s0 = s1 = 0.0f;
-        for(j=0; j<fbw_channels; j++) {
-            v0 += samples[j][i] * coef[j][0];
-            v1 += samples[j][i] * coef[j][1];
-            s0 += coef[j][0];
-            s1 += coef[j][1];
+        for(j=0; j<s->fbw_channels; j++) {
+            v0 += s->output[j][i] * s->downmix_coeffs[j][0];
+            v1 += s->output[j][i] * s->downmix_coeffs[j][1];
+            s0 += s->downmix_coeffs[j][0];
+            s1 += s->downmix_coeffs[j][1];
         }
         v0 /= s0;
         v1 /= s1;
-        if(output_mode == AC3_CHMODE_MONO) {
-            samples[0][i] = (v0 + v1) * LEVEL_MINUS_3DB;
-        } else if(output_mode == AC3_CHMODE_STEREO) {
-            samples[0][i] = v0;
-            samples[1][i] = v1;
+        if(s->output_mode == AC3_CHMODE_MONO) {
+            s->output[0][i] = (v0 + v1) * LEVEL_MINUS_3DB;
+        } else if(s->output_mode == AC3_CHMODE_STEREO) {
+            s->output[0][i] = v0;
+            s->output[1][i] = v1;
         }
     }
 }
@@ -791,7 +790,7 @@ static int ac3_parse_audio_block(AC3DecodeContext *s, int blk)
     do {
         if(get_bits1(gbc)) {
             s->dynamic_range[i] = ((dynamic_range_tab[get_bits(gbc, 8)]-1.0) *
-                                    s->avctx->drc_scale)+1.0;
+                                  s->avctx->drc_scale)+1.0;
         } else if(blk == 0) {
             s->dynamic_range[i] = 1.0f;
         }
@@ -1054,8 +1053,7 @@ static int ac3_parse_audio_block(AC3DecodeContext *s, int blk)
     /* downmix output if needed */
     if(s->channels != s->out_channels && !((s->output_mode & AC3_OUTPUT_LFEON) &&
             s->fbw_channels == s->out_channels)) {
-        ac3_downmix(s->output, s->fbw_channels, s->output_mode,
-                    s->downmix_coeffs);
+        ac3_downmix(s);
     }
 
     /* convert float to 16-bit integer */
@@ -1074,7 +1072,7 @@ static int ac3_parse_audio_block(AC3DecodeContext *s, int blk)
  */
 static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size, uint8_t *buf, int buf_size)
 {
-    AC3DecodeContext *s = (AC3DecodeContext *)avctx->priv_data;
+    AC3DecodeContext *s = avctx->priv_data;
     int16_t *out_samples = (int16_t *)data;
     int i, blk, ch, err;
 
@@ -1104,15 +1102,24 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size,
         return -1;
     }
 
-    avctx->sample_rate = s->sampling_rate;
-    avctx->bit_rate = s->bit_rate;
-
     /* check that reported frame size fits in input buffer */
     if(s->frame_size > buf_size) {
         av_log(avctx, AV_LOG_ERROR, "incomplete frame\n");
         return -1;
     }
 
+    /* check for crc mismatch */
+    if(avctx->error_resilience > 0) {
+        if(av_crc(av_crc8005, 0, &buf[2], s->frame_size-2)) {
+            av_log(avctx, AV_LOG_ERROR, "frame CRC mismatch\n");
+            return -1;
+        }
+        /* TODO: error concealment */
+    }
+
+    avctx->sample_rate = s->sample_rate;
+    avctx->bit_rate = s->bit_rate;
+
     /* channel config */
     s->out_channels = s->channels;
     if (avctx->request_channels > 0 && avctx->request_channels <= 2 &&
@@ -1142,7 +1149,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size,
  */
 static int ac3_decode_end(AVCodecContext *avctx)
 {
-    AC3DecodeContext *s = (AC3DecodeContext *)avctx->priv_data;
+    AC3DecodeContext *s = avctx->priv_data;
     ff_mdct_end(&s->imdct_512);
     ff_mdct_end(&s->imdct_256);