[FFmpeg-devel] [PATCH] aacenc: WIP support for PCEs

pkv.stream pkv.stream at gmail.com
Mon Oct 2 01:40:05 EEST 2017


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

-------------- next part --------------
From 507fa698974fe72d297e01c90396e602de0d42da Mon Sep 17 00:00:00 2001
From: pkviet <pkv.stream at 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



More information about the ffmpeg-devel mailing list