summaryrefslogtreecommitdiff
path: root/libavcodec/aacenc.c
diff options
context:
space:
mode:
authorRostislav Pehlivanov <atomnuker@gmail.com>2015-08-21 19:38:05 +0100
committerRostislav Pehlivanov <atomnuker@gmail.com>2015-08-21 19:38:05 +0100
commit76b81b10d90732a6609522b7b152395ae2c049bb (patch)
tree9bcf7ab1758bd1e1d9d84dcebf3f218e20751ba6 /libavcodec/aacenc.c
parenta1c487e9215c5685f0694ebde5bba07f4a07e95a (diff)
aacenc: implement the complete AAC-Main profile
This commit finalizes AAC-Main profile encoding support by implementing all mandatory and optional tools available in the specifications and current decoders. The AAC-Main profile reqires that prediction support be present (although decoders don't require it to be enabled) for an encoder to be deemed capable of AAC-Main encoding, as well as TNS, PNS and IS, all of which were implemented with previous commits or earlier of this year. Users are encouraged to test the new functionality using either -profile:a aac_main or -aac_pred 1, the former of which will enable the prediction option by default and the latter will change the profile to AAC-Main. No other options shall be changed by enabling either, it's currently up to the users to decide what's best. The current implementation works best using M/S and/or IS, so users are also welcome to enable both options and any other options (TNS, PNS) for maximum quality. Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
Diffstat (limited to 'libavcodec/aacenc.c')
-rw-r--r--libavcodec/aacenc.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c
index 5b05b993c4..0ffa4a23cc 100644
--- a/libavcodec/aacenc.c
+++ b/libavcodec/aacenc.c
@@ -167,7 +167,7 @@ static void put_ics_info(AACEncContext *s, IndividualChannelStream *info)
put_bits(&s->pb, 1, info->use_kb_window[0]);
if (info->window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
put_bits(&s->pb, 6, info->max_sfb);
- put_bits(&s->pb, 1, 0); // no prediction
+ put_bits(&s->pb, 1, !!info->predictor_present);
} else {
put_bits(&s->pb, 4, info->max_sfb);
for (w = 1; w < 8; w++)
@@ -396,8 +396,11 @@ static int encode_individual_channel(AVCodecContext *avctx, AACEncContext *s,
int common_window)
{
put_bits(&s->pb, 8, sce->sf_idx[0]);
- if (!common_window)
+ if (!common_window) {
put_ics_info(s, &sce->ics);
+ if (s->coder->encode_main_pred)
+ s->coder->encode_main_pred(s, sce);
+ }
encode_band_info(s, sce);
encode_scale_factors(avctx, s, sce);
encode_pulses(s, &sce->pulse);
@@ -574,6 +577,8 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
for (ch = 0; ch < chans; ch++) {
sce = &cpe->ch[ch];
coeffs[ch] = sce->coeffs;
+ sce->ics.predictor_present = 0;
+ memset(&sce->ics.prediction_used, 0, sizeof(sce->ics.prediction_used));
memset(&sce->tns, 0, sizeof(TemporalNoiseShaping));
for (w = 0; w < 128; w++)
if (sce->band_type[w] > RESERVED_BT)
@@ -604,8 +609,12 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
s->coder->search_for_pns(s, avctx, sce);
if (s->options.tns && s->coder->search_for_tns)
s->coder->search_for_tns(s, sce);
+ if (s->options.pred && s->coder->search_for_pred)
+ s->coder->search_for_pred(s, sce);
if (sce->tns.present)
tns_mode = 1;
+ if (sce->ics.predictor_present)
+ pred_mode = 1;
}
s->cur_channel = start_ch;
if (s->options.stereo_mode && cpe->common_window) {
@@ -622,14 +631,21 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
s->coder->search_for_is(s, avctx, cpe);
if (cpe->is_mode) is_mode = 1;
}
+ if (s->options.pred && s->coder->adjust_common_prediction)
+ s->coder->adjust_common_prediction(s, cpe);
if (s->coder->set_special_band_scalefactors)
for (ch = 0; ch < chans; ch++)
s->coder->set_special_band_scalefactors(s, &cpe->ch[ch]);
+ if (s->options.pred && s->coder->apply_main_pred)
+ for (ch = 0; ch < chans; ch++)
+ s->coder->apply_main_pred(s, &cpe->ch[ch]);
adjust_frame_information(cpe, chans);
if (chans == 2) {
put_bits(&s->pb, 1, cpe->common_window);
if (cpe->common_window) {
put_ics_info(s, &cpe->ch[0].ics);
+ if (s->coder->encode_main_pred)
+ s->coder->encode_main_pred(s, &cpe->ch[0]);
encode_ms_info(&s->pb, cpe);
if (cpe->ms_mode) ms_mode = 1;
}
@@ -660,6 +676,16 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
} while (1);
+ // update predictor state
+ if (s->options.pred && s->coder->update_main_pred) {
+ for (i = 0; i < s->chan_map[0]; i++) {
+ cpe = &s->cpe[i];
+ for (ch = 0; ch < chans; ch++)
+ s->coder->update_main_pred(s, &cpe->ch[ch],
+ (cpe->common_window && !ch) ? cpe : NULL);
+ }
+ }
+
put_bits(&s->pb, 3, TYPE_END);
flush_put_bits(&s->pb);
avctx->frame_bits = put_bits_count(&s->pb);
@@ -835,6 +861,9 @@ static const AVOption aacenc_options[] = {
{"aac_tns", "Temporal noise shaping", offsetof(AACEncContext, options.tns), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, AACENC_FLAGS, "aac_tns"},
{"disable", "Disable temporal noise shaping", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, INT_MIN, INT_MAX, AACENC_FLAGS, "aac_tns"},
{"enable", "Enable temporal noise shaping", 0, AV_OPT_TYPE_CONST, {.i64 = 1}, INT_MIN, INT_MAX, AACENC_FLAGS, "aac_tns"},
+ {"aac_pred", "AAC-Main prediction", offsetof(AACEncContext, options.pred), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, AACENC_FLAGS, "aac_pred"},
+ {"disable", "Disable AAC-Main prediction", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, INT_MIN, INT_MAX, AACENC_FLAGS, "aac_pred"},
+ {"enable", "Enable AAC-Main prediction", 0, AV_OPT_TYPE_CONST, {.i64 = 1}, INT_MIN, INT_MAX, AACENC_FLAGS, "aac_pred"},
{NULL}
};