1 /*******************************************************************************
2 chan.c
3
4 libquicktime - A library for reading and writing quicktime/avi/mp4 files.
5 http://libquicktime.sourceforge.net
6
7 Copyright (C) 2002 Heroine Virtual Ltd.
8 Copyright (C) 2002-2011 Members of the libquicktime project.
9
10 This library is free software; you can redistribute it and/or modify it under
11 the terms of the GNU Lesser General Public License as published by the Free
12 Software Foundation; either version 2.1 of the License, or (at your option)
13 any later version.
14
15 This library is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18 details.
19
20 You should have received a copy of the GNU Lesser General Public License along
21 with this library; if not, write to the Free Software Foundation, Inc., 51
22 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *******************************************************************************/
24
25 #include "lqt_private.h"
26 #include <stdlib.h>
27
28 /*
29 * Quicktime chan atom.
30 *
31 * I didn't find any official documentation about the channel
32 * description atom (which is needed for multichannel support).
33 * There is, however this document about the CAF format by Apple:
34 *
35 * http://developer.apple.com/documentation/MusicAudio/Reference/CAFSpec/index.html
36
37 * The guess was, that the chan atoms in CAF and Quicktime files are the same,
38 * and the guess turned out to be true :)
39 */
40
41 typedef enum
42 {
43 CHANNEL_LABEL_Unknown = 0xFFFFFFFF, // unknown role or uspecified
44 // other use for channel
45 CHANNEL_LABEL_Unused = 0, // channel is present, but
46 // has no intended role or destination
47 CHANNEL_LABEL_UseCoordinates = 100, // channel is described
48 // solely by the mCoordinates fields
49
50 CHANNEL_LABEL_Left = 1,
51 CHANNEL_LABEL_Right = 2,
52 CHANNEL_LABEL_Center = 3,
53 CHANNEL_LABEL_LFEScreen = 4,
54 CHANNEL_LABEL_LeftSurround = 5, // WAVE (.wav files): "Back Left"
55 CHANNEL_LABEL_RightSurround = 6, // WAVE: "Back Right"
56 CHANNEL_LABEL_LeftCenter = 7,
57 CHANNEL_LABEL_RightCenter = 8,
58 CHANNEL_LABEL_CenterSurround = 9, // WAVE: "Back Center or
59 // plain "Rear Surround"
60 CHANNEL_LABEL_LeftSurroundDirect = 10, // WAVE: "Side Left"
61 CHANNEL_LABEL_RightSurroundDirect = 11, // WAVE: "Side Right"
62 CHANNEL_LABEL_TopCenterSurround = 12,
63 CHANNEL_LABEL_VerticalHeightLeft = 13, // WAVE: "Top Front Left
64 CHANNEL_LABEL_VerticalHeightCenter = 14, // WAVE: "Top Front Center
65 CHANNEL_LABEL_VerticalHeightRight = 15, // WAVE: "Top Front Right
66 CHANNEL_LABEL_TopBackLeft = 16,
67 CHANNEL_LABEL_TopBackCenter = 17,
68 CHANNEL_LABEL_TopBackRight = 18,
69 CHANNEL_LABEL_RearSurroundLeft = 33,
70 CHANNEL_LABEL_RearSurroundRight = 34,
71 CHANNEL_LABEL_LeftWide = 35,
72 CHANNEL_LABEL_RightWide = 36,
73 CHANNEL_LABEL_LFE2 = 37,
74 CHANNEL_LABEL_LeftTotal = 38, // matrix encoded 4 channels
75 CHANNEL_LABEL_RightTotal = 39, // matrix encoded 4 channels
76 CHANNEL_LABEL_HearingImpaired = 40,
77 CHANNEL_LABEL_Narration = 41,
78 CHANNEL_LABEL_Mono = 42,
79 CHANNEL_LABEL_DialogCentricMix = 43,
80
81 CHANNEL_LABEL_CenterSurroundDirect = 44, // back center, non diffuse
82
83 // first order ambisonic channels
84
85 CHANNEL_LABEL_Ambisonic_W = 200,
86 CHANNEL_LABEL_Ambisonic_X = 201,
87 CHANNEL_LABEL_Ambisonic_Y = 202,
88 CHANNEL_LABEL_Ambisonic_Z = 203,
89
90 // Mid/Side Recording
91
92 CHANNEL_LABEL_MS_Mid = 204,
93 CHANNEL_LABEL_MS_Side = 205,
94
95 // X-Y Recording
96
97 CHANNEL_LABEL_XY_X = 206,
98 CHANNEL_LABEL_XY_Y = 207,
99
100 // other
101
102 CHANNEL_LABEL_HeadphonesLeft = 301,
103 CHANNEL_LABEL_HeadphonesRight = 302,
104 CHANNEL_LABEL_ClickTrack = 304,
105 CHANNEL_LABEL_ForeignLanguage = 305
106 } channel_label_t;
107
108 static struct
109 {
110 channel_label_t label;
111 char * name;
112 }
113 channel_label_names[] =
114 {
115 { CHANNEL_LABEL_Unknown, "Unknown" },
116 { CHANNEL_LABEL_Unused, "Unused" },
117 // has no intended role or destination
118 { CHANNEL_LABEL_UseCoordinates, "Use Coordinates" },
119
120 { CHANNEL_LABEL_Left, "Left" },
121 { CHANNEL_LABEL_Right, "Right" },
122 { CHANNEL_LABEL_Center, "Center" },
123 { CHANNEL_LABEL_LFEScreen, "LFE" },
124 { CHANNEL_LABEL_LeftSurround, "Left Surround" }, // WAVE (.wav files): Back Left
125 { CHANNEL_LABEL_RightSurround, "Right Surround" }, // WAVE: "Back Right"
126 { CHANNEL_LABEL_LeftCenter, "Left Center" },
127 { CHANNEL_LABEL_RightCenter, "Right Center" },
128 { CHANNEL_LABEL_CenterSurround, "Center Surround" }, // WAVE: "Back Center or
129 // plain "Rear Surround"
130 { CHANNEL_LABEL_LeftSurroundDirect, "Side Left" }, // WAVE: "Side Left"
131 { CHANNEL_LABEL_RightSurroundDirect, "Side Right" }, // WAVE: "Side Right"
132 { CHANNEL_LABEL_TopCenterSurround, "Top Center Surround" },
133 { CHANNEL_LABEL_VerticalHeightLeft, "Top Front Left" }, // WAVE: Top Front Left
134 { CHANNEL_LABEL_VerticalHeightCenter, "Top Front Center" }, // WAVE: Top Front Center
135 { CHANNEL_LABEL_VerticalHeightRight, "Top Front Right" }, // WAVE: "Top Front Right"
136 { CHANNEL_LABEL_TopBackLeft, "Top Back Left" },
137 { CHANNEL_LABEL_TopBackCenter, "Top Back Center" } ,
138 { CHANNEL_LABEL_TopBackRight, "Top Back Right" },
139 { CHANNEL_LABEL_RearSurroundLeft, "Rear Surround Left" },
140 { CHANNEL_LABEL_RearSurroundRight, "Rear Surround Right" },
141 { CHANNEL_LABEL_LeftWide, "Left Wide" },
142 { CHANNEL_LABEL_RightWide, "Right Wide" },
143 { CHANNEL_LABEL_LFE2, "LFE 2" },
144 { CHANNEL_LABEL_LeftTotal, "Left Total" }, // matrix encoded 4 channels
145 { CHANNEL_LABEL_RightTotal, "Right Total" }, // matrix encoded 4 channels
146 { CHANNEL_LABEL_HearingImpaired, "Hearing Impaired" },
147 { CHANNEL_LABEL_Narration, "Narration" },
148 { CHANNEL_LABEL_Mono, "Mono" },
149 { CHANNEL_LABEL_DialogCentricMix, "Dialog Centric Mix" },
150
151 { CHANNEL_LABEL_CenterSurroundDirect, "Center Surround Direct" }, // back center, non diffuse
152
153 // first order ambisonic channels
154
155 { CHANNEL_LABEL_Ambisonic_W, "Ambisonic W" },
156 { CHANNEL_LABEL_Ambisonic_X, "Ambisonic X" },
157 { CHANNEL_LABEL_Ambisonic_Y, "Ambisonic Y" },
158 { CHANNEL_LABEL_Ambisonic_Z, "Ambisonic Z" },
159
160 // Mid/Side Recording
161
162 { CHANNEL_LABEL_MS_Mid, "MS Mid" },
163 { CHANNEL_LABEL_MS_Side, "MS Side" },
164
165 // X-Y Recording
166
167 { CHANNEL_LABEL_XY_X, "Label XY X" },
168 { CHANNEL_LABEL_XY_Y, "Label XY Y" },
169
170 // other
171
172 { CHANNEL_LABEL_HeadphonesLeft, "Headphones Left" },
173 { CHANNEL_LABEL_HeadphonesRight, "Headphones Right" },
174 { CHANNEL_LABEL_ClickTrack, "Click Track" },
175 { CHANNEL_LABEL_ForeignLanguage, "Foreign Language" },
176
177 };
178
get_channel_name(channel_label_t label)179 static const char * get_channel_name(channel_label_t label)
180 {
181 int i;
182 for(i = 0; i < sizeof(channel_label_names)/sizeof(channel_label_names[0]); i++)
183 {
184 if(channel_label_names[i].label == label)
185 return channel_label_names[i].name;
186 }
187 return (char*)0;
188 }
189
190 typedef enum
191 {
192 CHANNEL_BIT_Left = (1<<0),
193 CHANNEL_BIT_Right = (1<<1),
194 CHANNEL_BIT_Center = (1<<2),
195 CHANNEL_BIT_LFEScreen = (1<<3),
196 CHANNEL_BIT_LeftSurround = (1<<4), // WAVE: "Back Left"
197 CHANNEL_BIT_RightSurround = (1<<5), // WAVE: "Back Right"
198 CHANNEL_BIT_LeftCenter = (1<<6),
199 CHANNEL_BIT_RightCenter = (1<<7),
200 CHANNEL_BIT_CenterSurround = (1<<8), // WAVE: "Back Center"
201 CHANNEL_BIT_LeftSurroundDirect = (1<<9), // WAVE: "Side Left"
202 CHANNEL_BIT_RightSurroundDirect = (1<<10), // WAVE: "Side Right"
203 CHANNEL_BIT_TopCenterSurround = (1<<11),
204 CHANNEL_BIT_VerticalHeightLeft = (1<<12), // WAVE: "Top Front Left"
205 CHANNEL_BIT_VerticalHeightCenter = (1<<13), // WAVE: "Top Front Center"
206 CHANNEL_BIT_VerticalHeightRight = (1<<14), // WAVE: "Top Front Right"
207 CHANNEL_BIT_TopBackLeft = (1<<15),
208 CHANNEL_BIT_TopBackCenter = (1<<16),
209 CHANNEL_BIT_TopBackRight = (1<<17)
210 } channel_bit_t;
211
212 static struct
213 {
214 channel_bit_t bit;
215 channel_label_t label;
216 }
217 channel_bits[] =
218 {
219 { CHANNEL_BIT_Left, CHANNEL_LABEL_Left },
220 { CHANNEL_BIT_Right, CHANNEL_LABEL_Right },
221 { CHANNEL_BIT_Center, CHANNEL_LABEL_Center },
222 { CHANNEL_BIT_LFEScreen, CHANNEL_LABEL_LFEScreen },
223 { CHANNEL_BIT_LeftSurround, CHANNEL_LABEL_LeftSurround }, // WAVE: "Back Left"
224 { CHANNEL_BIT_RightSurround, CHANNEL_LABEL_RightSurround },// WAVE: "Back Right"
225 { CHANNEL_BIT_LeftCenter, CHANNEL_LABEL_LeftCenter },
226 { CHANNEL_BIT_RightCenter, CHANNEL_LABEL_RightCenter },
227 { CHANNEL_BIT_CenterSurround, CHANNEL_LABEL_CenterSurround }, // WAVE: "Back Center"
228 { CHANNEL_BIT_LeftSurroundDirect, CHANNEL_LABEL_LeftSurroundDirect }, // WAVE: "Side Left"
229 { CHANNEL_BIT_RightSurroundDirect, CHANNEL_LABEL_RightSurroundDirect }, // WAVE: "Side Right"
230 { CHANNEL_BIT_TopCenterSurround, CHANNEL_LABEL_TopCenterSurround },
231 { CHANNEL_BIT_VerticalHeightLeft, CHANNEL_LABEL_VerticalHeightLeft }, // WAVE: "Top Front Left"
232 { CHANNEL_BIT_VerticalHeightCenter, CHANNEL_LABEL_VerticalHeightCenter }, // WAVE: "Top Front Center"
233 { CHANNEL_BIT_VerticalHeightRight, CHANNEL_LABEL_VerticalHeightRight }, // WAVE: "Top Front Right"
234 { CHANNEL_BIT_TopBackLeft, CHANNEL_LABEL_TopBackLeft },
235 { CHANNEL_BIT_TopBackCenter, CHANNEL_LABEL_TopBackCenter },
236 { CHANNEL_BIT_TopBackRight, CHANNEL_LABEL_TopBackRight },
237 };
238
channel_bit_2_channel_label(uint32_t bit)239 static channel_label_t channel_bit_2_channel_label(uint32_t bit)
240 {
241 int i;
242 for(i = 0; i < sizeof(channel_bits) / sizeof(channel_bits[0]); i++)
243 {
244 if(bit == channel_bits[i].bit)
245 return channel_bits[i].label;
246 }
247 return CHANNEL_LABEL_Unknown;
248 }
249
250 static struct
251 {
252 lqt_channel_t lqt_channel;
253 channel_label_t channel_label;
254 }
255 lqt_channels[] =
256 {
257 { LQT_CHANNEL_UNKNOWN, CHANNEL_LABEL_Unknown },
258 { LQT_CHANNEL_FRONT_LEFT, CHANNEL_LABEL_Left },
259 { LQT_CHANNEL_FRONT_RIGHT, CHANNEL_LABEL_Right },
260 { LQT_CHANNEL_FRONT_CENTER, CHANNEL_LABEL_Center },
261 { LQT_CHANNEL_FRONT_CENTER_LEFT, CHANNEL_LABEL_LeftCenter },
262 { LQT_CHANNEL_FRONT_CENTER_RIGHT, CHANNEL_LABEL_RightCenter },
263 { LQT_CHANNEL_BACK_CENTER, CHANNEL_LABEL_CenterSurround },
264 { LQT_CHANNEL_BACK_LEFT, CHANNEL_LABEL_LeftSurround },
265 { LQT_CHANNEL_BACK_RIGHT, CHANNEL_LABEL_RightSurround },
266 { LQT_CHANNEL_SIDE_LEFT, CHANNEL_LABEL_LeftSurroundDirect },
267 { LQT_CHANNEL_SIDE_RIGHT, CHANNEL_LABEL_RightSurroundDirect },
268 { LQT_CHANNEL_LFE, CHANNEL_LABEL_LFEScreen },
269 };
270
channel_label_2_channel(channel_label_t channel_label)271 static lqt_channel_t channel_label_2_channel(channel_label_t channel_label)
272 {
273 int i;
274 for(i = 0; i < sizeof(lqt_channels)/sizeof(lqt_channels[0]); i++)
275 {
276 if(lqt_channels[i].channel_label == channel_label)
277 return lqt_channels[i].lqt_channel;
278 }
279 return LQT_CHANNEL_UNKNOWN;
280 }
281
channel_2_channel_label(lqt_channel_t channel)282 static channel_label_t channel_2_channel_label(lqt_channel_t channel)
283 {
284 int i;
285 for(i = 0; i < sizeof(lqt_channels)/sizeof(lqt_channels[0]); i++)
286 {
287 if(lqt_channels[i].lqt_channel == channel)
288 return lqt_channels[i].channel_label;
289 }
290 return CHANNEL_LABEL_Unknown;
291 }
292
293
294 /* Layout tags */
295
296 typedef enum
297 {
298 CHANNEL_LAYOUT_UseChannelDescriptions = (0<<16) | 0, // use the array of AudioChannelDescriptions to define the mapping.
299 CHANNEL_LAYOUT_UseChannelBitmap = (1<<16) | 0, // use the bitmap to define the mapping.
300
301 // 1 Channel Layout
302
303 CHANNEL_LAYOUT_Mono = (100<<16) | 1, // a standard mono stream
304
305 // 2 Channel layouts
306
307 CHANNEL_LAYOUT_Stereo = (101<<16) | 2, // a standard stereo stream (L R)
308 CHANNEL_LAYOUT_StereoHeadphones = (102<<16) | 2, // a standard stereo stream (L R) - implied headphone playback
309
310 CHANNEL_LAYOUT_MatrixStereo = (103<<16) | 2, // a matrix encoded stereo stream (Lt, Rt)
311 CHANNEL_LAYOUT_MidSide = (104<<16) | 2, // mid/side recording
312 CHANNEL_LAYOUT_XY = (105<<16) | 2, // coincident mic pair (often 2 figure 8's)
313
314 CHANNEL_LAYOUT_Binaural = (106<<16) | 2, // binaural stereo (left, right)
315
316 // Symetric arrangements - same distance between speaker locations
317
318 CHANNEL_LAYOUT_Ambisonic_B_Format = (107<<16) | 4, // W, X, Y, Z
319 CHANNEL_LAYOUT_Quadraphonic = (108<<16) | 4, // front left, front right, back left, back right
320 CHANNEL_LAYOUT_Pentagonal = (109<<16) | 5, // left, right, rear left, rear right, center
321 CHANNEL_LAYOUT_Hexagonal = (110<<16) | 6, // left, right, rear left, rear right, center, rear
322 CHANNEL_LAYOUT_Octagonal = (111<<16) | 8, // front left, front right, rear left, rear right,
323 // front center, rear center, side left, side right
324 CHANNEL_LAYOUT_Cube = (112<<16) | 8, // left, right, rear left, rear right
325 // top left, top right, top rear left, top rear right
326
327 // MPEG defined layouts
328
329 CHANNEL_LAYOUT_MPEG_1_0 = CHANNEL_LAYOUT_Mono, // C
330 CHANNEL_LAYOUT_MPEG_2_0 = CHANNEL_LAYOUT_Stereo, // L R
331 CHANNEL_LAYOUT_MPEG_3_0_A = (113<<16) | 3, // L R C
332 CHANNEL_LAYOUT_MPEG_3_0_B = (114<<16) | 3, // C L R
333 CHANNEL_LAYOUT_MPEG_4_0_A = (115<<16) | 4, // L R C Cs
334 CHANNEL_LAYOUT_MPEG_4_0_B = (116<<16) | 4, // C L R Cs
335 CHANNEL_LAYOUT_MPEG_5_0_A = (117<<16) | 5, // L R C Ls Rs
336 CHANNEL_LAYOUT_MPEG_5_0_B = (118<<16) | 5, // L R Ls Rs C
337 CHANNEL_LAYOUT_MPEG_5_0_C = (119<<16) | 5, // L C R Ls Rs
338 CHANNEL_LAYOUT_MPEG_5_0_D = (120<<16) | 5, // C L R Ls Rs
339 CHANNEL_LAYOUT_MPEG_5_1_A = (121<<16) | 6, // L R C LFE Ls Rs
340 CHANNEL_LAYOUT_MPEG_5_1_B = (122<<16) | 6, // L R Ls Rs C LFE
341 CHANNEL_LAYOUT_MPEG_5_1_C = (123<<16) | 6, // L C R Ls Rs LFE
342 CHANNEL_LAYOUT_MPEG_5_1_D = (124<<16) | 6, // C L R Ls Rs LFE
343 CHANNEL_LAYOUT_MPEG_6_1_A = (125<<16) | 7, // L R C LFE Ls Rs Cs
344 CHANNEL_LAYOUT_MPEG_7_1_A = (126<<16) | 8, // L R C LFE Ls Rs Lc Rc
345 CHANNEL_LAYOUT_MPEG_7_1_B = (127<<16) | 8, // C Lc Rc L R Ls Rs LFE
346 CHANNEL_LAYOUT_MPEG_7_1_C = (128<<16) | 8, // L R C LFE Ls R Rls Rrs
347 CHANNEL_LAYOUT_Emagic_Default_7_1 = (129<<16) | 8, // L R Ls Rs C LFE Lc Rc
348 CHANNEL_LAYOUT_SMPTE_DTV = (130<<16) | 8, // L R C LFE Ls Rs Lt Rt
349 // (CHANNEL_LAYOUT_ITU_5_1 plus a matrix encoded stereo mix)
350
351 // ITU defined layouts
352
353 CHANNEL_LAYOUT_ITU_1_0 = CHANNEL_LAYOUT_Mono, // C
354 CHANNEL_LAYOUT_ITU_2_0 = CHANNEL_LAYOUT_Stereo, // L R
355 CHANNEL_LAYOUT_ITU_2_1 = (131<<16) | 3, // L R Cs
356 CHANNEL_LAYOUT_ITU_2_2 = (132<<16) | 4, // L R Ls Rs
357 CHANNEL_LAYOUT_ITU_3_0 = CHANNEL_LAYOUT_MPEG_3_0_A, // L R C
358 CHANNEL_LAYOUT_ITU_3_1 = CHANNEL_LAYOUT_MPEG_4_0_A, // L R C Cs
359 CHANNEL_LAYOUT_ITU_3_2 = CHANNEL_LAYOUT_MPEG_5_0_A, // L R C Ls Rs
360 CHANNEL_LAYOUT_ITU_3_2_1 = CHANNEL_LAYOUT_MPEG_5_1_A, // L R C LFE Ls Rs
361 CHANNEL_LAYOUT_ITU_3_4_1 = CHANNEL_LAYOUT_MPEG_7_1_C, // L R C LFE Ls Rs Rls Rrs
362
363 // DVD defined layouts
364
365 CHANNEL_LAYOUT_DVD_0 = CHANNEL_LAYOUT_Mono, // C (mono)
366 CHANNEL_LAYOUT_DVD_1 = CHANNEL_LAYOUT_Stereo, // L R
367 CHANNEL_LAYOUT_DVD_2 = CHANNEL_LAYOUT_ITU_2_1, // L R Cs
368 CHANNEL_LAYOUT_DVD_3 = CHANNEL_LAYOUT_ITU_2_2, // L R Ls Rs
369 CHANNEL_LAYOUT_DVD_4 = (133<<16) | 3, // L R LFE
370 CHANNEL_LAYOUT_DVD_5 = (134<<16) | 4, // L R LFE Cs
371 CHANNEL_LAYOUT_DVD_6 = (135<<16) | 5, // L R LFE Ls Rs
372 CHANNEL_LAYOUT_DVD_7 = CHANNEL_LAYOUT_MPEG_3_0_A,// L R C
373 CHANNEL_LAYOUT_DVD_8 = CHANNEL_LAYOUT_MPEG_4_0_A,// L R C Cs
374 CHANNEL_LAYOUT_DVD_9 = CHANNEL_LAYOUT_MPEG_5_0_A,// L R C Ls Rs
375 CHANNEL_LAYOUT_DVD_10 = (136<<16) | 4, // L R C LFE
376 CHANNEL_LAYOUT_DVD_11 = (137<<16) | 5, // L R C LFE Cs
377 CHANNEL_LAYOUT_DVD_12 = CHANNEL_LAYOUT_MPEG_5_1_A,// L R C LFE Ls Rs
378
379 // 13 through 17 are duplicates of 8 through 12.
380
381 CHANNEL_LAYOUT_DVD_13 = CHANNEL_LAYOUT_DVD_8, // L R C Cs
382 CHANNEL_LAYOUT_DVD_14 = CHANNEL_LAYOUT_DVD_9, // L R C Ls Rs
383 CHANNEL_LAYOUT_DVD_15 = CHANNEL_LAYOUT_DVD_10, // L R C LFE
384 CHANNEL_LAYOUT_DVD_16 = CHANNEL_LAYOUT_DVD_11, // L R C LFE Cs
385 CHANNEL_LAYOUT_DVD_17 = CHANNEL_LAYOUT_DVD_12, // L R C LFE Ls Rs
386 CHANNEL_LAYOUT_DVD_18 = (138<<16) | 5, // L R Ls Rs LFE
387 CHANNEL_LAYOUT_DVD_19 = CHANNEL_LAYOUT_MPEG_5_0_B,// L R Ls Rs C
388 CHANNEL_LAYOUT_DVD_20 = CHANNEL_LAYOUT_MPEG_5_1_B,// L R Ls Rs C LFE
389
390 // These layouts are recommended for Mac OS X's AudioUnit use
391 // These are the symmetrical layouts
392
393 CHANNEL_LAYOUT_AudioUnit_4= CHANNEL_LAYOUT_Quadraphonic,
394 CHANNEL_LAYOUT_AudioUnit_5= CHANNEL_LAYOUT_Pentagonal,
395 CHANNEL_LAYOUT_AudioUnit_6= CHANNEL_LAYOUT_Hexagonal,
396 CHANNEL_LAYOUT_AudioUnit_8= CHANNEL_LAYOUT_Octagonal,
397
398 // These are the surround-based layouts
399
400 CHANNEL_LAYOUT_AudioUnit_5_0 = CHANNEL_LAYOUT_MPEG_5_0_B, // L R Ls Rs C
401 CHANNEL_LAYOUT_AudioUnit_6_0 = (139<<16) | 6, // L R Ls Rs C Cs
402 CHANNEL_LAYOUT_AudioUnit_7_0 = (140<<16) | 7, // L R Ls Rs C Rls Rrs
403 CHANNEL_LAYOUT_AudioUnit_5_1 = CHANNEL_LAYOUT_MPEG_5_1_A, // L R C LFE Ls Rs
404 CHANNEL_LAYOUT_AudioUnit_6_1 = CHANNEL_LAYOUT_MPEG_6_1_A, // L R C LFE Ls Rs Cs
405 CHANNEL_LAYOUT_AudioUnit_7_1 = CHANNEL_LAYOUT_MPEG_7_1_C, // L R C LFE Ls Rs Rls Rrs
406
407 // These layouts are used for AAC Encoding within the MPEG-4 Specification
408
409 CHANNEL_LAYOUT_AAC_Quadraphonic = CHANNEL_LAYOUT_Quadraphonic, // L R Ls Rs
410 CHANNEL_LAYOUT_AAC_4_0= CHANNEL_LAYOUT_MPEG_4_0_B, // C L R Cs
411 CHANNEL_LAYOUT_AAC_5_0= CHANNEL_LAYOUT_MPEG_5_0_D, // C L R Ls Rs
412 CHANNEL_LAYOUT_AAC_5_1= CHANNEL_LAYOUT_MPEG_5_1_D, // C L R Ls Rs Lfe
413 CHANNEL_LAYOUT_AAC_6_0= (141<<16) | 6, // C L R Ls Rs Cs
414 CHANNEL_LAYOUT_AAC_6_1= (142<<16) | 7, // C L R Ls Rs Cs Lfe
415 CHANNEL_LAYOUT_AAC_7_0= (143<<16) | 7, // C L R Ls Rs Rls Rrs
416 CHANNEL_LAYOUT_AAC_7_1= CHANNEL_LAYOUT_MPEG_7_1_B, // C Lc Rc L R Ls Rs Lfe
417 CHANNEL_LAYOUT_AAC_Octagonal = (144<<16) | 8, // C L R Ls Rs Rls Rrs Cs
418 CHANNEL_LAYOUT_TMH_10_2_std = (145<<16) | 16, // L R C Vhc Lsd Rsd Ls Rs Vhl Vhr Lw Rw Csd Cs LFE1 LFE2
419 CHANNEL_LAYOUT_TMH_10_2_full = (146<<16) | 21, // TMH_10_2_std plus: Lc Rc HI VI Haptic
420 CHANNEL_LAYOUT_RESERVED_DO_NOT_USE= (147<<16)
421 } channel_layout_t;
422
423 static struct
424 {
425 channel_layout_t layout;
426 channel_label_t * channels;
427 }
428 channel_locations[] =
429 {
430 { CHANNEL_LAYOUT_Mono, (channel_label_t[]){ CHANNEL_LABEL_Center } }, // a standard mono stream
431
432 // 2 Channel layouts
433
434 { CHANNEL_LAYOUT_Stereo, (channel_label_t[]){ CHANNEL_LABEL_Left,
435 CHANNEL_LABEL_Right } }, // a standard stereo stream (L R)
436
437 { CHANNEL_LAYOUT_StereoHeadphones, (channel_label_t[]){ CHANNEL_LABEL_Left,
438 CHANNEL_LABEL_Right } }, // a standard stereo stream (L R) - implied headphone playback
439 { CHANNEL_LAYOUT_MatrixStereo, (channel_label_t[]){ CHANNEL_LABEL_LeftTotal,
440 CHANNEL_LABEL_RightTotal } }, // a matrix encoded stereo stream (Lt, Rt)
441
442 { CHANNEL_LAYOUT_MidSide, (channel_label_t[]){ CHANNEL_LABEL_MS_Mid,
443 CHANNEL_LABEL_MS_Side } }, // mid/side recording
444
445 { CHANNEL_LAYOUT_XY, (channel_label_t[]){ CHANNEL_LABEL_XY_X, CHANNEL_LABEL_XY_Y } }, // coincident mic pair (often 2 figure 8's)
446
447 { CHANNEL_LAYOUT_Binaural, (channel_label_t[]){ CHANNEL_LABEL_Left,
448 CHANNEL_LABEL_Right } }, // binaural stereo (left, right)
449
450 // Symetric arrangements - same distance between speaker locations
451
452 { CHANNEL_LAYOUT_Ambisonic_B_Format, (channel_label_t[]){ CHANNEL_LABEL_Ambisonic_W,
453 CHANNEL_LABEL_Ambisonic_X,
454 CHANNEL_LABEL_Ambisonic_Y,
455 CHANNEL_LABEL_Ambisonic_Z } }, // W, X, Y, Z
456
457 { CHANNEL_LAYOUT_Quadraphonic, (channel_label_t[]){ CHANNEL_LABEL_Left,
458 CHANNEL_LABEL_Right,
459 CHANNEL_LABEL_LeftSurround,
460 CHANNEL_LABEL_RightSurround } }, // front left, front right, back left, back right
461
462 { CHANNEL_LAYOUT_Pentagonal, (channel_label_t[]){ CHANNEL_LABEL_Left,
463 CHANNEL_LABEL_Right,
464 CHANNEL_LABEL_LeftSurround,
465 CHANNEL_LABEL_RightSurround,
466 CHANNEL_LABEL_Center } }, // left, right, rear left, rear right, center
467
468 { CHANNEL_LAYOUT_Hexagonal, (channel_label_t[]){ CHANNEL_LABEL_Left,
469 CHANNEL_LABEL_Right,
470 CHANNEL_LABEL_LeftSurround,
471 CHANNEL_LABEL_RightSurround,
472 CHANNEL_LABEL_Center,
473 CHANNEL_LABEL_CenterSurround } }, // left, right, rear left, rear right, center, rear
474
475 { CHANNEL_LAYOUT_Octagonal, (channel_label_t[]){ CHANNEL_LABEL_Left,
476 CHANNEL_LABEL_Right,
477 CHANNEL_LABEL_LeftSurround,
478 CHANNEL_LABEL_RightSurround,
479 CHANNEL_LABEL_Center,
480 CHANNEL_LABEL_CenterSurround,
481 CHANNEL_LABEL_LeftSurroundDirect,
482 CHANNEL_LABEL_RightSurroundDirect } }, // front left, front right, rear left, rear right,
483 // front center, rear center, side left, side right
484
485 { CHANNEL_LAYOUT_Cube, (channel_label_t[]){ CHANNEL_LABEL_Left,
486 CHANNEL_LABEL_Right,
487 CHANNEL_LABEL_LeftSurround,
488 CHANNEL_LABEL_RightSurround,
489 CHANNEL_LABEL_VerticalHeightLeft,
490 CHANNEL_LABEL_VerticalHeightRight,
491 CHANNEL_LABEL_TopBackLeft,
492 CHANNEL_LABEL_TopBackRight } }, // left, right, rear left, rear right
493 // top left, top right, top rear left, top rear right
494
495 // MPEG defined layouts
496
497 { CHANNEL_LAYOUT_MPEG_3_0_A, (channel_label_t[]){ CHANNEL_LABEL_Left,
498 CHANNEL_LABEL_Right,
499 CHANNEL_LABEL_Center } }, // L R C
500
501 { CHANNEL_LAYOUT_MPEG_4_0_A, (channel_label_t[]){ CHANNEL_LABEL_Left,
502 CHANNEL_LABEL_Right,
503 CHANNEL_LABEL_Center,
504 CHANNEL_LABEL_CenterSurround } }, // L R C Cs
505
506 { CHANNEL_LAYOUT_MPEG_5_0_A, (channel_label_t[]){ CHANNEL_LABEL_Left,
507 CHANNEL_LABEL_Right,
508 CHANNEL_LABEL_Center,
509 CHANNEL_LABEL_LeftSurround,
510 CHANNEL_LABEL_RightSurround } }, // L R C Ls Rs
511
512 { CHANNEL_LAYOUT_MPEG_5_1_A, (channel_label_t[]){ CHANNEL_LABEL_Left,
513 CHANNEL_LABEL_Right,
514 CHANNEL_LABEL_Center,
515 CHANNEL_LABEL_LFEScreen,
516 CHANNEL_LABEL_LeftSurround,
517 CHANNEL_LABEL_RightSurround } }, // L R C LFE Ls Rs
518
519 { CHANNEL_LAYOUT_MPEG_6_1_A, (channel_label_t[]){ CHANNEL_LABEL_Left,
520 CHANNEL_LABEL_Right,
521 CHANNEL_LABEL_Center,
522 CHANNEL_LABEL_LFEScreen,
523 CHANNEL_LABEL_LeftSurround,
524 CHANNEL_LABEL_RightSurround,
525 CHANNEL_LABEL_CenterSurround } }, // L R C LFE Ls Rs Cs
526
527 { CHANNEL_LAYOUT_MPEG_7_1_A, (channel_label_t[]){ CHANNEL_LABEL_Left,
528 CHANNEL_LABEL_Right,
529 CHANNEL_LABEL_Center,
530 CHANNEL_LABEL_LFEScreen,
531 CHANNEL_LABEL_LeftSurround,
532 CHANNEL_LABEL_RightSurround,
533 CHANNEL_LABEL_LeftCenter,
534 CHANNEL_LABEL_RightCenter } }, // L R C LFE Ls Rs Lc Rc
535
536 { CHANNEL_LAYOUT_MPEG_5_0_B, (channel_label_t[]){ CHANNEL_LABEL_Left,
537 CHANNEL_LABEL_Right,
538 CHANNEL_LABEL_LeftSurround,
539 CHANNEL_LABEL_RightSurround,
540 CHANNEL_LABEL_Center } }, // L R Ls Rs C
541
542 { CHANNEL_LAYOUT_MPEG_5_1_B, (channel_label_t[]){ CHANNEL_LABEL_Left,
543 CHANNEL_LABEL_Right,
544 CHANNEL_LABEL_LeftSurround,
545 CHANNEL_LABEL_RightSurround,
546 CHANNEL_LABEL_Center,
547 CHANNEL_LABEL_LFEScreen } }, // L R Ls Rs C LFE
548
549 { CHANNEL_LAYOUT_MPEG_3_0_B, (channel_label_t[]){ CHANNEL_LABEL_Center,
550 CHANNEL_LABEL_Left,
551 CHANNEL_LABEL_Right } }, // C L R
552
553 { CHANNEL_LAYOUT_MPEG_4_0_B, (channel_label_t[]){ CHANNEL_LABEL_Center,
554 CHANNEL_LABEL_Left,
555 CHANNEL_LABEL_Right,
556 CHANNEL_LABEL_CenterSurround } }, // C L R Cs
557
558 { CHANNEL_LAYOUT_MPEG_5_0_D, (channel_label_t[]){ CHANNEL_LABEL_Center,
559 CHANNEL_LABEL_Left,
560 CHANNEL_LABEL_Right,
561 CHANNEL_LABEL_LeftSurround,
562 CHANNEL_LABEL_RightSurround } }, // C L R Ls Rs
563
564 { CHANNEL_LAYOUT_MPEG_5_1_D, (channel_label_t[]){ CHANNEL_LABEL_Center,
565 CHANNEL_LABEL_Left,
566 CHANNEL_LABEL_Right,
567 CHANNEL_LABEL_LeftSurround,
568 CHANNEL_LABEL_RightSurround,
569 CHANNEL_LABEL_LFEScreen } }, // C L R Ls Rs LFE
570
571 { CHANNEL_LAYOUT_MPEG_5_0_C, (channel_label_t[]){ CHANNEL_LABEL_Left,
572 CHANNEL_LABEL_Center,
573 CHANNEL_LABEL_Right,
574 CHANNEL_LABEL_LeftSurround,
575 CHANNEL_LABEL_RightSurround } }, // L C R Ls Rs
576
577 { CHANNEL_LAYOUT_MPEG_5_1_C, (channel_label_t[]){ CHANNEL_LABEL_Left,
578 CHANNEL_LABEL_Center,
579 CHANNEL_LABEL_Right,
580 CHANNEL_LABEL_LeftSurround,
581 CHANNEL_LABEL_RightSurround,
582 CHANNEL_LABEL_LFEScreen } }, // L C R Ls Rs LFE
583
584 { CHANNEL_LAYOUT_MPEG_7_1_B, (channel_label_t[]){ CHANNEL_LABEL_Center,
585 CHANNEL_LABEL_LeftCenter,
586 CHANNEL_LABEL_RightCenter,
587 CHANNEL_LABEL_Left,
588 CHANNEL_LABEL_Right,
589 CHANNEL_LABEL_LeftSurround,
590 CHANNEL_LABEL_RightSurround,
591 CHANNEL_LABEL_LFEScreen } }, // C Lc Rc L R Ls Rs LFE
592
593 { CHANNEL_LAYOUT_MPEG_7_1_C, (channel_label_t[]){ CHANNEL_LABEL_Left,
594 CHANNEL_LABEL_Right,
595 CHANNEL_LABEL_Center,
596 CHANNEL_LABEL_LFEScreen,
597 CHANNEL_LABEL_LeftSurroundDirect,
598 CHANNEL_LABEL_RightSurroundDirect,
599 CHANNEL_LABEL_LeftSurround,
600 CHANNEL_LABEL_RightSurround } }, // L R C LFE Ls Rs Rls Rrs
601
602 { CHANNEL_LAYOUT_Emagic_Default_7_1, (channel_label_t[]){ CHANNEL_LABEL_Left,
603 CHANNEL_LABEL_Right,
604 CHANNEL_LABEL_LeftSurround,
605 CHANNEL_LABEL_RightSurround,
606 CHANNEL_LABEL_Center,
607 CHANNEL_LABEL_LFEScreen,
608 CHANNEL_LABEL_LeftCenter,
609 CHANNEL_LABEL_RightCenter } },// L R Ls Rs C LFE Lc Rc
610
611 { CHANNEL_LAYOUT_SMPTE_DTV, (channel_label_t[]){ CHANNEL_LABEL_Left,
612 CHANNEL_LABEL_Right,
613 CHANNEL_LABEL_Center,
614 CHANNEL_LABEL_LFEScreen,
615 CHANNEL_LABEL_LeftSurround,
616 CHANNEL_LABEL_RightSurround,
617 CHANNEL_LABEL_LeftTotal,
618 CHANNEL_LABEL_RightTotal } }, // L R C LFE Ls Rs Lt Rt
619 // (CHANNEL_LAYOUT_ITU_5_1 plus a matrix encoded stereo mix)
620
621 // ITU defined layouts
622
623 { CHANNEL_LAYOUT_ITU_2_1, (channel_label_t[]){ CHANNEL_LABEL_Left,
624 CHANNEL_LABEL_Right,
625 CHANNEL_LABEL_CenterSurround } }, // L R Cs
626
627 { CHANNEL_LAYOUT_ITU_2_2, (channel_label_t[]){ CHANNEL_LABEL_Left,
628 CHANNEL_LABEL_Right,
629 CHANNEL_LABEL_LeftSurround,
630 CHANNEL_LABEL_RightSurround } }, // L R Ls Rs
631
632 // DVD defined layouts
633
634 { CHANNEL_LAYOUT_DVD_4, (channel_label_t[]){ CHANNEL_LABEL_Left,
635 CHANNEL_LABEL_Right,
636 CHANNEL_LABEL_LFEScreen } }, // L R LFE
637 { CHANNEL_LAYOUT_DVD_5, (channel_label_t[]){ CHANNEL_LABEL_Left,
638 CHANNEL_LABEL_Right,
639 CHANNEL_LABEL_LFEScreen,
640 CHANNEL_LABEL_CenterSurround } }, // L R LFE Cs
641
642 { CHANNEL_LAYOUT_DVD_6, (channel_label_t[]){ CHANNEL_LABEL_Left,
643 CHANNEL_LABEL_Right,
644 CHANNEL_LABEL_LFEScreen,
645 CHANNEL_LABEL_LeftSurround,
646 CHANNEL_LABEL_RightSurround } }, // L R LFE Ls Rs
647
648 { CHANNEL_LAYOUT_DVD_10, (channel_label_t[]){ CHANNEL_LABEL_Left,
649 CHANNEL_LABEL_Right,
650 CHANNEL_LABEL_Center,
651 CHANNEL_LABEL_LFEScreen } }, // L R C LFE
652
653 { CHANNEL_LAYOUT_DVD_11, (channel_label_t[]){ CHANNEL_LABEL_Left,
654 CHANNEL_LABEL_Right,
655 CHANNEL_LABEL_Center,
656 CHANNEL_LABEL_LFEScreen,
657 CHANNEL_LABEL_CenterSurround } }, // L R C LFE Cs
658
659 // 13 through 17 are duplicates of 8 through 12.
660
661 { CHANNEL_LAYOUT_DVD_18, (channel_label_t[]){ CHANNEL_LABEL_Left,
662 CHANNEL_LABEL_Right,
663 CHANNEL_LABEL_LeftSurround,
664 CHANNEL_LABEL_RightSurround,
665 CHANNEL_LABEL_LFEScreen } }, // L R Ls Rs LFE
666
667 // These are the surround-based layouts
668
669 { CHANNEL_LAYOUT_AudioUnit_6_0, (channel_label_t[]){ CHANNEL_LABEL_Left,
670 CHANNEL_LABEL_Right,
671 CHANNEL_LABEL_LeftSurround,
672 CHANNEL_LABEL_RightSurround,
673 CHANNEL_LABEL_Center,
674 CHANNEL_LABEL_CenterSurround } }, // L R Ls Rs C Cs
675
676 { CHANNEL_LAYOUT_AudioUnit_7_0, (channel_label_t[]){ CHANNEL_LABEL_Left,
677 CHANNEL_LABEL_Right,
678 CHANNEL_LABEL_LeftSurroundDirect,
679 CHANNEL_LABEL_RightSurroundDirect,
680 CHANNEL_LABEL_Center,
681 CHANNEL_LABEL_LeftSurround,
682 CHANNEL_LABEL_RightSurround } }, // L R Ls Rs C Rls Rrs
683
684 // These layouts are used for AAC Encoding within the MPEG-4 Specification
685
686 { CHANNEL_LAYOUT_AAC_6_0, (channel_label_t[]){ CHANNEL_LABEL_Center,
687 CHANNEL_LABEL_Left,
688 CHANNEL_LABEL_Right,
689 CHANNEL_LABEL_LeftSurround,
690 CHANNEL_LABEL_RightSurround,
691 CHANNEL_LABEL_CenterSurround } }, // C L R Ls Rs Cs
692
693 { CHANNEL_LAYOUT_AAC_6_1, (channel_label_t[]){ CHANNEL_LABEL_Center,
694 CHANNEL_LABEL_Left,
695 CHANNEL_LABEL_Right,
696 CHANNEL_LABEL_LeftSurround,
697 CHANNEL_LABEL_RightSurround,
698 CHANNEL_LABEL_CenterSurround,
699 CHANNEL_LABEL_LFEScreen } }, // C L R Ls Rs Cs Lfe
700
701 { CHANNEL_LAYOUT_AAC_7_0, (channel_label_t[]){ CHANNEL_LABEL_Center,
702 CHANNEL_LABEL_Left,
703 CHANNEL_LABEL_Right,
704 CHANNEL_LABEL_LeftSurroundDirect,
705 CHANNEL_LABEL_RightSurroundDirect,
706 CHANNEL_LABEL_LeftSurround,
707 CHANNEL_LABEL_RightSurround } }, // C L R Ls Rs Rls Rrs
708
709 { CHANNEL_LAYOUT_AAC_Octagonal, (channel_label_t[]){ CHANNEL_LABEL_Center,
710 CHANNEL_LABEL_Left,
711 CHANNEL_LABEL_Right,
712 CHANNEL_LABEL_LeftSurroundDirect,
713 CHANNEL_LABEL_RightSurroundDirect,
714 CHANNEL_LABEL_LeftSurround,
715 CHANNEL_LABEL_RightSurround,
716 CHANNEL_LABEL_CenterSurround } }, // C L R Ls Rs Rls Rrs Cs
717
718 /* No, sorry the following 2 a to weird. The one who has such files, can program it */
719 // { CHANNEL_LAYOUT_TMH_10_2_std, (channel_label_t[]){ } }, // L R C Vhc Lsd Rsd Ls Rs Vhl Vhr Lw Rw Csd Cs LFE1 LFE2
720 // { CHANNEL_LAYOUT_TMH_10_2_full, (channel_label_t[]){ } }, // TMH_10_2_std plus: Lc Rc HI VI Haptic
721
722 };
723
get_channel_locations(uint32_t layout,int * num_channels)724 static channel_label_t * get_channel_locations(uint32_t layout, int * num_channels)
725 {
726 int i;
727
728 *num_channels = layout & 0xffff;
729 for(i = 0; i < sizeof(channel_locations)/sizeof(channel_locations[0]); i++)
730 {
731 if(channel_locations[i].layout == layout)
732 {
733 return channel_locations[i].channels;
734 }
735 }
736 return (channel_label_t*)0;
737 }
738
quicktime_chan_init(quicktime_chan_t * chan)739 void quicktime_chan_init(quicktime_chan_t *chan)
740 {
741
742 }
743
quicktime_chan_delete(quicktime_chan_t * chan)744 void quicktime_chan_delete(quicktime_chan_t *chan)
745 {
746 if(chan->ChannelDescriptions)
747 free(chan->ChannelDescriptions);
748 }
749
quicktime_chan_dump(quicktime_chan_t * chan)750 void quicktime_chan_dump(quicktime_chan_t *chan)
751 {
752 channel_label_t * channel_labels;
753 int num_channels;
754 int i, j;
755 uint32_t mask;
756 lqt_dump(" channel description\n");
757 lqt_dump(" version %d\n", chan->version);
758 lqt_dump(" flags %ld\n", chan->flags);
759 lqt_dump(" mChannelLayoutTag: 0x%08x", chan->mChannelLayoutTag);
760
761 if(chan->mChannelLayoutTag == CHANNEL_LAYOUT_UseChannelDescriptions)
762 {
763 lqt_dump(" [Use channel decriptions]\n");
764 }
765 else if(chan->mChannelLayoutTag == CHANNEL_LAYOUT_UseChannelBitmap)
766 {
767 lqt_dump(" [Use channel bitmap]\n");
768 }
769 else
770 {
771 channel_labels = get_channel_locations(chan->mChannelLayoutTag, &num_channels);
772
773 lqt_dump(" [");
774
775 if(channel_labels)
776 {
777 for(i = 0; i < num_channels; i++)
778 {
779 lqt_dump("%s", get_channel_name(channel_labels[i]));
780 if(i < num_channels-1)
781 lqt_dump(", ");
782 }
783 }
784 else
785 {
786 lqt_dump("Not available");
787 }
788 lqt_dump("]\n");
789 }
790
791 lqt_dump(" mChannelBitmap: 0x%08x", chan->mChannelBitmap);
792
793 if(chan->mChannelLayoutTag == CHANNEL_LAYOUT_UseChannelBitmap)
794 {
795 lqt_dump(" [");
796 j = 0;
797 mask = 1;
798 for(i = 0; i < 32; i++)
799 {
800 if(chan->mChannelBitmap & mask)
801 {
802 if(j)
803 lqt_dump(", ");
804 lqt_dump("%s", get_channel_name(channel_bit_2_channel_label(mask)));
805 j++;
806 }
807 mask <<= 1;
808 }
809 lqt_dump("]\n");
810 }
811 else
812 lqt_dump("\n");
813
814
815 lqt_dump(" mNumberChannelDescriptions: %d\n", chan->mNumberChannelDescriptions);
816 for(i = 0; i < chan->mNumberChannelDescriptions; i++)
817 {
818 lqt_dump(" mChannelLabel[%d]: 0x%08x [%s]\n", i,
819 chan->ChannelDescriptions[i].mChannelLabel, get_channel_name(chan->ChannelDescriptions[i].mChannelLabel));
820 lqt_dump(" mChannelFlags[%d]: 0x%08x\n", i,
821 chan->ChannelDescriptions[i].mChannelFlags);
822 lqt_dump(" mCoordinates[%d]: [%f %f %f]\n", i,
823 chan->ChannelDescriptions[i].mCoordinates[0],
824 chan->ChannelDescriptions[i].mCoordinates[1],
825 chan->ChannelDescriptions[i].mCoordinates[2]);
826 }
827 }
828
829
830
quicktime_read_chan(quicktime_t * file,quicktime_chan_t * chan)831 void quicktime_read_chan(quicktime_t *file, quicktime_chan_t *chan)
832 {
833 int i;
834 chan->version = quicktime_read_char(file);
835 chan->flags = quicktime_read_int24(file);
836
837 chan->mChannelLayoutTag = quicktime_read_int32(file);
838 chan->mChannelBitmap = quicktime_read_int32(file);
839 chan->mNumberChannelDescriptions = quicktime_read_int32(file);
840
841 if(chan->mNumberChannelDescriptions)
842 {
843 chan->ChannelDescriptions = calloc(chan->mNumberChannelDescriptions,
844 sizeof(*(chan->ChannelDescriptions)));
845
846 for(i = 0; i < chan->mNumberChannelDescriptions; i++)
847 {
848 chan->ChannelDescriptions[i].mChannelLabel = quicktime_read_int32(file);
849 chan->ChannelDescriptions[i].mChannelFlags = quicktime_read_int32(file);
850 chan->ChannelDescriptions[i].mCoordinates[0] = quicktime_read_float32(file);
851 chan->ChannelDescriptions[i].mCoordinates[1] = quicktime_read_float32(file);
852 chan->ChannelDescriptions[i].mCoordinates[2] = quicktime_read_float32(file);
853 }
854 }
855
856 }
857
quicktime_write_chan(quicktime_t * file,quicktime_chan_t * chan)858 void quicktime_write_chan(quicktime_t *file, quicktime_chan_t *chan)
859 {
860 quicktime_atom_t atom;
861 int i;
862 quicktime_atom_write_header(file, &atom, "chan");
863
864 quicktime_write_char(file, chan->version);
865 quicktime_write_int24(file, chan->flags);
866
867 quicktime_write_int32(file, chan->mChannelLayoutTag);
868 quicktime_write_int32(file, chan->mChannelBitmap);
869 quicktime_write_int32(file, chan->mNumberChannelDescriptions);
870
871 for(i = 0; i < chan->mNumberChannelDescriptions; i++)
872 {
873 quicktime_write_int32(file, chan->ChannelDescriptions[i].mChannelLabel);
874 quicktime_write_int32(file, chan->ChannelDescriptions[i].mChannelFlags);
875 quicktime_write_float32(file, chan->ChannelDescriptions[i].mCoordinates[0]);
876 quicktime_write_float32(file, chan->ChannelDescriptions[i].mCoordinates[1]);
877 quicktime_write_float32(file, chan->ChannelDescriptions[i].mCoordinates[2]);
878 }
879 quicktime_atom_write_footer(file, &atom);
880 }
881
882 /* Update an atrack from a chan atom */
quicktime_get_chan(quicktime_audio_map_t * atrack)883 void quicktime_get_chan(quicktime_audio_map_t * atrack)
884 {
885 int i, num_channels;
886 uint32_t mask;
887 quicktime_chan_t * chan;
888 const channel_label_t * channel_labels;
889 chan = &atrack->track->mdia.minf.stbl.stsd.table[0].chan;
890
891 if(chan->mChannelLayoutTag == CHANNEL_LAYOUT_UseChannelDescriptions)
892 {
893 atrack->channel_setup = calloc(chan->mNumberChannelDescriptions,
894 sizeof(*atrack->channel_setup));
895 atrack->channels = chan->mNumberChannelDescriptions;
896 for(i = 0; i < chan->mNumberChannelDescriptions; i++)
897 atrack->channel_setup[i] = channel_label_2_channel(chan->ChannelDescriptions[i].mChannelLabel);
898 }
899 else if(chan->mChannelLayoutTag == CHANNEL_LAYOUT_UseChannelBitmap)
900 {
901 /* Count the channels */
902 mask = 1;
903 num_channels = 0;
904 for(i = 0; i < 32; i++)
905 {
906 if(chan->mChannelBitmap & mask)
907 num_channels++;
908 mask <<= 1;
909 }
910
911 /* Set the channels */
912 atrack->channels = num_channels;
913 atrack->channel_setup = calloc(num_channels,
914 sizeof(*atrack->channel_setup));
915
916 mask = 1;
917 num_channels = 0;
918 for(i = 0; i < 32; i++)
919 {
920 if(chan->mChannelBitmap & mask)
921 {
922 atrack->channel_setup[num_channels] =
923 channel_label_2_channel(channel_bit_2_channel_label(mask));
924 num_channels++;
925 }
926 mask <<= 1;
927 }
928 }
929 else /* Predefined channel layout */
930 {
931 channel_labels = get_channel_locations(chan->mChannelLayoutTag, &num_channels);
932 atrack->channels = num_channels;
933
934 if(channel_labels)
935 {
936 atrack->channel_setup = calloc(num_channels,
937 sizeof(*atrack->channel_setup));
938 for(i = 0; i < num_channels; i++)
939 atrack->channel_setup[i] = channel_label_2_channel(channel_labels[i]);
940 }
941
942 }
943
944 }
945
946
layout_equal(channel_label_t * labels,lqt_channel_t * channels,int num_channels)947 static int layout_equal(channel_label_t * labels, lqt_channel_t * channels, int num_channels)
948 {
949 int i;
950
951 for(i = 0; i < num_channels; i++)
952 {
953 if(channels[i] != channel_label_2_channel(labels[i]))
954 return 0;
955 }
956 return 1;
957 }
958
layout_similar(channel_label_t * labels,lqt_channel_t * channels,int num_channels)959 static int layout_similar(channel_label_t * labels, lqt_channel_t * channels, int num_channels)
960 {
961 int i, j, found;
962
963 for(i = 0; i < num_channels; i++)
964 {
965 found = 0;
966 for(j = 0; j < num_channels; j++)
967 {
968 if(channels[i] == channel_label_2_channel(labels[j]))
969 {
970 found = 1;
971 break;
972 }
973 }
974 if(!found)
975 return 0;
976 }
977 return 1;
978 }
979
980 /* Set the chan atom of an atrack */
quicktime_set_chan(quicktime_audio_map_t * atrack)981 void quicktime_set_chan(quicktime_audio_map_t * atrack)
982 {
983 int i, j;
984 quicktime_chan_t * chan;
985
986 if(!atrack->channel_setup)
987 return;
988
989 chan = &atrack->track->mdia.minf.stbl.stsd.table[0].chan;
990
991 /* Search for a equal channel setup */
992 for(i = 0; i < sizeof(channel_locations) / sizeof(channel_locations[0]); i++)
993 {
994 if(((channel_locations[i].layout & 0xffff) == atrack->channels) &&
995 layout_equal(channel_locations[i].channels,
996 atrack->channel_setup,
997 atrack->channels))
998 {
999 chan->mChannelLayoutTag = channel_locations[i].layout;
1000 atrack->track->mdia.minf.stbl.stsd.table[0].has_chan = 1;
1001 return;
1002 }
1003 }
1004
1005 /* Search for a similar channel setup */
1006 for(i = 0; i < sizeof(channel_locations) / sizeof(channel_locations[0]); i++)
1007 {
1008 if(((channel_locations[i].layout & 0xffff) == atrack->channels) &&
1009 layout_similar(channel_locations[i].channels,
1010 atrack->channel_setup,
1011 atrack->channels))
1012 {
1013 chan->mChannelLayoutTag = channel_locations[i].layout;
1014 atrack->track->mdia.minf.stbl.stsd.table[0].has_chan = 1;
1015
1016 for(j = 0; j < atrack->channels; j++)
1017 atrack->channel_setup[j] = channel_label_2_channel(channel_locations[i].channels[j]);
1018 return;
1019 }
1020 }
1021
1022 /* Nothing found, create a custom channel setup */
1023 chan->ChannelDescriptions =
1024 calloc(atrack->channels, sizeof(*(chan->ChannelDescriptions)));
1025 chan->mNumberChannelDescriptions = atrack->channels;
1026 chan->mChannelLayoutTag = CHANNEL_LAYOUT_UseChannelDescriptions;
1027 for(i = 0; i < chan->mNumberChannelDescriptions; i++)
1028 {
1029 chan->ChannelDescriptions[i].mChannelLabel =
1030 channel_2_channel_label(atrack->channel_setup[i]);
1031 }
1032 atrack->track->mdia.minf.stbl.stsd.table[0].has_chan = 1;
1033
1034 }
1035