FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov_chan.c
Date: 2024-04-25 15:36:26
Exec Total Coverage
Lines: 172 217 79.3%
Functions: 11 11 100.0%
Branches: 107 158 67.7%

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