Commit fbf295e2 authored by Rostislav Pehlivanov's avatar Rostislav Pehlivanov

aacenc: support extended channel layouts using PCEs

This commit implements support for PCE (Program Configuration Elements) in the
AAC encoder, and as such allows for encoding of channel layouts not present
in the presets defined by the spec (which only lists the 8 most common ones).

This has been a highly requested feature and is also the first open source encoder
to support this many layouts.

Many thanks to pkviet <pkv.stream@gmail.com> who implemented support for and
verified all channel layouts.
parent 0a771e6b
......@@ -10,6 +10,7 @@ version <next>:
- Raw AMR-NB and AMR-WB demuxers
- TiVo ty/ty+ demuxer
- Intel QSV-accelerated MJPEG encoding
- PCE support for extended channel layouts in the AAC encoder
version 3.4:
......
......@@ -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++) {
......@@ -920,16 +956,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");
av_log(avctx, AV_LOG_INFO, "Using a PCE to encode channel layout\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 */
......@@ -1062,6 +1118,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}
};
......
This diff is collapsed.
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment