Coverage Report

Created: 2026-07-25 07:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavformat/mov_chan.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2011 Justin Ruggles
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
/**
22
 * mov 'chan' tag reading/writing.
23
 * @author Justin Ruggles
24
 */
25
26
#include <assert.h>
27
#include <stdint.h>
28
29
#include "libavutil/avassert.h"
30
#include "libavutil/channel_layout.h"
31
#include "libavutil/mem.h"
32
#include "libavcodec/codec_id.h"
33
#include "mov_chan.h"
34
35
enum {
36
    c_L      = AV_CHAN_FRONT_LEFT,
37
    c_R      = AV_CHAN_FRONT_RIGHT,
38
    c_C      = AV_CHAN_FRONT_CENTER,
39
    c_LFE    = AV_CHAN_LOW_FREQUENCY,
40
    c_Rls    = AV_CHAN_BACK_LEFT,
41
    c_Rrs    = AV_CHAN_BACK_RIGHT,
42
    c_Lc     = AV_CHAN_FRONT_LEFT_OF_CENTER,
43
    c_Rc     = AV_CHAN_FRONT_RIGHT_OF_CENTER,
44
    c_Cs     = AV_CHAN_BACK_CENTER,
45
    c_Ls     = AV_CHAN_SIDE_LEFT,
46
    c_Rs     = AV_CHAN_SIDE_RIGHT,
47
    c_Ts     = AV_CHAN_TOP_CENTER,
48
    c_Vhl    = AV_CHAN_TOP_FRONT_LEFT,
49
    c_Vhc    = AV_CHAN_TOP_FRONT_CENTER,
50
    c_Vhr    = AV_CHAN_TOP_FRONT_RIGHT,
51
    c_Rlt    = AV_CHAN_TOP_BACK_LEFT,
52
    //       = AV_CHAN_TOP_BACK_CENTER,
53
    c_Rrt    = AV_CHAN_TOP_BACK_RIGHT,
54
    c_Lt     = AV_CHAN_STEREO_LEFT,
55
    c_Rt     = AV_CHAN_STEREO_RIGHT,
56
    c_Lw     = AV_CHAN_WIDE_LEFT,
57
    c_Rw     = AV_CHAN_WIDE_RIGHT,
58
    c_Lsd    = AV_CHAN_SURROUND_DIRECT_LEFT,
59
    c_Rsd    = AV_CHAN_SURROUND_DIRECT_RIGHT,
60
    c_LFE2   = AV_CHAN_LOW_FREQUENCY_2,
61
    //       = AV_CHAN_TOP_SIDE_LEFT,
62
    //       = AV_CHAN_TOP_SIDE_RIGHT,
63
    //       = AV_CHAN_BOTTOM_FRONT_CENTER,
64
    //       = AV_CHAN_BOTTOM_FRONT_LEFT,
65
    //       = AV_CHAN_BOTTOM_FRONT_RIGHT,
66
    c_W      = AV_CHAN_AMBISONIC_BASE,
67
    c_Y      = AV_CHAN_AMBISONIC_BASE + 1,
68
    c_Z      = AV_CHAN_AMBISONIC_BASE + 2,
69
    c_X      = AV_CHAN_AMBISONIC_BASE + 3,
70
    /* The following have no exact counterparts */
71
    c_LFE1   = AV_CHAN_LOW_FREQUENCY,
72
    c_Csd    = AV_CHAN_NONE,
73
    c_HI     = AV_CHAN_NONE,
74
    c_VI     = AV_CHAN_NONE,
75
    c_Haptic = AV_CHAN_NONE,
76
};
77
78
enum {
79
    iso_L    = AV_CHAN_FRONT_LEFT,
80
    iso_R    = AV_CHAN_FRONT_RIGHT,
81
    iso_C    = AV_CHAN_FRONT_CENTER,
82
    iso_LFE  = AV_CHAN_LOW_FREQUENCY,
83
    iso_Lsr  = AV_CHAN_BACK_LEFT,
84
    iso_Rsr  = AV_CHAN_BACK_RIGHT,
85
    iso_Lc   = AV_CHAN_FRONT_LEFT_OF_CENTER,
86
    iso_Rc   = AV_CHAN_FRONT_RIGHT_OF_CENTER,
87
    iso_Cs   = AV_CHAN_BACK_CENTER,
88
    iso_Ls   = AV_CHAN_SIDE_LEFT,
89
    iso_Rs   = AV_CHAN_SIDE_RIGHT,
90
    iso_Ts   = AV_CHAN_TOP_CENTER,
91
    iso_Lv   = AV_CHAN_TOP_FRONT_LEFT,
92
    iso_Cv   = AV_CHAN_TOP_FRONT_CENTER,
93
    iso_Rv   = AV_CHAN_TOP_FRONT_RIGHT,
94
    iso_Lvr  = AV_CHAN_TOP_BACK_LEFT,
95
    iso_Cvr  = AV_CHAN_TOP_BACK_CENTER,
96
    iso_Rvr  = AV_CHAN_TOP_BACK_RIGHT,
97
    //       = AV_CHAN_STEREO_LEFT,
98
    //       = AV_CHAN_STEREO_RIGHT,
99
    iso_Lw   = AV_CHAN_WIDE_LEFT,
100
    iso_Rw   = AV_CHAN_WIDE_RIGHT,
101
    iso_Lsd  = AV_CHAN_SURROUND_DIRECT_LEFT,
102
    iso_Rsd  = AV_CHAN_SURROUND_DIRECT_RIGHT,
103
    iso_LFE2 = AV_CHAN_LOW_FREQUENCY_2,
104
    iso_Lvss = AV_CHAN_TOP_SIDE_LEFT,
105
    iso_Rvss = AV_CHAN_TOP_SIDE_RIGHT,
106
    iso_Cb   = AV_CHAN_BOTTOM_FRONT_CENTER,
107
    iso_Lb   = AV_CHAN_BOTTOM_FRONT_LEFT,
108
    iso_Rb   = AV_CHAN_BOTTOM_FRONT_RIGHT,
109
    iso_Lss  = AV_CHAN_SIDE_SURROUND_LEFT,
110
    iso_Rss  = AV_CHAN_SIDE_SURROUND_RIGHT,
111
    /* The following have no exact counterparts */
112
    iso_Lvs  = AV_CHAN_NONE,
113
    iso_Rvs  = AV_CHAN_NONE,
114
};
115
116
struct MovChannelLayoutMap {
117
    union {
118
        uint32_t tag;
119
        enum AVChannel id;
120
    };
121
};
122
123
#define TAG(_tag, _cnt)                                    {.tag = _tag}
124
#define ID(_0)                                             {.id = c_##_0}
125
#define CHLIST01(_tag, _1)                                 CHLIST(_tag, 1, ID(_1))
126
#define CHLIST02(_tag, _1, _2)                             CHLIST(_tag, 2, ID(_1), ID(_2))
127
#define CHLIST03(_tag, _1, _2, _3)                         CHLIST(_tag, 3, ID(_1), ID(_2), ID(_3))
128
#define CHLIST04(_tag, _1, _2, _3, _4)                     CHLIST(_tag, 4, ID(_1), ID(_2), ID(_3), ID(_4))
129
#define CHLIST05(_tag, _1, _2, _3, _4, _5)                 CHLIST(_tag, 5, ID(_1), ID(_2), ID(_3), ID(_4), ID(_5))
130
#define CHLIST06(_tag, _1, _2, _3, _4, _5, _6)             CHLIST(_tag, 6, ID(_1), ID(_2), ID(_3), ID(_4), ID(_5), ID(_6))
131
#define CHLIST07(_tag, _1, _2, _3, _4, _5, _6, _7)         CHLIST(_tag, 7, ID(_1), ID(_2), ID(_3), ID(_4), ID(_5), ID(_6), ID(_7))
132
#define CHLIST08(_tag, _1, _2, _3, _4, _5, _6, _7, _8)     CHLIST(_tag, 8, ID(_1), ID(_2), ID(_3), ID(_4), ID(_5), ID(_6), ID(_7), ID(_8))
133
#define CHLIST09(_tag, _1, _2, _3, _4, _5, _6, _7, _8, _9) CHLIST(_tag, 9, ID(_1), ID(_2), ID(_3), ID(_4), ID(_5), ID(_6), ID(_7), ID(_8), ID(_9))
134
#define CHLIST16(_tag, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \
135
    CHLIST(_tag, 16, ID(_1),  ID(_2),  ID(_3),  ID(_4),  ID(_5),  ID(_6), ID(_7), ID(_8), ID(_9), ID(_10), \
136
                     ID(_11), ID(_12), ID(_13), ID(_14), ID(_15), ID(_16))
137
#define CHLIST21(_tag, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21) \
138
    CHLIST(_tag, 21, ID(_1),  ID(_2),  ID(_3),  ID(_4),  ID(_5),  ID(_6),  ID(_7),  ID(_8),  ID(_9),  ID(_10), \
139
                     ID(_11), ID(_12), ID(_13), ID(_14), ID(_15), ID(_16), ID(_17), ID(_18), ID(_19), ID(_20), ID(_21))
140
#define CHLIST24(_tag, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24) \
141
    CHLIST(_tag, 24, ID(_1),  ID(_2),  ID(_3),  ID(_4),  ID(_5),  ID(_6),  ID(_7),  ID(_8),  ID(_9),  ID(_10), \
142
                     ID(_11), ID(_12), ID(_13), ID(_14), ID(_15), ID(_16), ID(_17), ID(_18), ID(_19), ID(_20), \
143
                     ID(_21), ID(_22), ID(_23), ID(_24))
144
145
#define MOV_CH_LAYOUT_MAP \
146
    CHLIST01( MOV_CH_LAYOUT_MONO,                 C    )\
147
    CHLIST02( MOV_CH_LAYOUT_STEREO,               L,   R    )\
148
    CHLIST02( MOV_CH_LAYOUT_STEREOHEADPHONES,     L,   R    )\
149
    CHLIST02( MOV_CH_LAYOUT_BINAURAL,             L,   R    )\
150
    CHLIST02( MOV_CH_LAYOUT_MIDSIDE,              L,   R    )\
151
    CHLIST02( MOV_CH_LAYOUT_XY,                   L,   R    )\
152
    CHLIST02( MOV_CH_LAYOUT_MATRIXSTEREO,         Lt,  Rt   )\
153
    CHLIST02( MOV_CH_LAYOUT_AC3_1_0_1,            C,   LFE  )\
154
    CHLIST03( MOV_CH_LAYOUT_MPEG_3_0_A,           L,   R,   C     )\
155
    CHLIST03( MOV_CH_LAYOUT_MPEG_3_0_B,           C,   L,   R     )\
156
    CHLIST03( MOV_CH_LAYOUT_AC3_3_0,              L,   C,   R     )\
157
    CHLIST03( MOV_CH_LAYOUT_ITU_2_1,              L,   R,   Cs    )\
158
    CHLIST03( MOV_CH_LAYOUT_DVD_4,                L,   R,   LFE   )\
159
    CHLIST04( MOV_CH_LAYOUT_AMBISONIC_B_FORMAT,   W,   X,   Y,    Z     )\
160
    CHLIST04( MOV_CH_LAYOUT_QUADRAPHONIC,         L,   R,   Rls,  Rrs   )\
161
    CHLIST04( MOV_CH_LAYOUT_MPEG_4_0_A,           L,   R,   C,    Cs    )\
162
    CHLIST04( MOV_CH_LAYOUT_MPEG_4_0_B,           C,   L,   R,    Cs    )\
163
    CHLIST04( MOV_CH_LAYOUT_AC3_3_1,              L,   C,   R,    Cs    )\
164
    CHLIST04( MOV_CH_LAYOUT_ITU_2_2,              L,   R,   Ls,   Rs    )\
165
    CHLIST04( MOV_CH_LAYOUT_DVD_5,                L,   R,   LFE,  Cs    )\
166
    CHLIST04( MOV_CH_LAYOUT_AC3_2_1_1,            L,   R,   Cs,   LFE   )\
167
    CHLIST04( MOV_CH_LAYOUT_DVD_10,               L,   R,   C,    LFE   )\
168
    CHLIST04( MOV_CH_LAYOUT_AC3_3_0_1,            L,   C,   R,    LFE   )\
169
    CHLIST04( MOV_CH_LAYOUT_DTS_3_1,              C,   L,   R,    LFE   )\
170
    CHLIST05( MOV_CH_LAYOUT_PENTAGONAL,           L,   R,   Rls,  Rrs,  C     )\
171
    CHLIST05( MOV_CH_LAYOUT_MPEG_5_0_A,           L,   R,   C,    Ls,   Rs    )\
172
    CHLIST05( MOV_CH_LAYOUT_MPEG_5_0_B,           L,   R,   Ls,   Rs,   C     )\
173
    CHLIST05( MOV_CH_LAYOUT_MPEG_5_0_C,           L,   C,   R,    Ls,   Rs    )\
174
    CHLIST05( MOV_CH_LAYOUT_MPEG_5_0_D,           C,   L,   R,    Ls,   Rs    )\
175
    CHLIST05( MOV_CH_LAYOUT_DVD_6,                L,   R,   LFE,  Ls,   Rs    )\
176
    CHLIST05( MOV_CH_LAYOUT_DVD_18,               L,   R,   Ls,   Rs,   LFE   )\
177
    CHLIST05( MOV_CH_LAYOUT_DVD_11,               L,   R,   C,    LFE,  Cs    )\
178
    CHLIST05( MOV_CH_LAYOUT_AC3_3_1_1,            L,   C,   R,    Cs,   LFE   )\
179
    CHLIST05( MOV_CH_LAYOUT_DTS_4_1,              C,   L,   R,    Cs,   LFE   )\
180
    CHLIST06( MOV_CH_LAYOUT_HEXAGONAL,            L,   R,   Rls,  Rrs,  C,    Cs     )\
181
    CHLIST06( MOV_CH_LAYOUT_DTS_6_0_C,            C,   Cs,  L,    R,    Rls,  Rrs    )\
182
    CHLIST06( MOV_CH_LAYOUT_MPEG_5_1_A,           L,   R,   C,    LFE,  Ls,   Rs     )\
183
    CHLIST06( MOV_CH_LAYOUT_MPEG_5_1_B,           L,   R,   Ls,   Rs,   C,    LFE    )\
184
    CHLIST06( MOV_CH_LAYOUT_MPEG_5_1_C,           L,   C,   R,    Ls,   Rs,   LFE    )\
185
    CHLIST06( MOV_CH_LAYOUT_MPEG_5_1_D,           C,   L,   R,    Ls,   Rs,   LFE    )\
186
    CHLIST06( MOV_CH_LAYOUT_AUDIOUNIT_6_0,        L,   R,   Ls,   Rs,   C,    Cs     )\
187
    CHLIST06( MOV_CH_LAYOUT_AAC_6_0,              C,   L,   R,    Ls,   Rs,   Cs     )\
188
    CHLIST06( MOV_CH_LAYOUT_EAC3_6_0_A,           L,   C,   R,    Ls,   Rs,   Cs     )\
189
    CHLIST06( MOV_CH_LAYOUT_DTS_6_0_A,            Lc,  Rc,  L,    R,    Ls,   Rs     )\
190
    CHLIST06( MOV_CH_LAYOUT_DTS_6_0_B,            C,   L,   R,    Rls,  Rrs,  Ts     )\
191
    CHLIST07( MOV_CH_LAYOUT_MPEG_6_1_A,           L,   R,   C,    LFE,  Ls,   Rs,    Cs    )\
192
    CHLIST07( MOV_CH_LAYOUT_AAC_6_1,              C,   L,   R,    Ls,   Rs,   Cs,    LFE   )\
193
    CHLIST07( MOV_CH_LAYOUT_EAC3_6_1_A,           L,   C,   R,    Ls,   Rs,   LFE,   Cs    )\
194
    CHLIST07( MOV_CH_LAYOUT_DTS_6_1_D,            C,   L,   R,    Ls,   Rs,   LFE,   Cs    )\
195
    CHLIST07( MOV_CH_LAYOUT_AUDIOUNIT_7_0,        L,   R,   Ls,   Rs,   C,    Rls,   Rrs   )\
196
    CHLIST07( MOV_CH_LAYOUT_AAC_7_0,              C,   L,   R,    Ls,   Rs,   Rls,   Rrs   )\
197
    CHLIST07( MOV_CH_LAYOUT_EAC3_7_0_A,           L,   C,   R,    Ls,   Rs,   Rls,   Rrs   )\
198
    CHLIST07( MOV_CH_LAYOUT_AUDIOUNIT_7_0_FRONT,  L,   R,   Ls,   Rs,   C,    Lc,    Rc    )\
199
    CHLIST07( MOV_CH_LAYOUT_DTS_7_0,              Lc,  C,   Rc,   L,    R,    Ls,    Rs    )\
200
    CHLIST07( MOV_CH_LAYOUT_EAC3_6_1_B,           L,   C,   R,    Ls,   Rs,   LFE,   Ts    )\
201
    CHLIST07( MOV_CH_LAYOUT_EAC3_6_1_C,           L,   C,   R,    Ls,   Rs,   LFE,   Vhc   )\
202
    CHLIST07( MOV_CH_LAYOUT_DTS_6_1_A,            Lc,  Rc,  L,    R,    Ls,   Rs,    LFE   )\
203
    CHLIST07( MOV_CH_LAYOUT_DTS_6_1_B,            C,   L,   R,    Rls,  Rrs,  Ts,    LFE   )\
204
    CHLIST07( MOV_CH_LAYOUT_DTS_6_1_C,            C,   Cs,  L,    R,    Rls,  Rrs,   LFE   )\
205
    CHLIST08( MOV_CH_LAYOUT_OCTAGONAL,            L,   R,   Rls,  Rrs,  C,    Cs,    Ls,   Rs    )\
206
    CHLIST08( MOV_CH_LAYOUT_AAC_OCTAGONAL,        C,   L,   R,    Ls,   Rs,   Rls,   Rrs,  Cs    )\
207
    CHLIST08( MOV_CH_LAYOUT_CUBE,                 L,   R,   Rls,  Rrs,  Vhl,  Vhr,   Rlt,  Rrt   )\
208
    CHLIST08( MOV_CH_LAYOUT_MPEG_7_1_A,           L,   R,   C,    LFE,  Ls,   Rs,    Lc,   Rc    )\
209
    CHLIST08( MOV_CH_LAYOUT_MPEG_7_1_B,           C,   Lc,  Rc,   L,    R,    Ls,    Rs,   LFE   )\
210
    CHLIST08( MOV_CH_LAYOUT_EMAGIC_DEFAULT_7_1,   L,   R,   Ls,   Rs,   C,    LFE,   Lc,   Rc    )\
211
    CHLIST08( MOV_CH_LAYOUT_EAC3_7_1_B,           L,   C,   R,    Ls,   Rs,   LFE,   Lc,   Rc    )\
212
    CHLIST08( MOV_CH_LAYOUT_DTS_7_1,              Lc,  C,   Rc,   L,    R,    Ls,    Rs,   LFE   )\
213
    CHLIST08( MOV_CH_LAYOUT_MPEG_7_1_C,           L,   R,   C,    LFE,  Ls,   Rs,    Rls,  Rrs   )\
214
    CHLIST08( MOV_CH_LAYOUT_EAC3_7_1_A,           L,   C,   R,    Ls,   Rs,   LFE,   Rls,  Rrs   )\
215
    CHLIST08( MOV_CH_LAYOUT_SMPTE_DTV,            L,   R,   C,    LFE,  Ls,   Rs,    Lt,   Rt    )\
216
    CHLIST08( MOV_CH_LAYOUT_EAC3_7_1_C,           L,   C,   R,    Ls,   Rs,   LFE,   Lsd,  Rsd   )\
217
    CHLIST08( MOV_CH_LAYOUT_EAC3_7_1_D,           L,   C,   R,    Ls,   Rs,   LFE,   Lw,   Rw    )\
218
    CHLIST08( MOV_CH_LAYOUT_EAC3_7_1_E,           L,   C,   R,    Ls,   Rs,   LFE,   Vhl,  Vhr   )\
219
    CHLIST08( MOV_CH_LAYOUT_EAC3_7_1_F,           L,   C,   R,    Ls,   Rs,   LFE,   Cs,   Ts    )\
220
    CHLIST08( MOV_CH_LAYOUT_EAC3_7_1_G,           L,   C,   R,    Ls,   Rs,   LFE,   Cs,   Vhc   )\
221
    CHLIST08( MOV_CH_LAYOUT_EAC3_7_1_H,           L,   C,   R,    Ls,   Rs,   LFE,   Ts,   Vhc   )\
222
    CHLIST08( MOV_CH_LAYOUT_DTS_8_0_A,            Lc,  Rc,  L,    R,    Ls,   Rs,    Rls,  Rrs   )\
223
    CHLIST08( MOV_CH_LAYOUT_DTS_8_0_B,            Lc,  C,   Rc,   L,    R,    Ls,    Cs,   Rs    )\
224
    CHLIST09( MOV_CH_LAYOUT_DTS_8_1_A,            Lc,  Rc,  L,    R,    Ls,   Rs,    Rls,  Rrs,  LFE   )\
225
    CHLIST09( MOV_CH_LAYOUT_DTS_8_1_B,            Lc,  C,   Rc,   L,    R,    Ls,    Cs,   Rs,   LFE   )\
226
    CHLIST16( MOV_CH_LAYOUT_TMH_10_2_STD,         L,   R,   C,    Vhc,  Lsd,  Rsd,   Ls,   Rs,   Vhl,  Vhr,  Lw,  Rw,  Csd,  Cs,  LFE1,  LFE2  )\
227
    CHLIST21( MOV_CH_LAYOUT_TMH_10_2_FULL,        L,   R,   C,    Vhc,  Lsd,  Rsd,   Ls,   Rs,   Vhl,  Vhr,  Lw,  Rw,  Csd,  Cs,  LFE1,  LFE2,  Lc,  Rc,  HI,  VI,  Haptic  )\
228
229
#define CHLIST(_tag, _cnt, ...)    static_assert((_tag & 0xffff) == _cnt, "Channel count of " #_tag " is not " #_cnt);
230
MOV_CH_LAYOUT_MAP
231
#undef CHLIST
232
#define CHLIST(_tag, _cnt, ...)    TAG(_tag, _cnt), __VA_ARGS__,
233
static const struct MovChannelLayoutMap mov_ch_layout_map[] = {
234
    MOV_CH_LAYOUT_MAP
235
    { {0} },
236
};
237
238
#undef ID
239
#undef TAG
240
#define ID(_0)            {.id = iso_##_0}
241
#define TAG(_tag, _cnt)   {.tag = (_tag << 16) | _cnt}
242
243
/* ISO/IEC 23001-8 */
244
static const struct MovChannelLayoutMap iso_ch_layout_map[] = {
245
    CHLIST01(  1,  C )
246
    CHLIST02(  2,  L,   R   )
247
    CHLIST03(  3,  C,   L,   R   )
248
    CHLIST04(  4,  C,   L,   R,    Cs  )
249
    CHLIST05(  5,  C,   L,   R,    Ls,   Rs  )
250
    CHLIST06(  6,  C,   L,   R,    Ls,   Rs,   LFE )
251
    CHLIST08(  7,  C,   Lc,  Rc,   L,    R,    Ls,   Rs,   LFE )
252
    CHLIST03(  9,  L,   R,   Cs  )
253
    CHLIST04( 10,  L,   R,   Ls,   Rs  )
254
    CHLIST07( 11,  C,   L,   R,    Ls,   Rs,   Cs,   LFE )
255
    CHLIST08( 12,  C,   L,   R,    Ls,   Rs,   Lsr,  Rsr,  LFE )
256
    CHLIST24( 13,  C,   Lc,  Rc,   L,    R,    Lss,  Rss,  Lsr,  Rsr,  Cs,  LFE,  LFE2,  Cv,  Lv,  Rv,  Lvss,  Rvss,  Ts,  Lvr,  Rvr,  Cvr,  Cb,  Lb,  Rb)
257
    CHLIST08( 14,  C,   L,   R,    Ls,   Rs,   LFE,  Lv,   Rv)
258
    { {0} },
259
};
260
261
static const enum MovChannelLayoutTag mov_ch_layouts_aac[] = {
262
    MOV_CH_LAYOUT_MONO,
263
    MOV_CH_LAYOUT_STEREO,
264
    MOV_CH_LAYOUT_AC3_1_0_1,
265
    MOV_CH_LAYOUT_MPEG_3_0_B,
266
    MOV_CH_LAYOUT_ITU_2_1,
267
    MOV_CH_LAYOUT_DVD_4,
268
    MOV_CH_LAYOUT_QUADRAPHONIC,
269
    MOV_CH_LAYOUT_MPEG_4_0_B,
270
    MOV_CH_LAYOUT_ITU_2_2,
271
    MOV_CH_LAYOUT_AC3_2_1_1,
272
    MOV_CH_LAYOUT_DTS_3_1,
273
    MOV_CH_LAYOUT_MPEG_5_0_D,
274
    MOV_CH_LAYOUT_DVD_18,
275
    MOV_CH_LAYOUT_DTS_4_1,
276
    MOV_CH_LAYOUT_MPEG_5_1_D,
277
    MOV_CH_LAYOUT_AAC_6_0,
278
    MOV_CH_LAYOUT_DTS_6_0_A,
279
    MOV_CH_LAYOUT_AAC_6_1,
280
    MOV_CH_LAYOUT_AAC_7_0,
281
    MOV_CH_LAYOUT_DTS_6_1_A,
282
    MOV_CH_LAYOUT_AAC_OCTAGONAL,
283
    MOV_CH_LAYOUT_MPEG_7_1_B,
284
    MOV_CH_LAYOUT_DTS_8_0_A,
285
    0,
286
};
287
288
static const enum MovChannelLayoutTag mov_ch_layouts_ac3[] = {
289
    MOV_CH_LAYOUT_MONO,
290
    MOV_CH_LAYOUT_STEREO,
291
    MOV_CH_LAYOUT_AC3_1_0_1,
292
    MOV_CH_LAYOUT_AC3_3_0,
293
    MOV_CH_LAYOUT_ITU_2_1,
294
    MOV_CH_LAYOUT_DVD_4,
295
    MOV_CH_LAYOUT_AC3_3_1,
296
    MOV_CH_LAYOUT_ITU_2_2,
297
    MOV_CH_LAYOUT_AC3_2_1_1,
298
    MOV_CH_LAYOUT_AC3_3_0_1,
299
    MOV_CH_LAYOUT_MPEG_5_0_C,
300
    MOV_CH_LAYOUT_DVD_18,
301
    MOV_CH_LAYOUT_AC3_3_1_1,
302
    MOV_CH_LAYOUT_MPEG_5_1_C,
303
    0,
304
};
305
306
static const enum MovChannelLayoutTag mov_ch_layouts_alac[] = {
307
    MOV_CH_LAYOUT_MONO,
308
    MOV_CH_LAYOUT_STEREO,
309
    MOV_CH_LAYOUT_MPEG_3_0_B,
310
    MOV_CH_LAYOUT_MPEG_4_0_B,
311
    MOV_CH_LAYOUT_MPEG_5_0_D,
312
    MOV_CH_LAYOUT_MPEG_5_1_D,
313
    MOV_CH_LAYOUT_AAC_6_1,
314
    MOV_CH_LAYOUT_MPEG_7_1_B,
315
    0,
316
};
317
318
static const enum MovChannelLayoutTag mov_ch_layouts_wav[] = {
319
    MOV_CH_LAYOUT_MONO,
320
    MOV_CH_LAYOUT_STEREO,
321
    MOV_CH_LAYOUT_MATRIXSTEREO,
322
    MOV_CH_LAYOUT_MPEG_3_0_A,
323
    MOV_CH_LAYOUT_QUADRAPHONIC,
324
    MOV_CH_LAYOUT_MPEG_5_0_A,
325
    MOV_CH_LAYOUT_MPEG_5_1_A,
326
    MOV_CH_LAYOUT_MPEG_6_1_A,
327
    MOV_CH_LAYOUT_MPEG_7_1_A,
328
    MOV_CH_LAYOUT_MPEG_7_1_C,
329
    MOV_CH_LAYOUT_SMPTE_DTV,
330
    0,
331
};
332
333
static const struct {
334
    enum AVCodecID codec_id;
335
    const enum MovChannelLayoutTag *layouts;
336
} mov_codec_ch_layouts[] = {
337
    { AV_CODEC_ID_AAC,          mov_ch_layouts_aac  },
338
    { AV_CODEC_ID_AC3,          mov_ch_layouts_ac3  },
339
    { AV_CODEC_ID_ADPCM_IMA_QT, mov_ch_layouts_wav  },
340
    { AV_CODEC_ID_ALAC,         mov_ch_layouts_alac },
341
    { AV_CODEC_ID_MACE3,        mov_ch_layouts_wav  },
342
    { AV_CODEC_ID_MACE6,        mov_ch_layouts_wav  },
343
    { AV_CODEC_ID_PCM_ALAW,     mov_ch_layouts_wav  },
344
    { AV_CODEC_ID_PCM_F32BE,    mov_ch_layouts_wav  },
345
    { AV_CODEC_ID_PCM_F32LE,    mov_ch_layouts_wav  },
346
    { AV_CODEC_ID_PCM_F64BE,    mov_ch_layouts_wav  },
347
    { AV_CODEC_ID_PCM_F64LE,    mov_ch_layouts_wav  },
348
    { AV_CODEC_ID_PCM_MULAW,    mov_ch_layouts_wav  },
349
    { AV_CODEC_ID_PCM_S16BE,    mov_ch_layouts_wav  },
350
    { AV_CODEC_ID_PCM_S16LE,    mov_ch_layouts_wav  },
351
    { AV_CODEC_ID_PCM_S24BE,    mov_ch_layouts_wav  },
352
    { AV_CODEC_ID_PCM_S24LE,    mov_ch_layouts_wav  },
353
    { AV_CODEC_ID_PCM_S32BE,    mov_ch_layouts_wav  },
354
    { AV_CODEC_ID_PCM_S32LE,    mov_ch_layouts_wav  },
355
    { AV_CODEC_ID_PCM_S8,       mov_ch_layouts_wav  },
356
    { AV_CODEC_ID_PCM_U8,       mov_ch_layouts_wav  },
357
    { AV_CODEC_ID_SPEEX,        mov_ch_layouts_wav  },
358
    { AV_CODEC_ID_NONE,         NULL                },
359
};
360
361
static const struct MovChannelLayoutMap* find_layout_map(uint32_t tag, const struct MovChannelLayoutMap *map)
362
4.18k
{
363
226k
    for (int i = 0; map[i].tag & 0xffff; i += 1 + (map[i].tag & 0xffff))
364
225k
        if (map[i].tag == tag)
365
3.12k
            return &map[i + 1];
366
1.05k
    return NULL;
367
4.18k
}
368
369
/**
370
 * Get the channel layout for the specified non-special channel layout tag if
371
 * known.
372
 *
373
 * @param[in,out]  ch_layout  channel layout
374
 * @param[in]      tag        channel layout tag
375
 * @return                    <0 on error
376
 */
377
static int mov_get_channel_layout(AVChannelLayout *ch_layout, uint32_t tag, uint64_t omitted_channel_map, const struct MovChannelLayoutMap *map)
378
4.18k
{
379
4.18k
    const struct MovChannelLayoutMap *layout_map;
380
381
    /* find the channel layout for the specified layout tag */
382
4.18k
    layout_map = find_layout_map(tag, map);
383
4.18k
    if (layout_map) {
384
3.12k
        AVChannelLayout tmp = { 0 };
385
3.12k
        int ret;
386
3.12k
        int map_layout_nb_channels = tag & 0xFFFF;
387
3.12k
        int nb_channels = ch_layout->nb_channels;
388
389
        /* Omitted channel bits must not exceed number of channels in map */
390
3.12k
        if (omitted_channel_map >> map_layout_nb_channels)
391
0
            return AVERROR_INVALIDDATA;
392
393
3.12k
        ret = av_channel_layout_custom_init(&tmp, nb_channels);
394
3.12k
        if (ret < 0)
395
0
            return ret;
396
397
32.3k
        for (int i = 0, idx = 0; i < map_layout_nb_channels && idx < nb_channels; i++, omitted_channel_map >>= 1) {
398
29.2k
            if (!(omitted_channel_map & 1)) {
399
29.2k
                enum AVChannel id = layout_map[i].id;
400
29.2k
                tmp.u.map[idx++].id = (id != AV_CHAN_NONE ? id : AV_CHAN_UNKNOWN);
401
29.2k
            }
402
29.2k
        }
403
404
3.12k
        ret = av_channel_layout_retype(&tmp, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
405
3.12k
        if (ret < 0) {
406
0
            av_channel_layout_uninit(&tmp);
407
0
            return ret;
408
0
        }
409
410
3.12k
        av_channel_layout_uninit(ch_layout);
411
3.12k
        *ch_layout = tmp;
412
3.12k
    }
413
4.18k
    return 0;
414
4.18k
}
415
416
static enum AVChannel mov_get_channel_id(uint32_t label)
417
250k
{
418
250k
    if (label == 0)
419
58.6k
        return AV_CHAN_UNUSED;
420
191k
    if (label <= 18)
421
3.97k
        return (label - 1);
422
187k
    if (label == 35)
423
515
        return AV_CHAN_WIDE_LEFT;
424
187k
    if (label == 36)
425
522
        return AV_CHAN_WIDE_RIGHT;
426
186k
    if (label == 37)
427
487
        return AV_CHAN_LOW_FREQUENCY_2;
428
186k
    if (label == 38)
429
575
        return AV_CHAN_STEREO_LEFT;
430
185k
    if (label == 39)
431
519
        return AV_CHAN_STEREO_RIGHT;
432
185k
    return AV_CHAN_UNKNOWN;
433
185k
}
434
435
static uint32_t mov_get_channel_label(enum AVChannel channel)
436
0
{
437
0
    if (channel < 0)
438
0
        return 0;
439
0
    if (channel <= AV_CHAN_TOP_BACK_RIGHT)
440
0
        return channel + 1;
441
0
    if (channel == AV_CHAN_WIDE_LEFT)
442
0
        return 35;
443
0
    if (channel == AV_CHAN_WIDE_RIGHT)
444
0
        return 36;
445
0
    if (channel == AV_CHAN_LOW_FREQUENCY_2)
446
0
        return 37;
447
0
    if (channel == AV_CHAN_STEREO_LEFT)
448
0
        return 38;
449
0
    if (channel == AV_CHAN_STEREO_RIGHT)
450
0
        return 39;
451
0
    return 0;
452
0
}
453
454
static int is_layout_valid_for_tag(const AVChannelLayout *ch_layout, uint32_t tag, const struct MovChannelLayoutMap *map)
455
0
{
456
0
    const struct MovChannelLayoutMap *layout_map;
457
0
    int channels = ch_layout->nb_channels;
458
459
    /* get the layout map based on the channel count */
460
0
    if ((tag & 0xFFFF) != channels)
461
0
        return 0;
462
463
0
    layout_map = find_layout_map(tag, map);
464
0
    if (layout_map) {
465
0
        int i;
466
0
        for (i = 0; i < channels; i++) {
467
0
            if (av_channel_layout_channel_from_index(ch_layout, i) != layout_map[i].id)
468
0
                break;
469
0
        }
470
0
        if (i == channels)
471
0
            return 1;
472
0
    }
473
0
    return 0;
474
0
}
475
476
int ff_mov_get_channel_layout_tag(const AVCodecParameters *par,
477
                                  uint32_t *layout,
478
                                  uint32_t *bitmap,
479
                                  uint32_t **pchannel_desc)
480
0
{
481
0
    int i;
482
0
    uint32_t tag = 0;
483
0
    const enum MovChannelLayoutTag *layouts = NULL;
484
485
    /* find the layout list for the specified codec */
486
0
    for (i = 0; mov_codec_ch_layouts[i].codec_id != AV_CODEC_ID_NONE; i++) {
487
0
        if (mov_codec_ch_layouts[i].codec_id == par->codec_id)
488
0
            break;
489
0
    }
490
0
    if (mov_codec_ch_layouts[i].codec_id != AV_CODEC_ID_NONE)
491
0
        layouts = mov_codec_ch_layouts[i].layouts;
492
493
0
    if (layouts) {
494
        /* find the layout tag for the specified channel layout */
495
0
        for (i = 0; layouts[i] != 0; i++)
496
0
            if (is_layout_valid_for_tag(&par->ch_layout, layouts[i], mov_ch_layout_map))
497
0
                break;
498
499
0
        tag = layouts[i];
500
0
    }
501
502
0
    *layout = tag;
503
0
    *bitmap = 0;
504
0
    *pchannel_desc = NULL;
505
506
    /* if no tag was found, use channel bitmap or description as a backup if possible */
507
0
    if (tag == 0) {
508
0
        uint32_t *channel_desc;
509
510
0
        if (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) {
511
            /* Parsers and encoders (e.g. AC3, AAC, ALAC) indicate/propagate the bitstream's
512
             * channel configuration using "standard" layouts in AV_CHANNEL_ORDER_NATIVE but
513
             * the encoded bitstream's channels are not actually in that order. Don't return
514
             * a channel layout bitmap or description using a conflicting channel order, as
515
             * some software will incorrectly override the bitstream-provided information
516
             * using the chan atom's data instead (e.g. afinfo/afplay for AAC in MOV) */
517
0
            if (layouts != mov_ch_layouts_wav) {
518
0
                *layout = MOV_CH_LAYOUT_UNKNOWN;
519
0
                return 0;
520
0
            }
521
522
0
            if (par->ch_layout.u.mask < 0x40000) {
523
0
                *layout = MOV_CH_LAYOUT_USE_BITMAP;
524
0
                *bitmap = (uint32_t)par->ch_layout.u.mask;
525
0
                return 0;
526
0
            }
527
0
        } else if (par->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
528
0
            return AVERROR(ENOSYS);
529
530
0
        channel_desc = av_malloc_array(par->ch_layout.nb_channels, sizeof(*channel_desc));
531
0
        if (!channel_desc)
532
0
            return AVERROR(ENOMEM);
533
534
0
        for (i = 0; i < par->ch_layout.nb_channels; i++) {
535
0
            channel_desc[i] =
536
0
                mov_get_channel_label(av_channel_layout_channel_from_index(&par->ch_layout, i));
537
538
0
            if (channel_desc[i] == 0) {
539
0
                av_free(channel_desc);
540
0
                return AVERROR(ENOSYS);
541
0
            }
542
0
        }
543
544
0
        *pchannel_desc = channel_desc;
545
0
    }
546
547
0
    return 0;
548
0
}
549
550
int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st,
551
                     int64_t size)
552
13.0k
{
553
13.0k
    uint32_t layout_tag, bitmap, num_descr;
554
13.0k
    int ret;
555
13.0k
    AVChannelLayout *ch_layout = &st->codecpar->ch_layout;
556
557
13.0k
    if (size < 12)
558
18
        return AVERROR_INVALIDDATA;
559
560
13.0k
    layout_tag = avio_rb32(pb);
561
13.0k
    bitmap     = avio_rb32(pb);
562
13.0k
    num_descr  = avio_rb32(pb);
563
564
13.0k
    av_log(s, AV_LOG_DEBUG, "chan: layout=%"PRIu32" "
565
13.0k
           "bitmap=%"PRIu32" num_descr=%"PRIu32"\n",
566
13.0k
           layout_tag, bitmap, num_descr);
567
568
13.0k
    if (size < 12ULL + num_descr * 20ULL)
569
2.31k
        return 0;
570
571
10.7k
    if (layout_tag == MOV_CH_LAYOUT_USE_DESCRIPTIONS) {
572
2.46k
        AVChannelLayout tmp = { 0 };
573
2.46k
        int nb_channels = ch_layout->nb_channels;
574
575
2.46k
        if (!num_descr || num_descr < nb_channels) {
576
207
            av_log(s, AV_LOG_ERROR, "got %"PRIu32" channel descriptions when at least %d were needed\n",
577
207
                   num_descr, nb_channels);
578
207
            return AVERROR_INVALIDDATA;
579
207
        }
580
581
2.25k
        if (num_descr > nb_channels) {
582
1.98k
            int strict = s->strict_std_compliance >= FF_COMPLIANCE_STRICT;
583
1.98k
            av_log(s, strict ? AV_LOG_ERROR : AV_LOG_WARNING,
584
1.98k
                   "got %"PRIu32" channel descriptions when number of channels is %d\n",
585
1.98k
                   num_descr, nb_channels);
586
1.98k
            if (strict)
587
0
                return AVERROR_INVALIDDATA;
588
1.98k
            av_log(s, AV_LOG_WARNING, "capping channel descriptions to the number of channels\n");
589
1.98k
            num_descr = nb_channels;
590
1.98k
        }
591
592
2.25k
        ret = av_channel_layout_custom_init(&tmp, nb_channels);
593
2.25k
        if (ret < 0)
594
438
            goto out;
595
596
252k
        for (int i = 0; i < num_descr; i++) {
597
250k
            uint32_t label;
598
250k
            if (pb->eof_reached) {
599
323
                av_log(s, AV_LOG_ERROR,
600
323
                       "reached EOF while reading channel layout\n");
601
323
                av_channel_layout_uninit(&tmp);
602
323
                return AVERROR_INVALIDDATA;
603
323
            }
604
250k
            label     = avio_rb32(pb);          // mChannelLabel
605
250k
            avio_rb32(pb);                      // mChannelFlags
606
250k
            avio_rl32(pb);                      // mCoordinates[0]
607
250k
            avio_rl32(pb);                      // mCoordinates[1]
608
250k
            avio_rl32(pb);                      // mCoordinates[2]
609
250k
            size -= 20;
610
250k
            tmp.u.map[i].id = mov_get_channel_id(label);
611
250k
        }
612
613
1.49k
        ret = av_channel_layout_retype(&tmp, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
614
1.49k
        if (ret < 0) {
615
0
            av_channel_layout_uninit(&tmp);
616
0
            goto out;
617
0
        }
618
619
1.49k
        av_channel_layout_uninit(ch_layout);
620
1.49k
        *ch_layout = tmp;
621
8.25k
    } else if (layout_tag == MOV_CH_LAYOUT_USE_BITMAP) {
622
2.33k
        if (!ch_layout->nb_channels || av_popcount(bitmap) == ch_layout->nb_channels) {
623
1.50k
            if (bitmap < 0x40000) {
624
1.07k
                av_channel_layout_uninit(ch_layout);
625
1.07k
                av_channel_layout_from_mask(ch_layout, bitmap);
626
1.07k
            }
627
1.50k
        } else {
628
826
            av_log(s, AV_LOG_WARNING, "ignoring channel layout bitmap with %d channels because number of channels is %d\n",
629
826
                   av_popcount64(bitmap), ch_layout->nb_channels);
630
826
        }
631
5.92k
    } else if (layout_tag & 0xFFFF) {
632
5.58k
        int nb_channels = layout_tag & 0xFFFF;
633
5.58k
        if (!ch_layout->nb_channels)
634
947
            ch_layout->nb_channels = nb_channels;
635
5.58k
        if (nb_channels == ch_layout->nb_channels) {
636
4.17k
            ret = mov_get_channel_layout(ch_layout, layout_tag, 0, mov_ch_layout_map);
637
4.17k
            if (ret < 0)
638
0
                return ret;
639
4.17k
        } else {
640
1.41k
            av_log(s, AV_LOG_WARNING, "ignoring layout tag with %d channels because number of channels is %d\n",
641
1.41k
                   nb_channels, ch_layout->nb_channels);
642
1.41k
        }
643
5.58k
    }
644
9.75k
    ret = 0;
645
646
10.1k
out:
647
10.1k
    avio_skip(pb, size - 12);
648
649
10.1k
    return ret;
650
9.75k
}
651
652
/* ISO/IEC 23001-8, table 8 */
653
static const enum AVChannel iso_channel_position[] = {
654
     [0] = AV_CHAN_FRONT_LEFT,              // left front
655
     [1] = AV_CHAN_FRONT_RIGHT,             // right front
656
     [2] = AV_CHAN_FRONT_CENTER,            // centre front
657
     [3] = AV_CHAN_LOW_FREQUENCY,           // low frequency enhancement
658
     [4] = AV_CHAN_SIDE_LEFT,               // left surround
659
     [5] = AV_CHAN_SIDE_RIGHT,              // right surround
660
     [6] = AV_CHAN_FRONT_LEFT_OF_CENTER,    // left front centre
661
     [7] = AV_CHAN_FRONT_RIGHT_OF_CENTER,   // right front centre
662
     [8] = AV_CHAN_BACK_LEFT,               // rear surround left
663
     [9] = AV_CHAN_BACK_RIGHT,              // rear surround right
664
    [10] = AV_CHAN_BACK_CENTER,             // rear centre
665
    [11] = AV_CHAN_SURROUND_DIRECT_LEFT,    // left surround direct
666
    [12] = AV_CHAN_SURROUND_DIRECT_RIGHT,   // right surround direct
667
    [13] = AV_CHAN_SIDE_SURROUND_LEFT,      // left side surround
668
    [14] = AV_CHAN_SIDE_SURROUND_RIGHT,     // right side surround
669
    [15] = AV_CHAN_WIDE_LEFT,               // left wide front
670
    [16] = AV_CHAN_WIDE_RIGHT,              // right wide front
671
    [17] = AV_CHAN_TOP_FRONT_LEFT,          // left front vertical height
672
    [18] = AV_CHAN_TOP_FRONT_RIGHT,         // right front vertical height
673
    [19] = AV_CHAN_TOP_FRONT_CENTER,        // centre front vertical height
674
    [20] = AV_CHAN_TOP_BACK_LEFT,           // left surround vertical height rear
675
    [21] = AV_CHAN_TOP_BACK_RIGHT,          // right surround vertical height rear
676
    [22] = AV_CHAN_TOP_BACK_CENTER,         // centre vertical height rear
677
    [23] = AV_CHAN_TOP_SIDE_LEFT,           // left vertical height side surround
678
    [24] = AV_CHAN_TOP_SIDE_RIGHT,          // right vertical height side surround
679
    [25] = AV_CHAN_TOP_CENTER,              // top centre surround
680
    [26] = AV_CHAN_LOW_FREQUENCY_2,         // low frequency enhancement 2
681
    [27] = AV_CHAN_BOTTOM_FRONT_LEFT,       // left front vertical bottom
682
    [28] = AV_CHAN_BOTTOM_FRONT_RIGHT,      // right front vertical bottom
683
    [29] = AV_CHAN_BOTTOM_FRONT_CENTER,     // centre front vertical bottom
684
    [30] = AV_CHAN_TOP_SURROUND_LEFT,       // left vertical height surround
685
    [31] = AV_CHAN_TOP_SURROUND_RIGHT,      // right vertical height surround
686
687
    [32] = AV_CHAN_NONE,                    // reserved
688
    [33] = AV_CHAN_NONE,                    // reserved
689
    [34] = AV_CHAN_NONE,                    // reserved
690
    [35] = AV_CHAN_NONE,                    // reserved
691
692
    [36] = AV_CHAN_NONE,                    // low frequency enhancement 3
693
    [37] = AV_CHAN_NONE,                    // left edge of screen
694
    [38] = AV_CHAN_NONE,                    // right edge of screen
695
    [39] = AV_CHAN_NONE,                    // half-way between centre of screen and left edge of screen
696
    [40] = AV_CHAN_NONE,                    // half-way between centre of screen and right edge of screen
697
    [41] = AV_CHAN_NONE,                    // left back surround
698
    [42] = AV_CHAN_NONE,                    // right back surround
699
700
    // 43 - 125: reserved
701
    // 126: explicit position
702
    // 127: unknown /undefined
703
};
704
705
int ff_mov_get_channel_config_from_layout(const AVChannelLayout *layout, int *config)
706
0
{
707
    // Set default value which means any setup in 23001-8
708
0
    *config = 0;
709
0
    for (int i = 0; iso_ch_layout_map[i].tag & 0xffff; i += 1 + (iso_ch_layout_map[i].tag & 0xffff)) {
710
0
        if (is_layout_valid_for_tag(layout, iso_ch_layout_map[i].tag, &iso_ch_layout_map[i])) {
711
0
            *config = iso_ch_layout_map[i].tag >> 16;
712
0
            break;
713
0
        }
714
0
    }
715
716
0
    return 0;
717
0
}
718
719
/**
720
 * Get AVChannelLayout from ISO/IEC 23001-8 ChannelConfiguration.
721
 *
722
 * @return 1  if the config was unknown, layout is untouched in this case
723
 *         0  if the config was found
724
 *         <0 on error
725
 */
726
static int mov_get_channel_layout_from_config(int config, AVChannelLayout *layout, uint64_t omitted_channel_map)
727
13
{
728
13
    if (config > 0) {
729
13
        uint32_t layout_tag;
730
13
        int nb_omitted_channels = av_popcount64(omitted_channel_map);
731
732
13
        if (layout->nb_channels <= 0 || layout->nb_channels > UINT16_MAX - nb_omitted_channels)
733
2
            return AVERROR_INVALIDDATA;
734
735
11
        layout_tag = (config << 16) | (layout->nb_channels + nb_omitted_channels);
736
11
        return mov_get_channel_layout(layout, layout_tag, omitted_channel_map, iso_ch_layout_map);
737
13
    }
738
0
    return 1;
739
13
}
740
741
int ff_mov_get_channel_positions_from_layout(const AVChannelLayout *layout,
742
                                             uint8_t *position, int position_num)
743
0
{
744
0
    enum AVChannel channel;
745
746
0
    if (position_num < layout->nb_channels)
747
0
        return AVERROR(EINVAL);
748
749
0
    for (int i = 0; i < layout->nb_channels; i++) {
750
0
        position[i] = 127;
751
0
        channel = av_channel_layout_channel_from_index(layout, i);
752
0
        if (channel == AV_CHAN_NONE)
753
0
            return AVERROR(EINVAL);
754
755
0
        for (int j = 0; j < FF_ARRAY_ELEMS(iso_channel_position); j++) {
756
0
            if (iso_channel_position[j] == channel) {
757
0
                position[i] = j;
758
0
                break;
759
0
            }
760
0
        }
761
0
        if (position[i] == 127)
762
0
            return AVERROR(EINVAL);
763
0
    }
764
765
0
    return 0;
766
0
}
767
768
int ff_mov_read_chnl(AVFormatContext *s, AVIOContext *pb, AVStream *st, int version)
769
682
{
770
682
    int stream_structure = avio_r8(pb);
771
682
    int base_channel_count;
772
682
    int obj_count = 0;
773
682
    int ret;
774
775
682
    if (version == 1) {
776
9
        stream_structure >>= 4;
777
9
        base_channel_count = avio_r8(pb);
778
9
    }
779
780
    // stream carries channels
781
682
    if (stream_structure & 1) {
782
411
        int layout = avio_r8(pb);
783
784
411
        av_log(s, AV_LOG_TRACE, "'chnl' layout %d\n", layout);
785
411
        if (!layout) {
786
396
            AVChannelLayout tmp = { 0 }, *ch_layout = &st->codecpar->ch_layout;
787
396
            int nb_channels = ch_layout->nb_channels;
788
789
396
            if (version == 1) {
790
7
                nb_channels = avio_r8(pb);
791
7
                obj_count = base_channel_count - nb_channels;
792
7
                if (obj_count < 0)
793
1
                    return AVERROR_INVALIDDATA;
794
7
            }
795
796
395
            ret = av_channel_layout_custom_init(&tmp, nb_channels);
797
395
            if (ret < 0)
798
142
                return ret;
799
800
591k
            for (int i = 0; i < nb_channels; i++) {
801
591k
                int speaker_pos = avio_r8(pb);
802
591k
                enum AVChannel channel;
803
804
591k
                if (speaker_pos == 126) // explicit position
805
75
                    avio_skip(pb, 3);   // azimuth, elevation
806
807
591k
                if (speaker_pos >= FF_ARRAY_ELEMS(iso_channel_position))
808
74.1k
                    channel = AV_CHAN_NONE;
809
516k
                else
810
516k
                    channel = iso_channel_position[speaker_pos];
811
812
591k
                if (channel == AV_CHAN_NONE) {
813
74.5k
                    av_log(s, AV_LOG_WARNING, "speaker position %d is not implemented\n", speaker_pos);
814
74.5k
                    channel = AV_CHAN_UNKNOWN;
815
74.5k
                }
816
817
591k
                tmp.u.map[i].id = channel;
818
591k
            }
819
820
253
            ret = av_channel_layout_retype(&tmp, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
821
253
            if (ret < 0) {
822
0
                av_channel_layout_uninit(&tmp);
823
0
                return ret;
824
0
            }
825
253
            av_channel_layout_uninit(ch_layout);
826
253
            *ch_layout = tmp;
827
253
        } else {
828
15
            uint64_t omitted_channel_map = 0;
829
15
            int omitted_channel_present = 1, channel_order_definition = 0;
830
831
15
            if (version == 1) {
832
2
                int byte = avio_r8(pb);
833
2
                omitted_channel_present  =  byte       & 1;
834
2
                channel_order_definition = (byte >> 1) & 0x7;
835
2
            }
836
837
15
            if (omitted_channel_present)
838
15
                omitted_channel_map = avio_rb64(pb);
839
15
            if (!channel_order_definition) {
840
13
                ret = mov_get_channel_layout_from_config(layout, &st->codecpar->ch_layout, omitted_channel_map);
841
13
                if (ret < 0)
842
2
                    return ret;
843
13
            } else
844
2
                av_log(s, AV_LOG_TRACE, "'chnl' with channel_order_definition %d\n", channel_order_definition);
845
846
13
            if (version == 1)
847
2
                obj_count = base_channel_count - st->codecpar->ch_layout.nb_channels;
848
13
        }
849
411
    }
850
851
    // stream carries objects
852
537
    if (stream_structure & 2) {
853
247
        if (version == 0)
854
246
            obj_count = avio_r8(pb);
855
247
        av_log(s, AV_LOG_TRACE, "'chnl' with object_count %d\n", obj_count);
856
247
    }
857
858
537
    return 0;
859
682
}