Hi atomnuker,
got your PCE working;
my previous issues where index related and were the reasons ffmpeg aac
decoder would issue errors.
So found out:
- index is not reset between groups of front, side, back;
- it runs actually for each type (SCE, CPE, LFE)
- for ffmpeg aac decoder to work, the list of index for a type must be
continuous (and probably start with 0, although the order is arbitrary);
ex: 0 1 2 or 2 0 1 are ok but not 0 4
I've corrected your PCE table accordingly.
I've tested the correctness of the PCE encode for all the layouts listed
in the attachment through the following systematic procedure:
- pcm stream with required number of channels declared with
-channel_layout identical to destination (to avoid any automatic channel
matrixing)
- the encoded file was decoded, channels split into mono streams in the
order of the channels. This allowed me to check the channel orders are
fine as well as the correctness of the aac encode itself.
For channels layouts with LFE starting from 4.1, I have had issues with
the order of the LFE channel. When encoding with PCE, the LFE channel is
always positioned as the last one even if the PCE positions it
elsewhere; the -config_map and -reorder_map options make no difference.
So either these layouts with LFE should be removed from the table; or a
workaround could be to replace the LFE by a SCE. This is not
sub-optimal, in terms of bitrate. But maybe as a convenience to user
this might be ok provisionally, until a real fix is found.
I have no opinion on the matter, but have provided working PCEs for
these layouts with LFE, in case.
I have added two convenience layouts in the PCE table , with 9 and 10
channels. They might be of use for order 2 ambisonics or mixed
ambisonics (of course this assumes the user has ordered his channels in
a meaningful way for a third party software since ffmpeg does not
provide ambisonics information yet).
Also, during the research into this PCE, I uncovered a bug with
-channel_layout option which initially is not passed correctly for
non-default layouts; output filters detect the layout as the default one
(for instance 4.0 instead of quad).
This means there are auto-inserts of unneeded filters remapping the
channels.
For instance when encoding a quad pcm source to aac file with quad
layout with PCE, an auto-insertion of aformat filter remaps quad source
to 4.0.
This completely blows up the aac PCE encode since channel matrixing occurs.
I have a separate patch for that issue (see ticket 6706).
regards
From 507fa698974fe72d297e01c90396e602de0d42da Mon Sep 17 00:00:00 2001
From: pkviet <pkv.str...@gmail.com>
Date: Sun, 24 Sep 2017 16:11:17 +0200
Subject: [PATCH] avcodec/aacenc: PCE for all ffmpeg usual layouts
PCE for all usual layouts listed in channel_layout_map
(channel_layout.c) have been added.
All encodes with PCE are decoded correctly by ffmpeg aac decoder (not
checked with others).
The correctness of the channel positions in the encodes have been checked
by splitting the channels to independent audio tracks.
Two non standard layouts have been added in the PCE for support of 9 and
10 channels, which are useful for ambisonics.
For layouts with LFE, the LFE element has been replaced by a SCE because
the encoder always puts the LFE as last channel, irrespective of
config_map and reorder_map. This is not optimal but it enables these
layouts.
---
libavcodec/aacenc.c | 2 +-
libavcodec/aacenc.h | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 234 insertions(+), 7 deletions(-)
diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c
index 2996996..faa0684 100644
--- a/libavcodec/aacenc.c
+++ b/libavcodec/aacenc.c
@@ -565,7 +565,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket
*avpkt,
return 0;
}
- copy_input_samples(s, frame);
+ copy_input_samples(s, frame);
if (s->psypp)
ff_psy_preprocess(s->psypp, s->planar_samples, s->channels);
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index 346d989..31afd04 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -99,6 +99,33 @@ typedef struct AACPCEInfo {
uint8_t reorder_map[16]; ///< maps channels from lavc
to aac order
} AACPCEInfo;
+/**
+ *List of PCE (Program Configuration Element) for the channel layouts listed
in channel_layout.h
+ *
+ *For those wishing in the future to add other layouts:
+ * - num_ele: number of elements in each group of front, side, back, lfe
channels;
+ * (an element is of type SCE (single channel) , CPE (channel pair) for the
first 3 groups;
+ * and is LFE for LFE group).
+ * - pairing: 0 for an SCE element or 1 for a CPE; does not apply to LFE group
+ * - index: there are three independent indices for SCE, CPE and LFE;
+ * they are incremented irrespective of the group to which the element
belongs;
+ * they are not reset when going from one group to another
+ *
+ * Example: for 7.0 channel layout,
+ * .pairing = { { 1, 0 }, { 1 }, { 1 }, }, (3 CPE and 1 SCE in front
group)
+ * .index = { { 0, 0 }, { 1 }, { 2 }, }, index is 0 for the single SCE
+ * but goes from 0 to 2 for the CPEs .
+ *
+ * The index order impacts the channel ordering. But is otherwise arbitrary
+ * (the sequence could have been 2, 0, 1 instead of 0, 1, 2).
+ * Spec allows discontinuous indices, e.g. if one has a total of two SCE,
SCE.0 SCE.15 is OK per spec;
+ * BUT it won't be decoded by ffmpeg aac decoder which at this time requires
that indices fully cover some range starting from 0.
+ * (SCE.1 SCE.0 is OK but not SCE.0 SCE.15).
+ *
+ * - config_map: total number of elements and their types. Beware, the way the
types are ordered impacts the final channel ordering.
+ * - reorder_map: reorders the channels.
+ *
+ */
static const AACPCEInfo aac_pce_configs[] = {
{
.layout = AV_CH_LAYOUT_MONO,
@@ -117,20 +144,220 @@ static const AACPCEInfo aac_pce_configs[] = {
.reorder_map = { 0, 1 },
},
{
+ .layout = AV_CH_LAYOUT_2POINT1,
+ .num_ele = { 1, 0, 0, 1 },
+ .pairing = { { 1 }, },
+ .index = { { 0 },{ 0 },{ 0 },{ 0 } },
+ .config_map = { 2, TYPE_CPE, TYPE_LFE },
+ .reorder_map = { 0, 1, 2 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_2_1,
+ .num_ele = { 1, 0, 1, 0 },
+ .pairing = { { 1 },{ 0 },{ 0 } },
+ .index = { { 0 },{ 0 },{ 0 }, },
+ .config_map = { 2, TYPE_CPE, TYPE_SCE },
+ .reorder_map = { 0, 1, 2 },
+ },
+ {
.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 },
+ .index = { { 0, 0 }, },
+ .config_map = { 2, TYPE_CPE, TYPE_SCE, },
+ .reorder_map = { 0, 1, 2 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_3POINT1,
+ .num_ele = { 2, 0, 0, 1 },
+ .pairing = { { 1, 0 }, },
+ .index = { { 0, 0 }, { 0 }, { 0 }, { 0 }, },
+ .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_LFE },
+ .reorder_map = { 0, 1, 2, 3 },
},
{
.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 },
+ .index = { { 0, 0 }, { 0 }, { 1 } },
+ .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_SCE },
+ .reorder_map = { 0, 1, 2, 3 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_4POINT1,
+ .num_ele = { 2, 1, 1, 0 },
+ .pairing = { { 1, 0 }, { 0 }, { 0 }, },
+ .index = { { 0, 0 }, { 1 }, { 2 }, { 0 } },
+ .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_SCE },
+ .reorder_map = { 0, 1, 2, 3, 4 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_2_2,
+ .num_ele = { 1, 1, 0, 0 },
+ .pairing = { { 1 }, { 1 }, },
+ .index = { { 0 }, { 1 }, },
+ .config_map = { 2, TYPE_CPE, TYPE_CPE },
+ .reorder_map = { 0, 1, 2, 3 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_QUAD,
+ .num_ele = { 1, 0, 1, 0 },
+ .pairing = { { 1 }, { 0 }, { 1 }, },
+ .index = { { 0 }, { 0 }, { 1 } },
+ .config_map = { 2, TYPE_CPE, TYPE_CPE },
+ .reorder_map = { 0, 1, 2, 3 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_5POINT0,
+ .num_ele = { 2, 1, 0, 0 },
+ .pairing = { { 1, 0 }, { 1 }, },
+ .index = { { 0, 0 }, { 1 } },
+ .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_CPE },
+ .reorder_map = { 0, 1, 2, 3, 4 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_5POINT1,
+ .num_ele = { 2, 1, 1, 0 },
+ .pairing = { { 1, 0 }, { 0 }, { 1 }, },
+ .index = { { 0, 0 }, { 1 }, { 1 } },
+ .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_5POINT0_BACK,
+ .num_ele = { 2, 0, 1, 0 },
+ .pairing = { { 1, 0 }, { 0 }, { 1 } },
+ .index = { { 0, 0 }, { 0 }, { 1 } },
+ .config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_CPE },
+ .reorder_map = { 0, 1, 2, 3, 4 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_5POINT1_BACK,
+ .num_ele = { 2, 1, 1, 0 },
+ .pairing = { { 1, 0 }, { 0 }, { 1 }, },
+ .index = { { 0, 0 }, { 1 }, { 1 } },
+ .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_6POINT0,
+ .num_ele = { 2, 1, 1, 0 },
+ .pairing = { { 1, 0 }, { 1 }, { 0 }, },
+ .index = { { 0, 0 }, { 1 }, { 1 } },
+ .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_6POINT0_FRONT,
+ .num_ele = { 2, 1, 0, 0 },
+ .pairing = { { 1, 1 }, { 1 } },
+ .index = { { 1, 0 }, { 2 }, },
+ .config_map = { 3, TYPE_CPE, TYPE_CPE, TYPE_CPE, },
+ .reorder_map = { 0, 1, 2, 3, 4, 5 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_HEXAGONAL,
+ .num_ele = { 2, 0, 2, 0 },
+ .pairing = { { 1, 0 },{ 0 },{ 1, 0 }, },
+ .index = { { 0, 0 },{ 0 },{ 1, 1 } },
+ .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, },
+ .reorder_map = { 0, 1, 2, 3, 4, 5 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_6POINT1,
+ .num_ele = { 2, 1, 2, 0 },
+ .pairing = { { 1, 0 },{ 0 },{ 1, 0 }, },
+ .index = { { 0, 0 },{ 1 },{ 1, 2 } },
+ .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_6POINT1_BACK,
+ .num_ele = { 2, 1, 2, 0 },
+ .pairing = { { 1, 0 }, { 0 }, { 1, 0 }, },
+ .index = { { 0, 0 }, { 1 }, { 1, 2 } },
+ .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_6POINT1_FRONT,
+ .num_ele = { 2, 1, 2, 0 },
+ .pairing = { { 1, 0 }, { 0 }, { 1, 0 }, },
+ .index = { { 0, 0 }, { 1 }, { 1, 2 } },
+ .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_7POINT0,
+ .num_ele = { 2, 1, 1, 0 },
+ .pairing = { { 1, 0 }, { 1 }, { 1 }, },
+ .index = { { 0, 0 }, { 1 }, { 2 }, },
+ .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_7POINT0_FRONT,
+ .num_ele = { 2, 1, 1, 0 },
+ .pairing = { { 1, 0 }, { 1 }, { 1 }, },
+ .index = { { 0, 0 }, { 1 }, { 2 }, },
+ .config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_7POINT1,
+ .num_ele = { 2, 1, 2, 0 },
+ .pairing = { { 1, 0 }, { 0 }, { 1, 1 }, },
+ .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
+ .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_7POINT1_WIDE,
+ .num_ele = { 2, 1, 2, 0 },
+ .pairing = { { 1, 0 }, { 0 },{ 1, 1 }, },
+ .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
+ .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_7POINT1_WIDE_BACK,
+ .num_ele = { 2, 1, 2, 0 },
+ .pairing = { { 1, 0 }, { 0 }, { 1, 1 }, },
+ .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
+ .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_OCTAGONAL,
+ .num_ele = { 2, 1, 2, 0 },
+ .pairing = { { 1, 0 }, { 1 }, { 1, 0 }, },
+ .index = { { 0, 0 }, { 1 }, { 2, 1 } },
+ .config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
+ },
+ {
+ .layout = 0x00000f37, //FL+FR+FC+BL+BR+BC+SL+SR+TC
+ .num_ele = { 2, 2, 2, 0 },
+ .pairing = { { 1, 0 }, { 1, 0 }, { 1, 0 }, },
+ .index = { { 0, 0 }, { 1, 1 }, { 2, 2 } },
+ .config_map = { 6, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_CPE,
TYPE_SCE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8 },
+ },
+ {
+ .layout = 0x00000ff3, //FL+FR+BL+BR+FLC+FRC+BC+SL+SR+TC
+ .num_ele = { 2, 2, 2, 0 },
+ .pairing = { { 1, 1 }, { 1, 0 }, { 1, 0 }, },
+ .index = { { 0, 1 }, { 2, 0 }, { 3, 1 } },
+ .config_map = { 6, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_CPE,
TYPE_SCE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+ },
+ {
+ .layout = AV_CH_LAYOUT_HEXADECAGONAL,
+ .num_ele = { 4, 2, 4, 0 },
+ .pairing = { { 1, 0, 1, 0 }, { 1, 1 }, { 1, 0, 1, 0 }, },
+ .index = { { 0, 0, 1, 1 }, { 2, 3 }, { 4, 2, 5, 3 } },
+ .config_map = { 10, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_CPE,
TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
+ .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
},
},
};
--
2.10.1.windows.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel