]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/ac3dec.c
lavc: drop unused argument from lock_avcodec()
[ffmpeg] / libavcodec / ac3dec.c
index 244a18323f8bf792b31a775c6d851fbf467ee7fe..c7deb56e1c61c5bfe2b98a685cca26c4d393439e 100644 (file)
@@ -33,6 +33,7 @@
 #include "libavutil/crc.h"
 #include "libavutil/downmix_info.h"
 #include "libavutil/opt.h"
+#include "libavutil/thread.h"
 #include "bswapdsp.h"
 #include "internal.h"
 #include "aac_ac3_parser.h"
@@ -183,23 +184,26 @@ static av_cold void ac3_tables_init(void)
  */
 static av_cold int ac3_decode_init(AVCodecContext *avctx)
 {
+    static AVOnce init_static_once = AV_ONCE_INIT;
     AC3DecodeContext *s = avctx->priv_data;
-    int i;
+    int i, ret;
 
     s->avctx = avctx;
 
-    ac3_tables_init();
-    ff_mdct_init(&s->imdct_256, 8, 1, 1.0);
-    ff_mdct_init(&s->imdct_512, 9, 1, 1.0);
+    if ((ret = ff_mdct_init(&s->imdct_256, 8, 1, 1.0)) < 0 ||
+        (ret = ff_mdct_init(&s->imdct_512, 9, 1, 1.0)) < 0)
+        return ret;
     AC3_RENAME(ff_kbd_window_init)(s->window, 5.0, 256);
     ff_bswapdsp_init(&s->bdsp);
 
 #if (USE_FIXED)
     s->fdsp = avpriv_alloc_fixed_dsp(avctx->flags & AV_CODEC_FLAG_BITEXACT);
 #else
-    s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
     ff_fmt_convert_init(&s->fmt_conv, avctx);
+    s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
 #endif
+    if (!s->fdsp)
+        return AVERROR(ENOMEM);
 
     ff_ac3dsp_init(&s->ac3dsp, avctx->flags & AV_CODEC_FLAG_BITEXACT);
     av_lfg_init(&s->dith_state, 0);
@@ -223,6 +227,8 @@ static av_cold int ac3_decode_init(AVCodecContext *avctx)
         s->dlyptr[i] = s->delay[i];
     }
 
+    ff_thread_once(&init_static_once, ac3_tables_init);
+
     return 0;
 }
 
@@ -317,6 +323,7 @@ static int parse_frame_header(AC3DecodeContext *s)
     s->fbw_channels                 = s->channels - s->lfe_on;
     s->lfe_ch                       = s->fbw_channels + 1;
     s->frame_size                   = hdr.frame_size;
+    s->superframe_size             += hdr.frame_size;
     s->preferred_downmix            = AC3_DMIXMOD_NOTINDICATED;
     s->center_mix_level             = hdr.center_mix_level;
     s->center_mix_level_ltrt        = 4; // -3.0dB
@@ -451,7 +458,7 @@ static int decode_exponents(AC3DecodeContext *s,
         prevexp += dexp[i] - 2;
         if (prevexp > 24U) {
             av_log(s->avctx, AV_LOG_ERROR, "exponent %d is out-of-range\n", prevexp);
-            return -1;
+            return AVERROR_INVALIDDATA;
         }
         switch (group_size) {
         case 4: dexps[j++] = prevexp;
@@ -683,7 +690,7 @@ static void do_rematrixing(AC3DecodeContext *s)
  * Convert frequency domain coefficients to time-domain audio samples.
  * reference: Section 7.9.4 Transformation Equations
  */
-static inline void do_imdct(AC3DecodeContext *s, int channels)
+static inline void do_imdct(AC3DecodeContext *s, int channels, int offset)
 {
     int ch;
 
@@ -695,25 +702,25 @@ static inline void do_imdct(AC3DecodeContext *s, int channels)
                 x[i] = s->transform_coeffs[ch][2 * i];
             s->imdct_256.imdct_half(&s->imdct_256, s->tmp_output, x);
 #if USE_FIXED
-            s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1],
+            s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1 + offset],
                                        s->tmp_output, s->window, 128, 8);
 #else
-            s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1],
+            s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1 + offset],
                                        s->tmp_output, s->window, 128);
 #endif
             for (i = 0; i < 128; i++)
                 x[i] = s->transform_coeffs[ch][2 * i + 1];
-            s->imdct_256.imdct_half(&s->imdct_256, s->delay[ch - 1], x);
+            s->imdct_256.imdct_half(&s->imdct_256, s->delay[ch - 1 + offset], x);
         } else {
             s->imdct_512.imdct_half(&s->imdct_512, s->tmp_output, s->transform_coeffs[ch]);
 #if USE_FIXED
-            s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1],
+            s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1 + offset],
                                        s->tmp_output, s->window, 128, 8);
 #else
-            s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1],
+            s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1 + offset],
                                        s->tmp_output, s->window, 128);
 #endif
-            memcpy(s->delay[ch - 1], s->tmp_output + 128, 128 * sizeof(FFTSample));
+            memcpy(s->delay[ch - 1 + offset], s->tmp_output + 128, 128 * sizeof(FFTSample));
         }
     }
 }
@@ -1063,7 +1070,7 @@ static inline int coupling_coordinates(AC3DecodeContext *s, int blk)
 /**
  * Decode a single audio block from the AC-3 bitstream.
  */
-static int decode_audio_block(AC3DecodeContext *s, int blk)
+static int decode_audio_block(AC3DecodeContext *s, int blk, int offset)
 {
     int fbw_channels = s->fbw_channels;
     int channel_mode = s->channel_mode;
@@ -1426,7 +1433,7 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
             ac3_upmix_delay(s);
         }
 
-        do_imdct(s, s->channels);
+        do_imdct(s, s->channels, offset);
 
         if (downmix_output) {
 #if USE_FIXED
@@ -1449,7 +1456,7 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
                                           s->out_channels, s->fbw_channels, 128);
         }
 
-        do_imdct(s, s->out_channels);
+        do_imdct(s, s->out_channels, offset);
     }
 
     return 0;
@@ -1463,14 +1470,37 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
 {
     AVFrame *frame     = data;
     const uint8_t *buf = avpkt->data;
-    int buf_size = avpkt->size;
+    int buf_size, full_buf_size = avpkt->size;
     AC3DecodeContext *s = avctx->priv_data;
-    int blk, ch, err, ret;
+    int blk, ch, err, offset, ret;
+    int i;
+    int skip = 0, got_independent_frame = 0;
     const uint8_t *channel_map;
+    uint8_t extended_channel_map[EAC3_MAX_CHANNELS];
     const SHORTFLOAT *output[AC3_MAX_CHANNELS];
     enum AVMatrixEncoding matrix_encoding;
     AVDownmixInfo *downmix_info;
 
+    s->superframe_size = 0;
+
+    buf_size = full_buf_size;
+    for (i = 1; i < buf_size; i += 2) {
+        if (buf[i] == 0x77 || buf[i] == 0x0B) {
+            if ((buf[i] ^ buf[i-1]) == (0x77 ^ 0x0B)) {
+                i--;
+                break;
+            } else if ((buf[i] ^ buf[i+1]) == (0x77 ^ 0x0B)) {
+                break;
+            }
+        }
+    }
+    if (i >= buf_size)
+        return AVERROR_INVALIDDATA;
+    if (i > 10)
+        return i;
+    buf += i;
+    buf_size -= i;
+
     /* copy input buffer to decoder context to avoid reading past the end
        of the buffer, which can be caused by a damaged input stream. */
     if (buf_size >= 2 && AV_RB16(buf) == 0x770B) {
@@ -1488,6 +1518,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
         av_lfg_init_from_data(&s->dith_state, s->input_buffer, FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE));
 
     buf = s->input_buffer;
+dependent_frame:
     /* initialize the GetBitContext with the start of valid AC-3 Frame */
     if ((ret = init_get_bits8(&s->gbc, buf, buf_size)) < 0)
         return ret;
@@ -1511,11 +1542,11 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
             break;
         case AAC_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) {
+            /* TODO: add support for substreams */
+            if (s->substreamid) {
                 av_log(avctx, AV_LOG_DEBUG,
-                       "unsupported frame type %d: skipping frame\n",
-                       s->frame_type);
+                       "unsupported substream %d: skipping frame\n",
+                       s->substreamid);
                 *got_frame_ptr = 0;
                 return buf_size;
             } else {
@@ -1546,10 +1577,10 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
         }
     }
 
-    /* if frame is ok, set audio parameters */
-    if (!err) {
-        avctx->sample_rate = s->sample_rate;
-        avctx->bit_rate    = s->bit_rate;
+    if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT && !got_independent_frame) {
+        av_log(avctx, AV_LOG_WARNING, "Ignoring dependent frame without independent frame.\n");
+        *got_frame_ptr = 0;
+        return FFMIN(full_buf_size, s->frame_size);
     }
 
     /* channel config */
@@ -1594,29 +1625,25 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
     if (s->bitstream_mode == 0x7 && s->channels > 1)
         avctx->audio_service_type = AV_AUDIO_SERVICE_TYPE_KARAOKE;
 
-    /* get output buffer */
-    frame->nb_samples = s->num_blocks * AC3_BLOCK_SIZE;
-    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
-        return ret;
-
     /* decode the audio blocks */
     channel_map = ff_ac3_dec_channel_map[s->output_mode & ~AC3_OUTPUT_LFEON][s->lfe_on];
+    offset = s->frame_type == EAC3_FRAME_TYPE_DEPENDENT ? AC3_MAX_CHANNELS : 0;
     for (ch = 0; ch < AC3_MAX_CHANNELS; ch++) {
-        output[ch] = s->output[ch];
-        s->outptr[ch] = s->output[ch];
+        output[ch] = s->output[ch + offset];
+        s->outptr[ch] = s->output[ch + offset];
     }
     for (ch = 0; ch < s->channels; ch++) {
         if (ch < s->out_channels)
-            s->outptr[channel_map[ch]] = (SHORTFLOAT *)frame->data[ch];
+            s->outptr[channel_map[ch]] = s->output_buffer[ch + offset];
     }
     for (blk = 0; blk < s->num_blocks; blk++) {
-        if (!err && decode_audio_block(s, blk)) {
+        if (!err && decode_audio_block(s, blk, offset)) {
             av_log(avctx, AV_LOG_ERROR, "error decoding the audio block\n");
             err = 1;
         }
         if (err)
             for (ch = 0; ch < s->out_channels; ch++)
-                memcpy(((SHORTFLOAT*)frame->data[ch]) + AC3_BLOCK_SIZE*blk, output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT));
+                memcpy(s->output_buffer[ch + offset] + AC3_BLOCK_SIZE*blk, output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT));
         for (ch = 0; ch < s->out_channels; ch++)
             output[ch] = s->outptr[channel_map[ch]];
         for (ch = 0; ch < s->out_channels; ch++) {
@@ -1625,11 +1652,120 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
         }
     }
 
-    frame->decode_error_flags = err ? FF_DECODE_ERROR_INVALID_BITSTREAM : 0;
-
     /* keep last block for error concealment in next frame */
     for (ch = 0; ch < s->out_channels; ch++)
-        memcpy(s->output[ch], output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT));
+        memcpy(s->output[ch + offset], output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT));
+
+    /* check if there is dependent frame */
+    if (buf_size > s->frame_size) {
+        AC3HeaderInfo hdr;
+        int err;
+
+        if (buf_size - s->frame_size <= 16) {
+            skip = buf_size - s->frame_size;
+            goto skip;
+        }
+
+        if ((ret = init_get_bits8(&s->gbc, buf + s->frame_size, buf_size - s->frame_size)) < 0)
+            return ret;
+
+        err = ff_ac3_parse_header(&s->gbc, &hdr);
+        if (err)
+            return err;
+
+        if (hdr.frame_type == EAC3_FRAME_TYPE_DEPENDENT) {
+            if (hdr.num_blocks != s->num_blocks || s->sample_rate != hdr.sample_rate) {
+                av_log(avctx, AV_LOG_WARNING, "Ignoring non-compatible dependent frame.\n");
+            } else {
+                buf += s->frame_size;
+                buf_size -= s->frame_size;
+                s->prev_output_mode = s->output_mode;
+                s->prev_bit_rate = s->bit_rate;
+                got_independent_frame = 1;
+                goto dependent_frame;
+            }
+        }
+    }
+skip:
+
+    frame->decode_error_flags = err ? FF_DECODE_ERROR_INVALID_BITSTREAM : 0;
+
+    /* if frame is ok, set audio parameters */
+    if (!err) {
+        avctx->sample_rate = s->sample_rate;
+        avctx->bit_rate    = s->bit_rate + s->prev_bit_rate;
+    }
+
+    for (ch = 0; ch < EAC3_MAX_CHANNELS; ch++)
+        extended_channel_map[ch] = ch;
+
+    if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) {
+        uint64_t ich_layout = avpriv_ac3_channel_layout_tab[s->prev_output_mode & ~AC3_OUTPUT_LFEON];
+        int channel_map_size = ff_ac3_channels_tab[s->output_mode & ~AC3_OUTPUT_LFEON] + s->lfe_on;
+        uint64_t channel_layout;
+        int extend = 0;
+
+        if (s->prev_output_mode & AC3_OUTPUT_LFEON)
+            ich_layout |= AV_CH_LOW_FREQUENCY;
+
+        channel_layout = ich_layout;
+        for (ch = 0; ch < 16; ch++) {
+            if (s->channel_map & (1 << (EAC3_MAX_CHANNELS - ch - 1))) {
+                channel_layout |= ff_eac3_custom_channel_map_locations[ch][1];
+            }
+        }
+        if (av_get_channel_layout_nb_channels(channel_layout) > EAC3_MAX_CHANNELS) {
+            av_log(avctx, AV_LOG_ERROR, "Too many channels (%d) coded\n",
+                   av_get_channel_layout_nb_channels(channel_layout));
+            return AVERROR_INVALIDDATA;
+        }
+
+        avctx->channel_layout = channel_layout;
+        avctx->channels = av_get_channel_layout_nb_channels(channel_layout);
+
+        for (ch = 0; ch < EAC3_MAX_CHANNELS; ch++) {
+            if (s->channel_map & (1 << (EAC3_MAX_CHANNELS - ch - 1))) {
+                if (ff_eac3_custom_channel_map_locations[ch][0]) {
+                    int index = av_get_channel_layout_channel_index(channel_layout,
+                                                                    ff_eac3_custom_channel_map_locations[ch][1]);
+                    if (index < 0)
+                        return AVERROR_INVALIDDATA;
+                    if (extend >= channel_map_size)
+                        return AVERROR_INVALIDDATA;
+
+                    extended_channel_map[index] = offset + channel_map[extend++];
+                } else {
+                    int i;
+
+                    for (i = 0; i < 64; i++) {
+                        if ((1ULL << i) & ff_eac3_custom_channel_map_locations[ch][1]) {
+                            int index = av_get_channel_layout_channel_index(channel_layout,
+                                                                            1ULL << i);
+                            if (index < 0)
+                                return AVERROR_INVALIDDATA;
+                            if (extend >= channel_map_size)
+                                return AVERROR_INVALIDDATA;
+
+                            extended_channel_map[index] = offset + channel_map[extend++];
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /* get output buffer */
+    frame->nb_samples = s->num_blocks * AC3_BLOCK_SIZE;
+    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+        return ret;
+
+    for (ch = 0; ch < avctx->channels; ch++) {
+        int map = extended_channel_map[ch];
+        av_assert0(ch>=AV_NUM_DATA_POINTERS || frame->extended_data[ch] == frame->data[ch]);
+        memcpy((SHORTFLOAT *)frame->extended_data[ch],
+               s->output_buffer[map],
+               s->num_blocks * AC3_BLOCK_SIZE * sizeof(SHORTFLOAT));
+    }
 
     /*
      * AVMatrixEncoding
@@ -1689,7 +1825,10 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
 
     *got_frame_ptr = 1;
 
-    return FFMIN(buf_size, s->frame_size);
+    if (!s->superframe_size)
+        return FFMIN(full_buf_size, s->frame_size + skip);
+
+    return FFMIN(full_buf_size, s->superframe_size + skip);
 }
 
 /**