Skip to content

Commit

Permalink
aac: convert to new channel layout API
Browse files Browse the repository at this point in the history
Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com>
Signed-off-by: Anton Khirnov <anton@khirnov.net>
Signed-off-by: James Almer <jamrial@gmail.com>
  • Loading branch information
elenril authored and jamrial committed Mar 15, 2022
1 parent 2350a50 commit 494760f
Show file tree
Hide file tree
Showing 14 changed files with 154 additions and 79 deletions.
11 changes: 9 additions & 2 deletions libavcodec/aac.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@


#include "aac_defines.h"
#include "libavutil/channel_layout.h"
#include "libavutil/float_dsp.h"
#include "libavutil/fixed_dsp.h"
#include "libavutil/mem_internal.h"
Expand Down Expand Up @@ -125,8 +126,7 @@ typedef struct OutputConfiguration {
MPEG4AudioConfig m4ac;
uint8_t layout_map[MAX_ELEM_ID*4][3];
int layout_map_tags;
int channels;
uint64_t channel_layout;
AVChannelLayout ch_layout;
enum OCStatus status;
} OutputConfiguration;

Expand Down Expand Up @@ -288,6 +288,11 @@ typedef struct ChannelElement {
SpectralBandReplication sbr;
} ChannelElement;

enum AACOutputChannelOrder {
CHANNEL_ORDER_DEFAULT,
CHANNEL_ORDER_CODED,
};

/**
* main AAC context
*/
Expand Down Expand Up @@ -352,6 +357,8 @@ struct AACContext {
int dmono_mode; ///< 0->not dmono, 1->use first channel, 2->use second channel
/** @} */

enum AACOutputChannelOrder output_channel_order;

DECLARE_ALIGNED(32, INTFLOAT, temp)[128];

OutputConfiguration oc[2];
Expand Down
9 changes: 7 additions & 2 deletions libavcodec/aac_ac3_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,13 @@ int ff_aac_ac3_parse(AVCodecParserContext *s1,
if (avctx->codec_id != AV_CODEC_ID_AAC) {
avctx->sample_rate = s->sample_rate;
if (!CONFIG_EAC3_DECODER || avctx->codec_id != AV_CODEC_ID_EAC3) {
avctx->channels = s->channels;
avctx->channel_layout = s->channel_layout;
av_channel_layout_uninit(&avctx->ch_layout);
if (s->channel_layout) {
av_channel_layout_from_mask(&avctx->ch_layout, s->channel_layout);
} else {
avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
avctx->ch_layout.nb_channels = s->channels;
}
}
s1->duration = s->samples;
avctx->audio_service_type = s->service_type;
Expand Down
10 changes: 5 additions & 5 deletions libavcodec/aaccoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ static void search_for_quantizers_fast(AVCodecContext *avctx, AACEncContext *s,
const float lambda)
{
int start = 0, i, w, w2, g;
int destbits = avctx->bit_rate * 1024.0 / avctx->sample_rate / avctx->channels * (lambda / 120.f);
int destbits = avctx->bit_rate * 1024.0 / avctx->sample_rate / avctx->ch_layout.nb_channels * (lambda / 120.f);
float dists[128] = { 0 }, uplims[128] = { 0 };
float maxvals[128];
int fflag, minscaler;
Expand Down Expand Up @@ -556,15 +556,15 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne
const float pns_transient_energy_r = FFMIN(0.7f, lambda / 140.f);

int refbits = avctx->bit_rate * 1024.0 / avctx->sample_rate
/ ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->channels)
/ ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->ch_layout.nb_channels)
* (lambda / 120.f);

/** Keep this in sync with twoloop's cutoff selection */
float rate_bandwidth_multiplier = 1.5f;
int prev = -1000, prev_sf = -1;
int frame_bit_rate = (avctx->flags & AV_CODEC_FLAG_QSCALE)
? (refbits * rate_bandwidth_multiplier * avctx->sample_rate / 1024)
: (avctx->bit_rate / avctx->channels);
: (avctx->bit_rate / avctx->ch_layout.nb_channels);

frame_bit_rate *= 1.15f;

Expand Down Expand Up @@ -693,14 +693,14 @@ static void mark_pns(AACEncContext *s, AVCodecContext *avctx, SingleChannelEleme
const float pns_transient_energy_r = FFMIN(0.7f, lambda / 140.f);

int refbits = avctx->bit_rate * 1024.0 / avctx->sample_rate
/ ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->channels)
/ ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->ch_layout.nb_channels)
* (lambda / 120.f);

/** Keep this in sync with twoloop's cutoff selection */
float rate_bandwidth_multiplier = 1.5f;
int frame_bit_rate = (avctx->flags & AV_CODEC_FLAG_QSCALE)
? (refbits * rate_bandwidth_multiplier * avctx->sample_rate / 1024)
: (avctx->bit_rate / avctx->channels);
: (avctx->bit_rate / avctx->ch_layout.nb_channels);

frame_bit_rate *= 1.15f;

Expand Down
4 changes: 2 additions & 2 deletions libavcodec/aaccoder_twoloop.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
{
int start = 0, i, w, w2, g, recomprd;
int destbits = avctx->bit_rate * 1024.0 / avctx->sample_rate
/ ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->channels)
/ ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->ch_layout.nb_channels)
* (lambda / 120.f);
int refbits = destbits;
int toomanybits, toofewbits;
Expand Down Expand Up @@ -186,7 +186,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
float rate_bandwidth_multiplier = 1.5f;
int frame_bit_rate = (avctx->flags & AV_CODEC_FLAG_QSCALE)
? (refbits * rate_bandwidth_multiplier * avctx->sample_rate / 1024)
: (avctx->bit_rate / avctx->channels);
: (avctx->bit_rate / avctx->ch_layout.nb_channels);

/** Compensate for extensions that increase efficiency */
if (s->options.pns || s->options.intensity_stereo)
Expand Down
6 changes: 6 additions & 0 deletions libavcodec/aacdec.c
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,10 @@ const AVCodec ff_aac_decoder = {
},
.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
#if FF_API_OLD_CHANNEL_LAYOUT
.channel_layouts = aac_channel_layout,
#endif
.ch_layouts = aac_ch_layout,
.flush = flush,
.priv_class = &aac_decoder_class,
.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
Expand All @@ -591,7 +594,10 @@ const AVCodec ff_aac_latm_decoder = {
},
.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
#if FF_API_OLD_CHANNEL_LAYOUT
.channel_layouts = aac_channel_layout,
#endif
.ch_layouts = aac_ch_layout,
.flush = flush,
.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
};
3 changes: 3 additions & 0 deletions libavcodec/aacdec_fixed.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,10 @@ const AVCodec ff_aac_fixed_decoder = {
},
.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
#if FF_API_OLD_CHANNEL_LAYOUT
.channel_layouts = aac_channel_layout,
#endif
.ch_layouts = aac_ch_layout,
.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
.flush = flush,
};
59 changes: 44 additions & 15 deletions libavcodec/aacdec_template.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,15 @@ static int frame_configure_elements(AVCodecContext *avctx)

/* get output buffer */
av_frame_unref(ac->frame);
if (!avctx->channels)
if (!avctx->ch_layout.nb_channels)
return 1;

ac->frame->nb_samples = 2048;
if ((ret = ff_get_buffer(avctx, ac->frame, 0)) < 0)
return ret;

/* map output channel pointers to AVFrame data */
for (ch = 0; ch < avctx->channels; ch++) {
for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
if (ac->output_element[ch])
ac->output_element[ch]->ret = (INTFLOAT *)ac->frame->extended_data[ch];
}
Expand Down Expand Up @@ -517,8 +517,7 @@ static int push_output_configuration(AACContext *ac) {
static void pop_output_configuration(AACContext *ac) {
if (ac->oc[1].status != OC_LOCKED && ac->oc[0].status != OC_NONE) {
ac->oc[1] = ac->oc[0];
ac->avctx->channels = ac->oc[1].channels;
ac->avctx->channel_layout = ac->oc[1].channel_layout;
ac->avctx->ch_layout = ac->oc[1].ch_layout;
output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags,
ac->oc[1].status, 0);
}
Expand Down Expand Up @@ -555,7 +554,14 @@ static int output_configure(AACContext *ac,
}
// 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)
#if FF_API_OLD_CHANNEL_LAYOUT
FF_DISABLE_DEPRECATION_WARNINGS
if (avctx->request_channel_layout == AV_CH_LAYOUT_NATIVE)
ac->output_channel_order = CHANNEL_ORDER_CODED;
FF_ENABLE_DEPRECATION_WARNINGS
#endif

if (ac->output_channel_order == CHANNEL_ORDER_DEFAULT)
layout = sniff_channel_order(layout_map, tags);
for (i = 0; i < tags; i++) {
int type = layout_map[i][0];
Expand All @@ -577,9 +583,22 @@ static int output_configure(AACContext *ac,
}
}

if (layout) avctx->channel_layout = layout;
ac->oc[1].channel_layout = layout;
avctx->channels = ac->oc[1].channels = channels;
av_channel_layout_uninit(&ac->oc[1].ch_layout);
if (layout)
av_channel_layout_from_mask(&ac->oc[1].ch_layout, layout);
else {
ac->oc[1].ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
ac->oc[1].ch_layout.nb_channels = channels;
}

av_channel_layout_copy(&avctx->ch_layout, &ac->oc[1].ch_layout);
#if FF_API_OLD_CHANNEL_LAYOUT
FF_DISABLE_DEPRECATION_WARNINGS
avctx->channels = avctx->ch_layout.nb_channels;
avctx->channel_layout = avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ?
avctx->ch_layout.u.mask : 0;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
ac->oc[1].status = oc_type;

if (get_new_frame) {
Expand Down Expand Up @@ -1292,12 +1311,12 @@ static av_cold int aac_decode_init(AVCodecContext *avctx)

sr = sample_rate_idx(avctx->sample_rate);
ac->oc[1].m4ac.sampling_index = sr;
ac->oc[1].m4ac.channels = avctx->channels;
ac->oc[1].m4ac.channels = avctx->ch_layout.nb_channels;
ac->oc[1].m4ac.sbr = -1;
ac->oc[1].m4ac.ps = -1;

for (i = 0; i < FF_ARRAY_ELEMS(ff_mpeg4audio_channels); i++)
if (ff_mpeg4audio_channels[i] == avctx->channels)
if (ff_mpeg4audio_channels[i] == avctx->ch_layout.nb_channels)
break;
if (i == FF_ARRAY_ELEMS(ff_mpeg4audio_channels)) {
i = 0;
Expand All @@ -1315,7 +1334,7 @@ static av_cold int aac_decode_init(AVCodecContext *avctx)
}
}

if (avctx->channels > MAX_CHANNELS) {
if (avctx->ch_layout.nb_channels > MAX_CHANNELS) {
av_log(avctx, AV_LOG_ERROR, "Too many channels\n");
return AVERROR_INVALIDDATA;
}
Expand Down Expand Up @@ -2556,7 +2575,8 @@ static int decode_extension_payload(AACContext *ac, GetBitContext *gb, int cnt,
av_log(ac->avctx, AV_LOG_ERROR, "Implicit SBR was found with a first occurrence after the first frame.\n");
skip_bits_long(gb, 8 * cnt - 4);
return res;
} else if (ac->oc[1].m4ac.ps == -1 && ac->oc[1].status < OC_LOCKED && ac->avctx->channels == 1) {
} else if (ac->oc[1].m4ac.ps == -1 && ac->oc[1].status < OC_LOCKED &&
ac->avctx->ch_layout.nb_channels == 1) {
ac->oc[1].m4ac.sbr = 1;
ac->oc[1].m4ac.ps = 1;
ac->avctx->profile = FF_PROFILE_AAC_HE_V2;
Expand Down Expand Up @@ -3264,7 +3284,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
if (avctx->debug & FF_DEBUG_STARTCODE)
av_log(avctx, AV_LOG_DEBUG, "Elem type:%x id:%x\n", elem_type, elem_id);

if (!avctx->channels && elem_type != TYPE_PCE) {
if (!avctx->ch_layout.nb_channels && elem_type != TYPE_PCE) {
err = AVERROR_INVALIDDATA;
goto fail;
}
Expand Down Expand Up @@ -3385,7 +3405,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
}
}

if (!avctx->channels) {
if (!avctx->ch_layout.nb_channels) {
*got_frame_ptr = 0;
return 0;
}
Expand Down Expand Up @@ -3419,7 +3439,8 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data,

/* for dual-mono audio (SCE + SCE) */
is_dmono = ac->dmono_mode && sce_count == 2 &&
ac->oc[1].channel_layout == (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT);
!av_channel_layout_compare(&ac->oc[1].ch_layout,
&(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO);
if (is_dmono) {
if (ac->dmono_mode == 1)
((AVFrame *)data)->data[1] =((AVFrame *)data)->data[0];
Expand Down Expand Up @@ -3553,6 +3574,14 @@ static const AVOption options[] = {
{"sub" , "Select Sub/Right channel", 0, AV_OPT_TYPE_CONST, {.i64= 2}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"},
{"both", "Select both channels", 0, AV_OPT_TYPE_CONST, {.i64= 0}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"},

{ "channel_order", "Order in which the channels are to be exported",
offsetof(AACContext, output_channel_order), AV_OPT_TYPE_INT,
{ .i64 = CHANNEL_ORDER_DEFAULT }, 0, 1, AACDEC_FLAGS, "channel_order" },
{ "default", "normal libavcodec channel order", 0, AV_OPT_TYPE_CONST,
{ .i64 = CHANNEL_ORDER_DEFAULT }, .flags = AACDEC_FLAGS, "channel_order" },
{ "coded", "order in which the channels are coded in the bitstream",
0, AV_OPT_TYPE_CONST, { .i64 = CHANNEL_ORDER_CODED }, .flags = AACDEC_FLAGS, "channel_order" },

{NULL},
};

Expand Down
20 changes: 20 additions & 0 deletions libavcodec/aacdectab.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ static const uint8_t aac_channel_layout_map[16][16][3] = {
/* TODO: Add 7+1 TOP configuration */
};

#if FF_API_OLD_CHANNEL_LAYOUT
static const uint64_t aac_channel_layout[16] = {
AV_CH_LAYOUT_MONO,
AV_CH_LAYOUT_STEREO,
Expand All @@ -89,5 +90,24 @@ static const uint64_t aac_channel_layout[16] = {
0,
/* AV_CH_LAYOUT_7POINT1_TOP, */
};
#endif

static const AVChannelLayout aac_ch_layout[16] = {
AV_CHANNEL_LAYOUT_MONO,
AV_CHANNEL_LAYOUT_STEREO,
AV_CHANNEL_LAYOUT_SURROUND,
AV_CHANNEL_LAYOUT_4POINT0,
AV_CHANNEL_LAYOUT_5POINT0_BACK,
AV_CHANNEL_LAYOUT_5POINT1_BACK,
AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK,
{ 0 },
{ 0 },
{ 0 },
AV_CHANNEL_LAYOUT_6POINT1,
AV_CHANNEL_LAYOUT_7POINT1,
AV_CHANNEL_LAYOUT_22POINT2,
{ 0 },
/* AV_CHANNEL_LAYOUT_7POINT1_TOP, */
};

#endif /* AVCODEC_AACDECTAB_H */
13 changes: 8 additions & 5 deletions libavcodec/aacenc.c
Original file line number Diff line number Diff line change
Expand Up @@ -962,11 +962,11 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
s->lambda = avctx->global_quality > 0 ? avctx->global_quality : 120;

/* Channel map and unspecified bitrate guessing */
s->channels = avctx->channels;
s->channels = avctx->ch_layout.nb_channels;

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]) {
if (!av_channel_layout_compare(&avctx->ch_layout, &aac_normal_chan_layouts[i])) {
s->needs_pce = s->options.pce;
break;
}
Expand All @@ -975,10 +975,13 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
if (s->needs_pce) {
char buf[64];
for (i = 0; i < FF_ARRAY_ELEMS(aac_pce_configs); i++)
if (avctx->channel_layout == aac_pce_configs[i].layout)
if (!av_channel_layout_compare(&avctx->ch_layout, &aac_pce_configs[i].layout))
break;
av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout);
ERROR_IF(i == FF_ARRAY_ELEMS(aac_pce_configs), "Unsupported channel layout \"%s\"\n", buf);
av_channel_layout_describe(&avctx->ch_layout, buf, sizeof(buf));
if (i == FF_ARRAY_ELEMS(aac_pce_configs)) {
av_log(avctx, AV_LOG_ERROR, "Unsupported channel layout \"%s\"\n", buf);
return AVERROR(EINVAL);
}
av_log(avctx, AV_LOG_INFO, "Using a PCE to encode channel layout \"%s\"\n", buf);
s->pce = aac_pce_configs[i];
s->reorder_map = s->pce.reorder_map;
Expand Down

0 comments on commit 494760f

Please sign in to comment.