]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/ac3dec.c
mmaldec: fix pkt_dts determination
[ffmpeg] / libavcodec / ac3dec.c
index 3edb3aff83b46dac550fe0ce995c98cf76ca9a32..97ce2878a8740308b6dd0af0475dbff4c205fcbb 100644 (file)
 #include <math.h>
 #include <string.h>
 
+#include "libavutil/channel_layout.h"
 #include "libavutil/crc.h"
+#include "libavutil/downmix_info.h"
 #include "libavutil/opt.h"
+#include "bswapdsp.h"
 #include "internal.h"
 #include "aac_ac3_parser.h"
 #include "ac3_parser.h"
@@ -76,6 +79,15 @@ static const float gain_levels[9] = {
     LEVEL_MINUS_9DB
 };
 
+/** Adjustments in dB gain (LFE, +10 to -21 dB) */
+static const float gain_levels_lfe[32] = {
+    3.162275, 2.818382, 2.511886, 2.238719, 1.995261, 1.778278, 1.584893,
+    1.412536, 1.258924, 1.122018, 1.000000, 0.891251, 0.794328, 0.707946,
+    0.630957, 0.562341, 0.501187, 0.446683, 0.398107, 0.354813, 0.316227,
+    0.281838, 0.251188, 0.223872, 0.199526, 0.177828, 0.158489, 0.141253,
+    0.125892, 0.112201, 0.100000, 0.089125
+};
+
 /**
  * Table for default stereo downmixing coefficients
  * reference: Section 7.8.2 Downmixing Into Two Channels
@@ -169,20 +181,21 @@ static av_cold int ac3_decode_init(AVCodecContext *avctx)
     ff_mdct_init(&s->imdct_256, 8, 1, 1.0);
     ff_mdct_init(&s->imdct_512, 9, 1, 1.0);
     ff_kbd_window_init(s->window, 5.0, 256);
-    ff_dsputil_init(&s->dsp, avctx);
-    avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
-    ff_ac3dsp_init(&s->ac3dsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    ff_bswapdsp_init(&s->bdsp);
+    avpriv_float_dsp_init(&s->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT);
+    ff_ac3dsp_init(&s->ac3dsp, avctx->flags & AV_CODEC_FLAG_BITEXACT);
     ff_fmt_convert_init(&s->fmt_conv, avctx);
     av_lfg_init(&s->dith_state, 0);
 
     avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
 
     /* allow downmixing to stereo or mono */
-    if (avctx->channels > 0 && avctx->request_channels > 0 &&
-            avctx->request_channels < avctx->channels &&
-            avctx->request_channels <= 2) {
-        avctx->channels = avctx->request_channels;
-    }
+    if (avctx->channels > 1 &&
+        avctx->request_channel_layout == AV_CH_LAYOUT_MONO)
+        avctx->channels = 1;
+    else if (avctx->channels > 2 &&
+             avctx->request_channel_layout == AV_CH_LAYOUT_STEREO)
+        avctx->channels = 2;
     s->downmixed = 1;
 
     for (i = 0; i < AC3_MAX_CHANNELS; i++) {
@@ -217,12 +230,26 @@ static int ac3_parse_header(AC3DecodeContext *s)
 
     skip_bits(gbc, 2); //skip copyright bit and original bitstream bit
 
-    /* skip the timecodes (or extra bitstream information for Alternate Syntax)
-       TODO: read & use the xbsi1 downmix levels */
-    if (get_bits1(gbc))
-        skip_bits(gbc, 14); //skip timecode1 / xbsi1
-    if (get_bits1(gbc))
-        skip_bits(gbc, 14); //skip timecode2 / xbsi2
+    /* skip the timecodes or parse the Alternate Bit Stream Syntax */
+    if (s->bitstream_id != 6) {
+        if (get_bits1(gbc))
+            skip_bits(gbc, 14); //skip timecode1
+        if (get_bits1(gbc))
+            skip_bits(gbc, 14); //skip timecode2
+    } else {
+        if (get_bits1(gbc)) {
+            s->preferred_downmix       = get_bits(gbc, 2);
+            s->center_mix_level_ltrt   = get_bits(gbc, 3);
+            s->surround_mix_level_ltrt = av_clip(get_bits(gbc, 3), 3, 7);
+            s->center_mix_level        = get_bits(gbc, 3);
+            s->surround_mix_level      = av_clip(get_bits(gbc, 3), 3, 7);
+        }
+        if (get_bits1(gbc)) {
+            s->dolby_surround_ex_mode = get_bits(gbc, 2);
+            s->dolby_headphone_mode   = get_bits(gbc, 2);
+            skip_bits(gbc, 10); // skip adconvtyp (1), xbsi2 (8), encinfo (1)
+        }
+    }
 
     /* skip additional bitstream info */
     if (get_bits1(gbc)) {
@@ -249,9 +276,9 @@ static int parse_frame_header(AC3DecodeContext *s)
 
     /* get decoding parameters from header info */
     s->bit_alloc_params.sr_code     = hdr.sr_code;
+    s->bitstream_id                 = hdr.bitstream_id;
     s->bitstream_mode               = hdr.bitstream_mode;
     s->channel_mode                 = hdr.channel_mode;
-    s->channel_layout               = hdr.channel_layout;
     s->lfe_on                       = hdr.lfe_on;
     s->bit_alloc_params.sr_shift    = hdr.sr_shift;
     s->sample_rate                  = hdr.sample_rate;
@@ -260,11 +287,18 @@ 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->preferred_downmix            = AC3_DMIXMOD_NOTINDICATED;
     s->center_mix_level             = hdr.center_mix_level;
+    s->center_mix_level_ltrt        = 4; // -3.0dB
     s->surround_mix_level           = hdr.surround_mix_level;
+    s->surround_mix_level_ltrt      = 4; // -3.0dB
+    s->lfe_mix_level_exists         = 0;
     s->num_blocks                   = hdr.num_blocks;
     s->frame_type                   = hdr.frame_type;
     s->substreamid                  = hdr.substreamid;
+    s->dolby_surround_mode          = hdr.dolby_surround_mode;
+    s->dolby_surround_ex_mode       = AC3_DSUREXMOD_NOTINDICATED;
+    s->dolby_headphone_mode         = AC3_DHEADPHONMOD_NOTINDICATED;
 
     if (s->lfe_on) {
         s->start_freq[s->lfe_ch]     = 0;
@@ -273,7 +307,7 @@ static int parse_frame_header(AC3DecodeContext *s)
         s->channel_in_cpl[s->lfe_ch] = 0;
     }
 
-    if (hdr.bitstream_id <= 10) {
+    if (s->bitstream_id <= 10) {
         s->eac3                  = 0;
         s->snr_offset_strategy   = 2;
         s->block_switch_syntax   = 1;
@@ -410,7 +444,7 @@ static void calc_transform_coeffs_cpl(AC3DecodeContext *s)
 /**
  * Grouped mantissas for 3-level 5-level and 11-level quantization
  */
-typedef struct {
+typedef struct mant_groups {
     int b1_mant[2];
     int b2_mant[2];
     int b4_mant;
@@ -747,8 +781,13 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
     i = !s->channel_mode;
     do {
         if (get_bits1(gbc)) {
-            s->dynamic_range[i] = ((dynamic_range_tab[get_bits(gbc, 8)] - 1.0) *
-                                  s->drc_scale) + 1.0;
+            /* Allow asymmetric application of DRC when drc_scale > 1.
+               Amplification of quiet sounds is enhanced */
+            float range = dynamic_range_tab[get_bits(gbc, 8)];
+            if (range > 1.0 || s->drc_scale <= 1.0)
+                s->dynamic_range[i] = powf(range, s->drc_scale);
+            else
+                s->dynamic_range[i] = range;
         } else if (blk == 0) {
             s->dynamic_range[i] = 1.0f;
         }
@@ -1271,13 +1310,16 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
     int blk, ch, err, ret;
     const uint8_t *channel_map;
     const float *output[AC3_MAX_CHANNELS];
+    enum AVMatrixEncoding matrix_encoding;
+    AVDownmixInfo *downmix_info;
 
     /* 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) {
         // seems to be byte-swapped AC-3
         int cnt = FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE) >> 1;
-        s->dsp.bswap16_buf((uint16_t *)s->input_buffer, (const uint16_t *)buf, cnt);
+        s->bdsp.bswap16_buf((uint16_t *) s->input_buffer,
+                            (const uint16_t *) buf, cnt);
     } else
         memcpy(s->input_buffer, buf, FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE));
     buf = s->input_buffer;
@@ -1349,14 +1391,15 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
         s->output_mode  = s->channel_mode;
         if (s->lfe_on)
             s->output_mode |= AC3_OUTPUT_LFEON;
-        if (avctx->request_channels > 0 && avctx->request_channels <= 2 &&
-                avctx->request_channels < s->channels) {
-            s->out_channels = avctx->request_channels;
-            s->output_mode  = avctx->request_channels == 1 ? AC3_CHMODE_MONO : AC3_CHMODE_STEREO;
-            s->channel_layout = avpriv_ac3_channel_layout_tab[s->output_mode];
+        if (s->channels > 1 &&
+            avctx->request_channel_layout == AV_CH_LAYOUT_MONO) {
+            s->out_channels = 1;
+            s->output_mode  = AC3_CHMODE_MONO;
+        } else if (s->channels > 2 &&
+                   avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
+            s->out_channels = 2;
+            s->output_mode  = AC3_CHMODE_STEREO;
         }
-        avctx->channels       = s->out_channels;
-        avctx->channel_layout = s->channel_layout;
 
         /* set downmixing coefficients if needed */
         if (s->channels != s->out_channels && !((s->output_mode & AC3_OUTPUT_LFEON) &&
@@ -1368,6 +1411,9 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
         return AVERROR_INVALIDDATA;
     }
     avctx->channels = s->out_channels;
+    avctx->channel_layout = avpriv_ac3_channel_layout_tab[s->output_mode & ~AC3_OUTPUT_LFEON];
+    if (s->output_mode & AC3_OUTPUT_LFEON)
+        avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
 
     /* set audio service type based on bitstream mode for AC-3 */
     avctx->audio_service_type = s->bitstream_mode;
@@ -1408,6 +1454,62 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
     for (ch = 0; ch < s->out_channels; ch++)
         memcpy(s->output[ch], output[ch], sizeof(**output) * AC3_BLOCK_SIZE);
 
+    /*
+     * AVMatrixEncoding
+     *
+     * Check whether the input layout is compatible, and make sure we're not
+     * downmixing (else the matrix encoding is no longer applicable).
+     */
+    matrix_encoding = AV_MATRIX_ENCODING_NONE;
+    if (s->channel_mode == AC3_CHMODE_STEREO &&
+        s->channel_mode == (s->output_mode & ~AC3_OUTPUT_LFEON)) {
+        if (s->dolby_surround_mode == AC3_DSURMOD_ON)
+            matrix_encoding = AV_MATRIX_ENCODING_DOLBY;
+        else if (s->dolby_headphone_mode == AC3_DHEADPHONMOD_ON)
+            matrix_encoding = AV_MATRIX_ENCODING_DOLBYHEADPHONE;
+    } else if (s->channel_mode >= AC3_CHMODE_2F2R &&
+               s->channel_mode == (s->output_mode & ~AC3_OUTPUT_LFEON)) {
+        switch (s->dolby_surround_ex_mode) {
+        case AC3_DSUREXMOD_ON: // EX or PLIIx
+            matrix_encoding = AV_MATRIX_ENCODING_DOLBYEX;
+            break;
+        case AC3_DSUREXMOD_PLIIZ:
+            matrix_encoding = AV_MATRIX_ENCODING_DPLIIZ;
+            break;
+        default: // not indicated or off
+            break;
+        }
+    }
+    if ((ret = ff_side_data_update_matrix_encoding(frame, matrix_encoding)) < 0)
+        return ret;
+
+    /* AVDownmixInfo */
+    if ((downmix_info = av_downmix_info_update_side_data(frame))) {
+        switch (s->preferred_downmix) {
+        case AC3_DMIXMOD_LTRT:
+            downmix_info->preferred_downmix_type = AV_DOWNMIX_TYPE_LTRT;
+            break;
+        case AC3_DMIXMOD_LORO:
+            downmix_info->preferred_downmix_type = AV_DOWNMIX_TYPE_LORO;
+            break;
+        case AC3_DMIXMOD_DPLII:
+            downmix_info->preferred_downmix_type = AV_DOWNMIX_TYPE_DPLII;
+            break;
+        default:
+            downmix_info->preferred_downmix_type = AV_DOWNMIX_TYPE_UNKNOWN;
+            break;
+        }
+        downmix_info->center_mix_level        = gain_levels[s->       center_mix_level];
+        downmix_info->center_mix_level_ltrt   = gain_levels[s->  center_mix_level_ltrt];
+        downmix_info->surround_mix_level      = gain_levels[s->     surround_mix_level];
+        downmix_info->surround_mix_level_ltrt = gain_levels[s->surround_mix_level_ltrt];
+        if (s->lfe_mix_level_exists)
+            downmix_info->lfe_mix_level       = gain_levels_lfe[s->lfe_mix_level];
+        else
+            downmix_info->lfe_mix_level       = 0.0; // -inf dB
+    } else
+        return AVERROR(ENOMEM);
+
     *got_frame_ptr = 1;
 
     return FFMIN(buf_size, s->frame_size);
@@ -1428,7 +1530,7 @@ static av_cold int ac3_decode_end(AVCodecContext *avctx)
 #define OFFSET(x) offsetof(AC3DecodeContext, x)
 #define PAR (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM)
 static const AVOption options[] = {
-    { "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 1.0, PAR },
+    { "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 6.0, PAR },
     { NULL},
 };
 
@@ -1448,7 +1550,7 @@ AVCodec ff_ac3_decoder = {
     .init           = ac3_decode_init,
     .close          = ac3_decode_end,
     .decode         = ac3_decode_frame,
-    .capabilities   = CODEC_CAP_DR1,
+    .capabilities   = AV_CODEC_CAP_DR1,
     .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
     .priv_class     = &ac3_decoder_class,
@@ -1471,7 +1573,7 @@ AVCodec ff_eac3_decoder = {
     .init           = ac3_decode_init,
     .close          = ac3_decode_end,
     .decode         = ac3_decode_frame,
-    .capabilities   = CODEC_CAP_DR1,
+    .capabilities   = AV_CODEC_CAP_DR1,
     .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
     .priv_class     = &eac3_decoder_class,