---
I'm not 100% sure about 1 change. In output_configure() I moved the call
to sniff_channel_order() to above where the layout map and tags are
saved to ac->oc[1]. Otherwise the final layout map is never saved and
cannot be used to map the AVFrame channel pointers. I don't really know
the full consequences of this change though.

 libavcodec/aac.h    |   11 +---
 libavcodec/aacdec.c |  140 ++++++++++++++++++++++++++++++++++----------------
 libavcodec/aacsbr.c |    6 +--
 3 files changed, 100 insertions(+), 57 deletions(-)

diff --git a/libavcodec/aac.h b/libavcodec/aac.h
index 32baf9d..18f674f 100644
--- a/libavcodec/aac.h
+++ b/libavcodec/aac.h
@@ -237,9 +237,10 @@ typedef struct SingleChannelElement {
     uint8_t zeroes[128];                            ///< band is not coded 
(used by encoder)
     DECLARE_ALIGNED(32, float,   coeffs)[1024];     ///< coefficients for IMDCT
     DECLARE_ALIGNED(32, float,   saved)[1024];      ///< overlap
-    DECLARE_ALIGNED(32, float,   ret)[2048];        ///< PCM output
+    DECLARE_ALIGNED(32, float,   ret_buf)[2048];    ///< PCM output buffer
     DECLARE_ALIGNED(16, float,   ltp_state)[3072];  ///< time signal for LTP
     PredictorState predictor_state[MAX_PREDICTORS];
+    float *ret;                                     ///< PCM output
 } SingleChannelElement;
 
 /**
@@ -263,6 +264,7 @@ typedef struct ChannelElement {
 typedef struct AACContext {
     AVCodecContext *avctx;
     AVFrame frame;
+    int got_frame_buffer;
 
     int is_saved;                 ///< Set if elements have stored overlap 
from previous frame.
     DynamicRangeControl che_drc;
@@ -297,13 +299,6 @@ typedef struct AACContext {
     int random_state;
     /** @} */
 
-    /**
-     * @name Members used for output interleaving
-     * @{
-     */
-    float *output_data[MAX_CHANNELS];                 ///< Points to each 
element's 'ret' buffer (PCM output).
-    /** @} */
-
     DECLARE_ALIGNED(32, float, temp)[128];
 
     OutputConfiguration oc[2];
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 4a6d390..9d3c3b1 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -79,6 +79,7 @@
            Parametric Stereo.
  */
 
+#include "libavutil/audioconvert.h"
 #include "libavutil/float_dsp.h"
 #include "avcodec.h"
 #include "internal.h"
@@ -149,10 +150,10 @@ static av_cold int che_configure(AACContext *ac,
             ff_aac_sbr_ctx_init(ac, &ac->che[type][id]->sbr);
         }
         if (type != TYPE_CCE) {
-            ac->output_data[(*channels)++] = ac->che[type][id]->ch[0].ret;
+            (*channels)++;
             if (type == TYPE_CPE ||
                 (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1)) {
-                ac->output_data[(*channels)++] = ac->che[type][id]->ch[1].ret;
+                (*channels)++;
             }
         }
     } else {
@@ -163,6 +164,64 @@ static av_cold int che_configure(AACContext *ac,
     return 0;
 }
 
+static int frame_configure_elements(AVCodecContext *avctx, int is_init)
+{
+    AACContext *ac = avctx->priv_data;
+    ChannelElement *che;
+    int ch, i, ret;
+    int type, id, pos;
+
+    /* set channel pointers to internal buffers by default */
+    for (type = 0; type < 4; type++) {
+        for (id = 0; id < MAX_ELEM_ID; id++) {
+            che = ac->che[type][id];
+            if (che) {
+                che->ch[0].ret = che->ch[0].ret_buf;
+                che->ch[1].ret = che->ch[1].ret_buf;
+            }
+        }
+    }
+
+    /* if this function was called during initialization, we do not need to
+       call get_buffer() or map output channel pointers */
+    if (is_init)
+        return 0;
+
+    /* get output buffer */
+    if (!ac->got_frame_buffer ||
+        ac->oc[1].channel_layout != ac->frame.channel_layout) {
+        ac->frame.nb_samples = 2048;
+        if ((ret = avctx->get_buffer(avctx, &ac->frame)) < 0) {
+            av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+            return ret;
+        }
+        ac->got_frame_buffer = 1;
+    }
+
+    /* map output channel pointers to AVFrame data */
+    ch = 0;
+    for (i = 0; i < ac->oc[1].layout_map_tags; i++) {
+        type = ac->oc[1].layout_map[i][0];
+        id   = ac->oc[1].layout_map[i][1];
+        pos  = ac->oc[1].layout_map[i][2];
+
+        che  = ac->che[type][id];
+        if (che && pos && type != TYPE_CCE) {
+            if (ch >= avctx->channels)
+                return AVERROR(EINVAL);
+            che->ch[0].ret = (float *)ac->frame.extended_data[ch++];
+            if (type == TYPE_CPE ||
+                (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1)) {
+                if (ch >= avctx->channels)
+                    return AVERROR(EINVAL);
+                che->ch[1].ret = (float *)ac->frame.extended_data[ch++];
+            }
+        }
+    }
+
+    return 0;
+}
+
 struct elem_to_channel {
     uint64_t av_position;
     uint8_t syn_ele;
@@ -378,22 +437,24 @@ static void pop_output_configuration(AACContext *ac) {
  * @return  Returns error status. 0 - OK, !0 - error
  */
 static int output_configure(AACContext *ac,
-                                    uint8_t layout_map[MAX_ELEM_ID*4][3], int 
tags,
-                                    int channel_config, enum OCStatus oc_type)
+                            uint8_t layout_map[MAX_ELEM_ID*4][3], int tags,
+                            int channel_config, enum OCStatus oc_type,
+                            int is_init)
 {
     AVCodecContext *avctx = ac->avctx;
     int i, channels = 0, ret;
     uint64_t layout = 0;
 
+    // Try to sniff a reasonable channel order, otherwise output the
+    // channels in the order the PCE declared them.
+    if (avctx->request_channel_layout != AV_CH_LAYOUT_NATIVE)
+        layout = sniff_channel_order(layout_map, tags);
+
     if (ac->oc[1].layout_map != layout_map) {
         memcpy(ac->oc[1].layout_map, layout_map, tags * sizeof(layout_map[0]));
         ac->oc[1].layout_map_tags = tags;
     }
 
-    // Try to sniff a reasonable channel order, otherwise output the
-    // channels in the order the PCE declared them.
-    if (avctx->request_channel_layout != AV_CH_LAYOUT_NATIVE)
-        layout = sniff_channel_order(layout_map, tags);
     for (i = 0; i < tags; i++) {
         int type =     layout_map[i][0];
         int id =       layout_map[i][1];
@@ -417,6 +478,9 @@ static int output_configure(AACContext *ac,
     avctx->channels = ac->oc[1].channels = channels;
     ac->oc[1].status = oc_type;
 
+    if ((ret = frame_configure_elements(ac->avctx, is_init)) < 0)
+        return ret;
+
     return 0;
 }
 
@@ -457,7 +521,7 @@ static ChannelElement *get_che(AACContext *ac, int type, 
int elem_id)
                                        2) < 0)
             return NULL;
         if (output_configure(ac, layout_map, layout_map_tags,
-                             2, OC_TRIAL_FRAME) < 0)
+                             2, OC_TRIAL_FRAME, 0) < 0)
             return NULL;
 
         ac->oc[1].m4ac.chan_config = 2;
@@ -473,7 +537,7 @@ static ChannelElement *get_che(AACContext *ac, int type, 
int elem_id)
                                        1) < 0)
             return NULL;
         if (output_configure(ac, layout_map, layout_map_tags,
-                             1, OC_TRIAL_FRAME) < 0)
+                             1, OC_TRIAL_FRAME, 0) < 0)
             return NULL;
 
         ac->oc[1].m4ac.chan_config = 1;
@@ -661,7 +725,7 @@ static int decode_ga_specific_config(AACContext *ac, 
AVCodecContext *avctx,
         m4ac->ps = 1;
 
     if (ac && (ret = output_configure(ac, layout_map, tags,
-                                      channel_config, OC_GLOBAL_HDR)))
+                                      channel_config, OC_GLOBAL_HDR, 1)))
         return ret;
 
     if (extension_flag) {
@@ -803,11 +867,12 @@ static void reset_predictor_group(PredictorState *ps, int 
group_num)
 static av_cold int aac_decode_init(AVCodecContext *avctx)
 {
     AACContext *ac = avctx->priv_data;
-    float output_scale_factor;
 
     ac->avctx = avctx;
     ac->oc[1].m4ac.sample_rate = avctx->sample_rate;
 
+    avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
+
     if (avctx->extradata_size > 0) {
         if (decode_audio_specific_config(ac, ac->avctx, &ac->oc[1].m4ac,
                                          avctx->extradata,
@@ -837,20 +902,12 @@ static av_cold int aac_decode_init(AVCodecContext *avctx)
                 &layout_map_tags, ac->oc[1].m4ac.chan_config);
             if (!ret)
                 output_configure(ac, layout_map, layout_map_tags,
-                                 ac->oc[1].m4ac.chan_config, OC_GLOBAL_HDR);
+                                 ac->oc[1].m4ac.chan_config, OC_GLOBAL_HDR, 1);
             else if (avctx->err_recognition & AV_EF_EXPLODE)
                 return AVERROR_INVALIDDATA;
         }
     }
 
-    if (avctx->request_sample_fmt == AV_SAMPLE_FMT_FLT) {
-        avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
-        output_scale_factor = 1.0 / 32768.0;
-    } else {
-        avctx->sample_fmt = AV_SAMPLE_FMT_S16;
-        output_scale_factor = 1.0;
-    }
-
     AAC_INIT_VLC_STATIC( 0, 304);
     AAC_INIT_VLC_STATIC( 1, 270);
     AAC_INIT_VLC_STATIC( 2, 550);
@@ -878,9 +935,9 @@ static av_cold int aac_decode_init(AVCodecContext *avctx)
                     ff_aac_scalefactor_code, 
sizeof(ff_aac_scalefactor_code[0]), sizeof(ff_aac_scalefactor_code[0]),
                     352);
 
-    ff_mdct_init(&ac->mdct,       11, 1, output_scale_factor/1024.0);
-    ff_mdct_init(&ac->mdct_small,  8, 1, output_scale_factor/128.0);
-    ff_mdct_init(&ac->mdct_ltp,   11, 0, -2.0/output_scale_factor);
+    ff_mdct_init(&ac->mdct,       11, 1, 1.0 / (32768.0 * 1024.0));
+    ff_mdct_init(&ac->mdct_small,  8, 1, 1.0 / (32768.0 * 128.0));
+    ff_mdct_init(&ac->mdct_ltp,   11, 0, -2.0 * 32768.0);
     // window initialization
     ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024);
     ff_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128);
@@ -1943,7 +2000,7 @@ static int decode_extension_payload(AACContext *ac, 
GetBitContext *gb, int cnt,
             ac->oc[1].m4ac.sbr = 1;
             ac->oc[1].m4ac.ps = 1;
             output_configure(ac, ac->oc[1].layout_map, 
ac->oc[1].layout_map_tags,
-                             ac->oc[1].m4ac.chan_config, ac->oc[1].status);
+                             ac->oc[1].m4ac.chan_config, ac->oc[1].status, 0);
         } else {
             ac->oc[1].m4ac.sbr = 1;
         }
@@ -2334,7 +2391,7 @@ static int parse_adts_frame_header(AACContext *ac, 
GetBitContext *gb)
                 return -7;
             if (output_configure(ac, layout_map, layout_map_tags,
                                  hdr_info.chan_config,
-                                 FFMAX(ac->oc[1].status, OC_TRIAL_FRAME)))
+                                 FFMAX(ac->oc[1].status, OC_TRIAL_FRAME), 0))
                 return -7;
         } else {
             ac->oc[1].m4ac.chan_config = 0;
@@ -2376,6 +2433,11 @@ static int aac_decode_frame_int(AVCodecContext *avctx, 
void *data,
         }
     }
 
+    if (frame_configure_elements(avctx, 0) < 0) {
+        err = -1;
+        goto fail;
+    }
+
     ac->tags_mapped = 0;
     // parse
     while ((elem_type = get_bits(gb, 3)) != TYPE_END) {
@@ -2430,7 +2492,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, 
void *data,
                        "Not evaluating a further program_config_element as 
this construct is dubious at best.\n");
                 pop_output_configuration(ac);
             } else {
-                err = output_configure(ac, layout_map, tags, 0, OC_TRIAL_PCE);
+                err = output_configure(ac, layout_map, tags, 0, OC_TRIAL_PCE, 
0);
                 pce_found = 1;
             }
             break;
@@ -2473,23 +2535,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, 
void *data,
     samples <<= multiplier;
 
     if (samples) {
-        /* get output buffer */
         ac->frame.nb_samples = samples;
-        if ((err = avctx->get_buffer(avctx, &ac->frame)) < 0) {
-            av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
-            err = -1;
-            goto fail;
-        }
-
-        if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT)
-            ac->fmt_conv.float_interleave((float *)ac->frame.data[0],
-                                          (const float **)ac->output_data,
-                                          samples, avctx->channels);
-        else
-            ac->fmt_conv.float_to_int16_interleave((int16_t 
*)ac->frame.data[0],
-                                                   (const float 
**)ac->output_data,
-                                                   samples, avctx->channels);
-
         *(AVFrame *)data = ac->frame;
     }
     *got_frame_ptr = !!samples;
@@ -2521,6 +2567,8 @@ static int aac_decode_frame(AVCodecContext *avctx, void 
*data,
                                        AV_PKT_DATA_NEW_EXTRADATA,
                                        &new_extradata_size);
 
+    ac->got_frame_buffer = 0;
+
     if (new_extradata) {
         av_free(avctx->extradata);
         avctx->extradata = av_mallocz(new_extradata_size +
@@ -2783,6 +2831,8 @@ static int latm_decode_frame(AVCodecContext *avctx, void 
*out,
     int                 muxlength, err;
     GetBitContext       gb;
 
+    latmctx->aac_ctx.got_frame_buffer = 0;
+
     init_get_bits(&gb, avpkt->data, avpkt->size * 8);
 
     // check for LOAS sync word
@@ -2848,7 +2898,7 @@ AVCodec ff_aac_decoder = {
     .decode          = aac_decode_frame,
     .long_name       = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"),
     .sample_fmts     = (const enum AVSampleFormat[]) {
-        AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE
+        AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE
     },
     .capabilities    = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1,
     .channel_layouts = aac_channel_layout,
@@ -2869,7 +2919,7 @@ AVCodec ff_aac_latm_decoder = {
     .decode          = latm_decode_frame,
     .long_name       = NULL_IF_CONFIG_SMALL("AAC LATM (Advanced Audio Coding 
LATM syntax)"),
     .sample_fmts     = (const enum AVSampleFormat[]) {
-        AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE
+        AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE
     },
     .capabilities    = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1,
     .channel_layouts = aac_channel_layout,
diff --git a/libavcodec/aacsbr.c b/libavcodec/aacsbr.c
index 5eca115..c1133d8 100644
--- a/libavcodec/aacsbr.c
+++ b/libavcodec/aacsbr.c
@@ -140,7 +140,6 @@ static void sbr_turnoff(SpectralBandReplication *sbr) {
 
 av_cold void ff_aac_sbr_ctx_init(AACContext *ac, SpectralBandReplication *sbr)
 {
-    float mdct_scale;
     sbr->kx[0] = sbr->kx[1];
     sbr_turnoff(sbr);
     sbr->data[0].synthesis_filterbank_samples_offset = SBR_SYNTHESIS_BUF_SIZE 
- (1280 - 128);
@@ -148,9 +147,8 @@ av_cold void ff_aac_sbr_ctx_init(AACContext *ac, 
SpectralBandReplication *sbr)
     /* SBR requires samples to be scaled to +/-32768.0 to work correctly.
      * mdct scale factors are adjusted to scale up from +/-1.0 at analysis
      * and scale back down at synthesis. */
-    mdct_scale = ac->avctx->sample_fmt == AV_SAMPLE_FMT_FLT ? 32768.0f : 1.0f;
-    ff_mdct_init(&sbr->mdct,     7, 1, 1.0 / (64 * mdct_scale));
-    ff_mdct_init(&sbr->mdct_ana, 7, 1, -2.0 * mdct_scale);
+    ff_mdct_init(&sbr->mdct,     7, 1, 1.0 / (64 * 32768.0));
+    ff_mdct_init(&sbr->mdct_ana, 7, 1, -2.0 * 32768.0);
     ff_ps_ctx_init(&sbr->ps);
     ff_sbrdsp_init(&sbr->dsp);
 }
-- 
1.7.1

_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to