FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mov_chan.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 173 224 77.2%
Functions: 11 11 100.0%
Branches: 108 164 65.9%

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 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_ALAC, mov_ch_layouts_alac },
340 { AV_CODEC_ID_PCM_U8, mov_ch_layouts_wav },
341 { AV_CODEC_ID_PCM_S8, mov_ch_layouts_wav },
342 { AV_CODEC_ID_PCM_S16LE, mov_ch_layouts_wav },
343 { AV_CODEC_ID_PCM_S16BE, mov_ch_layouts_wav },
344 { AV_CODEC_ID_PCM_S24LE, mov_ch_layouts_wav },
345 { AV_CODEC_ID_PCM_S24BE, mov_ch_layouts_wav },
346 { AV_CODEC_ID_PCM_S32LE, mov_ch_layouts_wav },
347 { AV_CODEC_ID_PCM_S32BE, mov_ch_layouts_wav },
348 { AV_CODEC_ID_PCM_F32LE, mov_ch_layouts_wav },
349 { AV_CODEC_ID_PCM_F32BE, mov_ch_layouts_wav },
350 { AV_CODEC_ID_PCM_F64LE, mov_ch_layouts_wav },
351 { AV_CODEC_ID_PCM_F64BE, mov_ch_layouts_wav },
352 { AV_CODEC_ID_NONE, NULL },
353 };
354
355 79 static const struct MovChannelLayoutMap* find_layout_map(uint32_t tag, const struct MovChannelLayoutMap *map)
356 {
357
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))
358
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 84 times.
163 if (map[i].tag == tag)
359 79 return &map[i + 1];
360 return NULL;
361 }
362
363 /**
364 * Get the channel layout for the specified non-special channel layout tag if
365 * known.
366 *
367 * @param[in,out] ch_layout channel layout
368 * @param[in] tag channel layout tag
369 * @return <0 on error
370 */
371 44 static int mov_get_channel_layout(AVChannelLayout *ch_layout, uint32_t tag, uint64_t omitted_channel_map, const struct MovChannelLayoutMap *map)
372 {
373 const struct MovChannelLayoutMap *layout_map;
374
375 /* find the channel layout for the specified layout tag */
376 44 layout_map = find_layout_map(tag, map);
377
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 if (layout_map) {
378 int ret;
379 44 int map_layout_nb_channels = tag & 0xFFFF;
380 44 int nb_channels = ch_layout->nb_channels;
381
382 /* Omitted channel bits must not exceed number of channels in map */
383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (omitted_channel_map >> map_layout_nb_channels)
384 return AVERROR_INVALIDDATA;
385
386 44 av_channel_layout_uninit(ch_layout);
387 44 ret = av_channel_layout_custom_init(ch_layout, nb_channels);
388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (ret < 0)
389 return ret;
390
391
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) {
392
1/2
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
79 if (!(omitted_channel_map & 1)) {
393 79 enum AVChannel id = layout_map[i].id;
394
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);
395 }
396 }
397
398 44 return av_channel_layout_retype(ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
399 }
400 return 0;
401 }
402
403 3 static enum AVChannel mov_get_channel_id(uint32_t label)
404 {
405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (label == 0)
406 return AV_CHAN_UNUSED;
407
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (label <= 18)
408 1 return (label - 1);
409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (label == 35)
410 return AV_CHAN_WIDE_LEFT;
411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (label == 36)
412 return AV_CHAN_WIDE_RIGHT;
413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (label == 37)
414 return AV_CHAN_LOW_FREQUENCY_2;
415
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (label == 38)
416 1 return AV_CHAN_STEREO_LEFT;
417
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (label == 39)
418 1 return AV_CHAN_STEREO_RIGHT;
419 return AV_CHAN_UNKNOWN;
420 }
421
422 2 static uint32_t mov_get_channel_label(enum AVChannel channel)
423 {
424
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (channel < 0)
425 return 0;
426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (channel <= AV_CHAN_TOP_BACK_RIGHT)
427 return channel + 1;
428
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (channel == AV_CHAN_WIDE_LEFT)
429 return 35;
430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (channel == AV_CHAN_WIDE_RIGHT)
431 return 36;
432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (channel == AV_CHAN_LOW_FREQUENCY_2)
433 return 37;
434
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (channel == AV_CHAN_STEREO_LEFT)
435 1 return 38;
436
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (channel == AV_CHAN_STEREO_RIGHT)
437 1 return 39;
438 return 0;
439 }
440
441 165 static int is_layout_valid_for_tag(const AVChannelLayout *ch_layout, uint32_t tag, const struct MovChannelLayoutMap *map)
442 {
443 const struct MovChannelLayoutMap *layout_map;
444 165 int channels = ch_layout->nb_channels;
445
446 /* get the layout map based on the channel count */
447
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 35 times.
165 if ((tag & 0xFFFF) != channels)
448 130 return 0;
449
450 35 layout_map = find_layout_map(tag, map);
451
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if (layout_map) {
452 int i;
453
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 20 times.
73 for (i = 0; i < channels; i++) {
454
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)
455 15 break;
456 }
457
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 15 times.
35 if (i == channels)
458 20 return 1;
459 }
460 15 return 0;
461 }
462
463 40 int ff_mov_get_channel_layout_tag(const AVCodecParameters *par,
464 uint32_t *layout,
465 uint32_t *bitmap,
466 uint32_t **pchannel_desc)
467 {
468 int i;
469 40 uint32_t tag = 0;
470 40 const enum MovChannelLayoutTag *layouts = NULL;
471
472 /* find the layout list for the specified codec */
473
2/2
✓ Branch 0 taken 328 times.
✓ Branch 1 taken 14 times.
342 for (i = 0; mov_codec_ch_layouts[i].codec_id != AV_CODEC_ID_NONE; i++) {
474
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 302 times.
328 if (mov_codec_ch_layouts[i].codec_id == par->codec_id)
475 26 break;
476 }
477
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 14 times.
40 if (mov_codec_ch_layouts[i].codec_id != AV_CODEC_ID_NONE)
478 26 layouts = mov_codec_ch_layouts[i].layouts;
479
480
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 14 times.
40 if (layouts) {
481 /* find the layout tag for the specified channel layout */
482
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 7 times.
118 for (i = 0; layouts[i] != 0; i++)
483
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))
484 19 break;
485
486 26 tag = layouts[i];
487 }
488
489 40 *layout = tag;
490 40 *bitmap = 0;
491 40 *pchannel_desc = NULL;
492
493 /* if no tag was found, use channel bitmap or description as a backup if possible */
494
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 19 times.
40 if (tag == 0) {
495 uint32_t *channel_desc;
496
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE &&
497
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 2 times.
21 par->ch_layout.u.mask < 0x40000) {
498 19 *layout = MOV_CH_LAYOUT_USE_BITMAP;
499 19 *bitmap = (uint32_t)par->ch_layout.u.mask;
500 19 return 0;
501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } else if (par->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
502 return AVERROR(ENOSYS);
503
504 2 channel_desc = av_malloc_array(par->ch_layout.nb_channels, sizeof(*channel_desc));
505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!channel_desc)
506 return AVERROR(ENOMEM);
507
508
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (i = 0; i < par->ch_layout.nb_channels; i++) {
509 4 channel_desc[i] =
510 2 mov_get_channel_label(av_channel_layout_channel_from_index(&par->ch_layout, i));
511
512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (channel_desc[i] == 0) {
513 av_free(channel_desc);
514 return AVERROR(ENOSYS);
515 }
516 }
517
518 2 *pchannel_desc = channel_desc;
519 }
520
521 21 return 0;
522 }
523
524 61 int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st,
525 int64_t size)
526 {
527 uint32_t layout_tag, bitmap, num_descr;
528 int ret;
529 61 AVChannelLayout *ch_layout = &st->codecpar->ch_layout;
530
531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if (size < 12)
532 return AVERROR_INVALIDDATA;
533
534 61 layout_tag = avio_rb32(pb);
535 61 bitmap = avio_rb32(pb);
536 61 num_descr = avio_rb32(pb);
537
538 61 av_log(s, AV_LOG_DEBUG, "chan: layout=%"PRIu32" "
539 "bitmap=%"PRIu32" num_descr=%"PRIu32"\n",
540 layout_tag, bitmap, num_descr);
541
542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if (size < 12ULL + num_descr * 20ULL)
543 return 0;
544
545
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 58 times.
61 if (layout_tag == MOV_CH_LAYOUT_USE_DESCRIPTIONS) {
546 3 int nb_channels = ch_layout->nb_channels;
547
548
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (!num_descr || num_descr < nb_channels) {
549 av_log(s, AV_LOG_ERROR, "got %d channel descriptions when at least %d were needed\n",
550 num_descr, nb_channels);
551 return AVERROR_INVALIDDATA;
552 }
553
554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (num_descr > nb_channels) {
555 int strict = s->strict_std_compliance >= FF_COMPLIANCE_STRICT;
556 av_log(s, strict ? AV_LOG_ERROR : AV_LOG_WARNING,
557 "got %d channel descriptions when number of channels is %d\n",
558 num_descr, nb_channels);
559 if (strict)
560 return AVERROR_INVALIDDATA;
561 av_log(s, AV_LOG_WARNING, "capping channel descriptions to the number of channels\n");
562 num_descr = nb_channels;
563 }
564
565 3 av_channel_layout_uninit(ch_layout);
566 3 ret = av_channel_layout_custom_init(ch_layout, nb_channels);
567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
568 goto out;
569
570
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 for (int i = 0; i < num_descr; i++) {
571 uint32_t label;
572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (pb->eof_reached) {
573 av_log(s, AV_LOG_ERROR,
574 "reached EOF while reading channel layout\n");
575 return AVERROR_INVALIDDATA;
576 }
577 3 label = avio_rb32(pb); // mChannelLabel
578 3 avio_rb32(pb); // mChannelFlags
579 3 avio_rl32(pb); // mCoordinates[0]
580 3 avio_rl32(pb); // mCoordinates[1]
581 3 avio_rl32(pb); // mCoordinates[2]
582 3 size -= 20;
583 3 ch_layout->u.map[i].id = mov_get_channel_id(label);
584 }
585
586 3 ret = av_channel_layout_retype(ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
588 goto out;
589
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 43 times.
58 } else if (layout_tag == MOV_CH_LAYOUT_USE_BITMAP) {
590
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
15 if (!ch_layout->nb_channels || av_popcount(bitmap) == ch_layout->nb_channels) {
591
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (bitmap < 0x40000) {
592 15 av_channel_layout_uninit(ch_layout);
593 15 av_channel_layout_from_mask(ch_layout, bitmap);
594 }
595 } else {
596 av_log(s, AV_LOG_WARNING, "ignoring channel layout bitmap with %d channels because number of channels is %d\n",
597 av_popcount64(bitmap), ch_layout->nb_channels);
598 }
599
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 } else if (layout_tag & 0xFFFF) {
600 43 int nb_channels = layout_tag & 0xFFFF;
601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (!ch_layout->nb_channels)
602 ch_layout->nb_channels = nb_channels;
603
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 if (nb_channels == ch_layout->nb_channels) {
604 43 ret = mov_get_channel_layout(ch_layout, layout_tag, 0, mov_ch_layout_map);
605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
43 if (ret < 0)
606 return ret;
607 } else {
608 av_log(s, AV_LOG_WARNING, "ignoring layout tag with %d channels because number of channels is %d\n",
609 nb_channels, ch_layout->nb_channels);
610 }
611 }
612 61 ret = 0;
613
614 61 out:
615 61 avio_skip(pb, size - 12);
616
617 61 return ret;
618 }
619
620 /* ISO/IEC 23001-8, table 8 */
621 static const enum AVChannel iso_channel_position[] = {
622 [0] = AV_CHAN_FRONT_LEFT, // left front
623 [1] = AV_CHAN_FRONT_RIGHT, // right front
624 [2] = AV_CHAN_FRONT_CENTER, // centre front
625 [3] = AV_CHAN_LOW_FREQUENCY, // low frequency enhancement
626 [4] = AV_CHAN_SIDE_LEFT, // left surround
627 [5] = AV_CHAN_SIDE_RIGHT, // right surround
628 [6] = AV_CHAN_FRONT_LEFT_OF_CENTER, // left front centre
629 [7] = AV_CHAN_FRONT_RIGHT_OF_CENTER, // right front centre
630 [8] = AV_CHAN_BACK_LEFT, // rear surround left
631 [9] = AV_CHAN_BACK_RIGHT, // rear surround right
632 [10] = AV_CHAN_BACK_CENTER, // rear centre
633 [11] = AV_CHAN_SURROUND_DIRECT_LEFT, // left surround direct
634 [12] = AV_CHAN_SURROUND_DIRECT_RIGHT, // right surround direct
635 [13] = AV_CHAN_SIDE_SURROUND_LEFT, // left side surround
636 [14] = AV_CHAN_SIDE_SURROUND_RIGHT, // right side surround
637 [15] = AV_CHAN_WIDE_LEFT, // left wide front
638 [16] = AV_CHAN_WIDE_RIGHT, // right wide front
639 [17] = AV_CHAN_TOP_FRONT_LEFT, // left front vertical height
640 [18] = AV_CHAN_TOP_FRONT_RIGHT, // right front vertical height
641 [19] = AV_CHAN_TOP_FRONT_CENTER, // centre front vertical height
642 [20] = AV_CHAN_TOP_BACK_LEFT, // left surround vertical height rear
643 [21] = AV_CHAN_TOP_BACK_RIGHT, // right surround vertical height rear
644 [22] = AV_CHAN_TOP_BACK_CENTER, // centre vertical height rear
645 [23] = AV_CHAN_TOP_SIDE_LEFT, // left vertical height side surround
646 [24] = AV_CHAN_TOP_SIDE_RIGHT, // right vertical height side surround
647 [25] = AV_CHAN_TOP_CENTER, // top centre surround
648 [26] = AV_CHAN_LOW_FREQUENCY_2, // low frequency enhancement 2
649 [27] = AV_CHAN_BOTTOM_FRONT_LEFT, // left front vertical bottom
650 [28] = AV_CHAN_BOTTOM_FRONT_RIGHT, // right front vertical bottom
651 [29] = AV_CHAN_BOTTOM_FRONT_CENTER, // centre front vertical bottom
652 [30] = AV_CHAN_TOP_SURROUND_LEFT, // left vertical height surround
653 [31] = AV_CHAN_TOP_SURROUND_RIGHT, // right vertical height surround
654
655 [32] = AV_CHAN_NONE, // reserved
656 [33] = AV_CHAN_NONE, // reserved
657 [34] = AV_CHAN_NONE, // reserved
658 [35] = AV_CHAN_NONE, // reserved
659
660 [36] = AV_CHAN_NONE, // low frequency enhancement 3
661 [37] = AV_CHAN_NONE, // left edge of screen
662 [38] = AV_CHAN_NONE, // right edge of screen
663 [39] = AV_CHAN_NONE, // half-way between centre of screen and left edge of screen
664 [40] = AV_CHAN_NONE, // half-way between centre of screen and right edge of screen
665 [41] = AV_CHAN_NONE, // left back surround
666 [42] = AV_CHAN_NONE, // right back surround
667
668 // 43 - 125: reserved
669 // 126: explicit position
670 // 127: unknown /undefined
671 };
672
673 5 int ff_mov_get_channel_config_from_layout(const AVChannelLayout *layout, int *config)
674 {
675 // Set default value which means any setup in 23001-8
676 5 *config = 0;
677
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)) {
678
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])) {
679 1 *config = iso_ch_layout_map[i].tag >> 16;
680 1 break;
681 }
682 }
683
684 5 return 0;
685 }
686
687 1 int ff_mov_get_channel_layout_from_config(int config, AVChannelLayout *layout, uint64_t omitted_channel_map)
688 {
689
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (config > 0) {
690 uint32_t layout_tag;
691 1 int nb_omitted_channels = av_popcount64(omitted_channel_map);
692
693
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)
694 return AVERROR_INVALIDDATA;
695
696 1 layout_tag = (config << 16) | (layout->nb_channels + nb_omitted_channels);
697 1 return mov_get_channel_layout(layout, layout_tag, omitted_channel_map, iso_ch_layout_map);
698 }
699 return 1;
700 }
701
702 4 int ff_mov_get_channel_positions_from_layout(const AVChannelLayout *layout,
703 uint8_t *position, int position_num)
704 {
705 enum AVChannel channel;
706
707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (position_num < layout->nb_channels)
708 return AVERROR(EINVAL);
709
710
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int i = 0; i < layout->nb_channels; i++) {
711 20 position[i] = 127;
712 20 channel = av_channel_layout_channel_from_index(layout, i);
713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (channel == AV_CHAN_NONE)
714 return AVERROR(EINVAL);
715
716
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 for (int j = 0; j < FF_ARRAY_ELEMS(iso_channel_position); j++) {
717
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 61 times.
81 if (iso_channel_position[j] == channel) {
718 20 position[i] = j;
719 20 break;
720 }
721 }
722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (position[i] == 127)
723 return AVERROR(EINVAL);
724 }
725
726 4 return 0;
727 }
728
729 5 int ff_mov_read_chnl(AVFormatContext *s, AVIOContext *pb, AVStream *st)
730 {
731 5 int stream_structure = avio_r8(pb);
732 int ret;
733
734 // stream carries channels
735
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (stream_structure & 1) {
736 5 int layout = avio_r8(pb);
737
738 5 av_log(s, AV_LOG_TRACE, "'chnl' layout %d\n", layout);
739
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (!layout) {
740 4 AVChannelLayout *ch_layout = &st->codecpar->ch_layout;
741 4 int nb_channels = ch_layout->nb_channels;
742
743 4 av_channel_layout_uninit(ch_layout);
744 4 ret = av_channel_layout_custom_init(ch_layout, nb_channels);
745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
746 return ret;
747
748
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 for (int i = 0; i < nb_channels; i++) {
749 20 int speaker_pos = avio_r8(pb);
750 enum AVChannel channel;
751
752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (speaker_pos == 126) // explicit position
753 avio_skip(pb, 3); // azimuth, elevation
754
755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (speaker_pos >= FF_ARRAY_ELEMS(iso_channel_position))
756 channel = AV_CHAN_NONE;
757 else
758 20 channel = iso_channel_position[speaker_pos];
759
760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (channel == AV_CHAN_NONE) {
761 av_log(s, AV_LOG_WARNING, "speaker position %d is not implemented\n", speaker_pos);
762 channel = AV_CHAN_UNKNOWN;
763 }
764
765 20 ch_layout->u.map[i].id = channel;
766 }
767
768 4 ret = av_channel_layout_retype(ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
770 return ret;
771 } else {
772 1 uint64_t omitted_channel_map = avio_rb64(pb);
773 1 ret = ff_mov_get_channel_layout_from_config(layout, &st->codecpar->ch_layout, omitted_channel_map);
774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
775 return ret;
776 }
777 }
778
779 // stream carries objects
780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (stream_structure & 2) {
781 int obj_count = avio_r8(pb);
782 av_log(s, AV_LOG_TRACE, "'chnl' with object_count %d\n", obj_count);
783 }
784
785 5 return 0;
786 }
787