]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/ac3dec.c
skip unsupported frame types and substream id's
[ffmpeg] / libavcodec / ac3dec.c
index 40727e78b467aad30e7bf7c602858efde58003d3..b7941c1623725325b7542c3ab641f43ddbe30342 100644 (file)
@@ -111,6 +111,7 @@ static const uint8_t ac3_default_coeffs[8][5][2] = {
 #define AC3_OUTPUT_LFEON  8
 
 typedef struct {
+    int num_blocks;                         ///< number of audio blocks
     int channel_mode;                       ///< channel mode (acmod)
     int block_switch[AC3_MAX_CHANNELS];     ///< block switch flags
     int dither_flag[AC3_MAX_CHANNELS];      ///< dither flags
@@ -133,6 +134,8 @@ typedef struct {
 
     int sample_rate;                        ///< sample frequency, in Hz
     int bit_rate;                           ///< stream bit rate, in bits-per-second
+    int frame_type;                         ///< frame type (strmtyp)
+    int substreamid;                        ///< substream identification
     int frame_size;                         ///< current frame size, in bytes
 
     int channels;                           ///< number of total channels
@@ -324,6 +327,16 @@ static int ac3_parse_header(AC3DecodeContext *s)
     s->frame_size                   = hdr.frame_size;
     s->center_mix_level             = hdr.center_mix_level;
     s->surround_mix_level           = hdr.surround_mix_level;
+    s->num_blocks                   = hdr.num_blocks;
+    s->frame_type                   = hdr.frame_type;
+    s->substreamid                  = hdr.substreamid;
+
+    if(s->lfe_on) {
+        s->start_freq[s->lfe_ch] = 0;
+        s->end_freq[s->lfe_ch] = 7;
+        s->num_exp_groups[s->lfe_ch] = 2;
+        s->channel_in_cpl[s->lfe_ch] = 0;
+    }
 
     /* read the rest of the bsi. read twice for dual mono mode. */
     i = !(s->channel_mode);
@@ -896,10 +909,7 @@ static int ac3_parse_audio_block(AC3DecodeContext *s, int blk)
     s->exp_strategy[CPL_CH] = EXP_REUSE;
     s->exp_strategy[s->lfe_ch] = EXP_REUSE;
     for (ch = !s->cpl_in_use; ch <= s->channels; ch++) {
-        if(ch == s->lfe_ch)
-            s->exp_strategy[ch] = get_bits(gbc, 1);
-        else
-            s->exp_strategy[ch] = get_bits(gbc, 2);
+        s->exp_strategy[ch] = get_bits(gbc, 2 - (ch == s->lfe_ch));
         if(s->exp_strategy[ch] != EXP_REUSE)
             bit_alloc_stages[ch] = 3;
     }
@@ -926,9 +936,6 @@ static int ac3_parse_audio_block(AC3DecodeContext *s, int blk)
                 memset(bit_alloc_stages, 3, AC3_MAX_CHANNELS);
         }
     }
-    s->start_freq[s->lfe_ch] = 0;
-    s->end_freq[s->lfe_ch] = 7;
-    s->num_exp_groups[s->lfe_ch] = 2;
     if (s->cpl_in_use && s->exp_strategy[CPL_CH] != EXP_REUSE) {
         s->num_exp_groups[CPL_CH] = (s->end_freq[CPL_CH] - s->start_freq[CPL_CH]) /
                                     (3 << (s->exp_strategy[CPL_CH] - 1));
@@ -1153,12 +1160,11 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size,
         }
     }
 
-    /* parse the syncinfo */
     if(err && err != AC3_PARSE_ERROR_CRC) {
         switch(err) {
             case AC3_PARSE_ERROR_SYNC:
                 av_log(avctx, AV_LOG_ERROR, "frame sync error\n");
-                break;
+                return -1;
             case AC3_PARSE_ERROR_BSID:
                 av_log(avctx, AV_LOG_ERROR, "invalid bitstream id\n");
                 break;
@@ -1169,7 +1175,14 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size,
                 av_log(avctx, AV_LOG_ERROR, "invalid frame size\n");
                 break;
             case AC3_PARSE_ERROR_FRAME_TYPE:
+                /* skip frame if CRC is ok. otherwise use error concealment. */
+                /* TODO: add support for substreams and dependent frames */
+                if(s->frame_type == EAC3_FRAME_TYPE_DEPENDENT || s->substreamid) {
+                    av_log(avctx, AV_LOG_ERROR, "unsupported frame type : skipping frame\n");
+                    return s->frame_size;
+                } else {
                 av_log(avctx, AV_LOG_ERROR, "invalid frame type\n");
+                }
                 break;
             default:
                 av_log(avctx, AV_LOG_ERROR, "invalid header\n");
@@ -1206,15 +1219,17 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size,
     }
 
     /* parse the audio blocks */
-    for (blk = 0; blk < NB_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         if (!err && ac3_parse_audio_block(s, blk)) {
             av_log(avctx, AV_LOG_ERROR, "error parsing the audio block\n");
         }
+
+        /* interleave output samples */
         for (i = 0; i < 256; i++)
             for (ch = 0; ch < s->out_channels; ch++)
                 *(out_samples++) = s->int_output[ch][i];
     }
-    *data_size = NB_BLOCKS * 256 * avctx->channels * sizeof (int16_t);
+    *data_size = s->num_blocks * 256 * avctx->channels * sizeof (int16_t);
     return s->frame_size;
 }