Commit 76b81b10 authored by Rostislav Pehlivanov's avatar Rostislav Pehlivanov

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: 's avatarRostislav Pehlivanov <atomnuker@gmail.com>
parent a1c487e9
......@@ -134,6 +134,7 @@ OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \
aacpsy.o aactab.o \
aacenc_is.o \
aacenc_tns.o \
aacenc_pred.o \
psymodel.o mpeg4audio.o kbdwin.o
OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o
OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o kbdwin.o
......
......@@ -139,6 +139,8 @@ typedef struct PredictorState {
AAC_FLOAT var1;
AAC_FLOAT r0;
AAC_FLOAT r1;
AAC_FLOAT k1;
AAC_FLOAT x_est;
} PredictorState;
#define MAX_PREDICTORS 672
......@@ -181,6 +183,7 @@ typedef struct IndividualChannelStream {
int predictor_present;
int predictor_initialized;
int predictor_reset_group;
int predictor_reset_count[31]; ///< used by encoder to count prediction resets
uint8_t prediction_used[41];
uint8_t window_clipping[8]; ///< set if a certain window is near clipping
float clip_avoidance_factor; ///< set if any window is near clipping to the necessary atennuation factor to avoid it
......@@ -244,6 +247,7 @@ typedef struct SingleChannelElement {
TemporalNoiseShaping tns;
Pulse pulse;
enum BandType band_type[128]; ///< band types
enum BandType orig_band_type[128]; ///< band type backups for undoing prediction
int band_type_run_end[120]; ///< band type run end points
INTFLOAT sf[120]; ///< scalefactors
int sf_idx[128]; ///< scalefactor indices (used by encoder)
......@@ -256,6 +260,7 @@ typedef struct SingleChannelElement {
DECLARE_ALIGNED(32, INTFLOAT, ret_buf)[2048]; ///< PCM output buffer
DECLARE_ALIGNED(16, INTFLOAT, ltp_state)[3072]; ///< time signal for LTP
DECLARE_ALIGNED(32, AAC_FLOAT, pqcoeffs)[1024]; ///< quantization error of coefs (used by encoder)
DECLARE_ALIGNED(32, AAC_FLOAT, prcoeffs)[1024]; ///< Main prediction coefs (used by encoder)
PredictorState predictor_state[MAX_PREDICTORS];
INTFLOAT *ret; ///< PCM output
} SingleChannelElement;
......
......@@ -46,6 +46,7 @@
#include "aacenc_is.h"
#include "aacenc_tns.h"
#include "aacenc_pred.h"
/** Frequency in Hz for lower limit of noise substitution **/
#define NOISE_LOW_LIMIT 4500
......@@ -960,43 +961,63 @@ AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = {
encode_window_bands_info,
quantize_and_encode_band,
encode_tns_info,
encode_main_pred,
adjust_common_prediction,
apply_main_pred,
update_main_pred,
set_special_band_scalefactors,
search_for_pns,
search_for_tns,
search_for_ms,
search_for_is,
search_for_pred,
},
[AAC_CODER_ANMR] = {
search_for_quantizers_anmr,
encode_window_bands_info,
quantize_and_encode_band,
encode_tns_info,
encode_main_pred,
adjust_common_prediction,
apply_main_pred,
update_main_pred,
set_special_band_scalefactors,
search_for_pns,
search_for_tns,
search_for_ms,
search_for_is,
search_for_pred,
},
[AAC_CODER_TWOLOOP] = {
search_for_quantizers_twoloop,
codebook_trellis_rate,
quantize_and_encode_band,
encode_tns_info,
encode_main_pred,
adjust_common_prediction,
apply_main_pred,
update_main_pred,
set_special_band_scalefactors,
search_for_pns,
search_for_tns,
search_for_ms,
search_for_is,
search_for_pred,
},
[AAC_CODER_FAST] = {
search_for_quantizers_fast,
encode_window_bands_info,
quantize_and_encode_band,
encode_tns_info,
encode_main_pred,
adjust_common_prediction,
apply_main_pred,
update_main_pred,
set_special_band_scalefactors,
search_for_pns,
search_for_tns,
search_for_ms,
search_for_is,
search_for_pred,
},
};
......@@ -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}
};
......
......@@ -60,11 +60,16 @@ typedef struct AACCoefficientsEncoder {
void (*quantize_and_encode_band)(struct AACEncContext *s, PutBitContext *pb, const float *in, float *out, int size,
int scale_idx, int cb, const float lambda, int rtz);
void (*encode_tns_info)(struct AACEncContext *s, SingleChannelElement *sce);
void (*encode_main_pred)(struct AACEncContext *s, SingleChannelElement *sce);
void (*adjust_common_prediction)(struct AACEncContext *s, ChannelElement *cpe);
void (*apply_main_pred)(struct AACEncContext *s, SingleChannelElement *sce);
void (*update_main_pred)(struct AACEncContext *s, SingleChannelElement *sce, ChannelElement *cpe);
void (*set_special_band_scalefactors)(struct AACEncContext *s, SingleChannelElement *sce);
void (*search_for_pns)(struct AACEncContext *s, AVCodecContext *avctx, SingleChannelElement *sce);
void (*search_for_tns)(struct AACEncContext *s, SingleChannelElement *sce);
void (*search_for_ms)(struct AACEncContext *s, ChannelElement *cpe);
void (*search_for_is)(struct AACEncContext *s, AVCodecContext *avctx, ChannelElement *cpe);
void (*search_for_pred)(struct AACEncContext *s, SingleChannelElement *sce);
} AACCoefficientsEncoder;
extern AACCoefficientsEncoder ff_aac_coders[];
......
This diff is collapsed.
/*
* AAC encoder main-type prediction
* Copyright (C) 2015 Rostislav Pehlivanov
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* AAC encoder main prediction
* @author Rostislav Pehlivanov ( atomnuker gmail com )
*/
#ifndef AVCODEC_AACENC_PRED_H
#define AVCODEC_AACENC_PRED_H
#include "aacenc.h"
/* Every predictor group needs to get reset at least once in this many frames */
#define PRED_RESET_FRAME_MIN 240
/* Any frame with less than this amount of frames since last reset is ok */
#define PRED_RESET_MIN 128
/* Raise to filter any low frequency artifacts due to prediction */
#define PRED_SFB_START 10
/* Offset for the number of bits to encode normal coefficients */
#define PRICE_OFFSET 440
void apply_main_pred(AACEncContext *s, SingleChannelElement *sce);
void update_main_pred(AACEncContext *s, SingleChannelElement *sce, ChannelElement *cpe);
void adjust_common_prediction(AACEncContext *s, ChannelElement *cpe);
void search_for_pred(AACEncContext *s, SingleChannelElement *sce);
void encode_main_pred(AACEncContext *s, SingleChannelElement *sce);
#endif /* AVCODEC_AACENC_PRED_H */
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