@@ -50,6 +50,40 @@
static AVOnce aac_table_init = AV_ONCE_INIT;
+static void put_pce(PutBitContext *pb, AVCodecContext *avctx)
+{
+ int i, j;
+ AACEncContext *s = avctx->priv_data;
+ AACPCEInfo *pce = &s->pce;
+
+ put_bits(pb, 4, 0);
+
+ put_bits(pb, 2, avctx->profile);
+ put_bits(pb, 4, s->samplerate_index);
+
+ put_bits(pb, 4, pce->num_ele[0]); /* Front */
+ put_bits(pb, 4, pce->num_ele[1]); /* Side */
+ put_bits(pb, 4, pce->num_ele[2]); /* Back */
+ put_bits(pb, 2, pce->num_ele[3]); /* LFE */
+ put_bits(pb, 3, 0); /* Assoc data */
+ put_bits(pb, 4, 0); /* CCs */
+
+ put_bits(pb, 1, 0); /* Stereo mixdown */
+ put_bits(pb, 1, 0); /* Mono mixdown */
+ put_bits(pb, 1, 0); /* Something else */
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < pce->num_ele[i]; j++) {
+ if (i < 3)
+ put_bits(pb, 1, pce->pairing[i][j]);
+ put_bits(pb, 4, pce->index[i][j]);
+ }
+ }
+
+ avpriv_align_put_bits(pb);
+ put_bits(pb, 8, 0);
+}
+
/**
* Make AAC audio config object.
* @see 1.6.2.1 "Syntax - AudioSpecificConfig"
@@ -58,7 +92,7 @@ static void put_audio_specific_config(AVCodecContext *avctx)
{
PutBitContext pb;
AACEncContext *s = avctx->priv_data;
- int channels = s->channels - (s->channels == 8 ? 1 : 0);
+ int channels = (!s->needs_pce)*(s->channels - (s->channels == 8 ? 1 : 0));
init_put_bits(&pb, avctx->extradata, avctx->extradata_size);
put_bits(&pb, 5, s->profile+1); //profile
@@ -68,6 +102,8 @@ static void put_audio_specific_config(AVCodecContext *avctx)
put_bits(&pb, 1, 0); //frame length - 1024 samples
put_bits(&pb, 1, 0); //does not depend on core coder
put_bits(&pb, 1, 0); //is not extension
+ if (s->needs_pce)
+ put_pce(&pb, avctx);
//Explicitly Mark SBR absent
put_bits(&pb, 11, 0x2b7); //sync extension
@@ -488,7 +524,7 @@ static void copy_input_samples(AACEncContext *s, const AVFrame *frame)
{
int ch;
int end = 2048 + (frame ? frame->nb_samples : 0);
- const uint8_t *channel_map = aac_chan_maps[s->channels - 1];
+ const uint8_t *channel_map = s->reorder_map;
/* copy and remap input samples */
for (ch = 0; ch < s->channels; ch++) {
@@ -923,16 +959,36 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
/* Constants */
s->last_frame_pb_count = 0;
- avctx->extradata_size = 5;
+ avctx->extradata_size = 20;
avctx->frame_size = 1024;
avctx->initial_padding = 1024;
s->lambda = avctx->global_quality > 0 ? avctx->global_quality : 120;
/* Channel map and unspecified bitrate guessing */
s->channels = avctx->channels;
- ERROR_IF(s->channels > AAC_MAX_CHANNELS || s->channels == 7,
- "Unsupported number of channels: %d\n", s->channels);
- s->chan_map = aac_chan_configs[s->channels-1];
+
+ s->needs_pce = 1;
+ for (i = 0; i < FF_ARRAY_ELEMS(aac_normal_chan_layouts); i++) {
+ if (avctx->channel_layout == aac_normal_chan_layouts[i]) {
+ s->needs_pce = s->options.pce;
+ break;
+ }
+ }
+
+ if (s->needs_pce) {
+ for (i = 0; i < FF_ARRAY_ELEMS(aac_pce_configs); i++)
+ if (avctx->channel_layout == aac_pce_configs[i].layout)
+ break;
+ ERROR_IF(i == FF_ARRAY_ELEMS(aac_pce_configs), "Unsupported channel layout\n");
+ WARN_IF(1, "Using a PCE!\n");
+ s->pce = aac_pce_configs[i];
+ s->reorder_map = s->pce.reorder_map;
+ s->chan_map = s->pce.config_map;
+ } else {
+ s->reorder_map = aac_chan_maps[s->channels - 1];
+ s->chan_map = aac_chan_configs[s->channels - 1];
+ }
+
if (!avctx->bit_rate) {
for (i = 1; i <= s->chan_map[0]; i++) {
avctx->bit_rate += s->chan_map[i] == TYPE_CPE ? 128000 : /* Pair */
@@ -1059,6 +1115,7 @@ static const AVOption aacenc_options[] = {
{"aac_tns", "Temporal noise shaping", offsetof(AACEncContext, options.tns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
{"aac_ltp", "Long term prediction", offsetof(AACEncContext, options.ltp), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
{"aac_pred", "AAC-Main prediction", offsetof(AACEncContext, options.pred), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
+ {"aac_pce", "Forces the use of PCEs", offsetof(AACEncContext, options.pce), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
{NULL}
};
@@ -46,6 +46,7 @@ typedef struct AACEncOptions {
int pns;
int tns;
int ltp;
+ int pce;
int pred;
int mid_side;
int intensity_stereo;
@@ -90,6 +91,50 @@ typedef struct AACQuantizeBandCostCacheEntry {
uint16_t generation;
} AACQuantizeBandCostCacheEntry;
+typedef struct AACPCEInfo {
+ int64_t layout;
+ int num_ele[4]; ///< front, side, back, lfe
+ int pairing[3][8]; ///< front, side, back
+ int index[4][8]; ///< front, side, back, lfe
+ uint8_t config_map[16]; ///< configs the encoder's channel specific settings
+ uint8_t reorder_map[16]; ///< maps channels from lavc to aac order
+} AACPCEInfo;
+
+static const AACPCEInfo aac_pce_configs[] = {
+ {
+ .layout = AV_CH_LAYOUT_MONO,
+ .num_ele = { 1, 0, 0, 0 },
+ .pairing = { { 0 }, },
+ .index = { { 0 }, },
+ .config_map = { 1, TYPE_SCE, },
+ .reorder_map = { 0 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_STEREO,
+ .num_ele = { 1, 0, 0, 0 },
+ .pairing = { { 1 }, },
+ .index = { { 0 }, },
+ .config_map = { 1, TYPE_CPE, },
+ .reorder_map = { 0, 1 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_SURROUND,
+ .num_ele = { 2, 0, 0, 0 },
+ .pairing = { { 1, 0 }, },
+ .index = { { 0, 1 }, },
+ .config_map = { 2, TYPE_SCE, TYPE_CPE },
+ .reorder_map = { 2, 0, 1 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_4POINT0,
+ .num_ele = { 2, 0, 1, 0 },
+ .pairing = { { 1, 0 }, { 0 }, { 0 }, },
+ .index = { { 0, 1 }, { 0 }, { 0 } },
+ .config_map = { 3, TYPE_SCE, TYPE_CPE, TYPE_SCE },
+ .reorder_map = { 2, 0, 1, 3 },
+ },
+};
+
/**
* AAC encoder context
*/
@@ -101,12 +146,15 @@ typedef struct AACEncContext {
FFTContext mdct128; ///< short (128 samples) frame transform context
AVFloatDSPContext *fdsp;
AVLFG lfg; ///< PRNG needed for PNS
- float *planar_samples[8]; ///< saved preprocessed input
+ AACPCEInfo pce; ///< PCE data, if needed
+ float *planar_samples[16]; ///< saved preprocessed input
int profile; ///< copied from avctx
+ int needs_pce; ///< flag for non-standard layout
LPCContext lpc; ///< used by TNS
int samplerate_index; ///< MPEG-4 samplerate index
int channels; ///< channel count
+ const uint8_t *reorder_map; ///< lavc to aac reorder map
const uint8_t *chan_map; ///< channel configuration map
ChannelElement *cpe; ///< channel elements
@@ -36,13 +36,24 @@
/** Total number of codebooks, including special ones **/
#define CB_TOT_ALL 15
-#define AAC_MAX_CHANNELS 8
+#define AAC_MAX_CHANNELS 16
extern const uint8_t *ff_aac_swb_size_1024[];
extern const int ff_aac_swb_size_1024_len;
extern const uint8_t *ff_aac_swb_size_128[];
extern const int ff_aac_swb_size_128_len;
+/* Supported layouts without using a PCE */
+static const int64_t aac_normal_chan_layouts[7] = {
+ AV_CH_LAYOUT_MONO,
+ AV_CH_LAYOUT_STEREO,
+ AV_CH_LAYOUT_SURROUND,
+ AV_CH_LAYOUT_4POINT0,
+ AV_CH_LAYOUT_5POINT0,
+ AV_CH_LAYOUT_5POINT1,
+ AV_CH_LAYOUT_7POINT1,
+};
+
/** default channel configurations */
static const uint8_t aac_chan_configs[AAC_MAX_CHANNELS][6] = {
{1, TYPE_SCE}, // 1 channel - single channel element