mov_chan.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. /*
  2. * Copyright (c) 2011 Justin Ruggles
  3. *
  4. * This file is part of Libav.
  5. *
  6. * Libav 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. * Libav 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 Libav; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. /**
  21. * mov 'chan' tag reading/writing.
  22. * @author Justin Ruggles
  23. */
  24. #include <stdint.h>
  25. #include "libavutil/audioconvert.h"
  26. #include "libavcodec/avcodec.h"
  27. #include "mov_chan.h"
  28. /**
  29. * Channel Layout Tag
  30. * This tells which channels are present in the audio stream and the order in
  31. * which they appear.
  32. *
  33. * @note We're using the channel layout tag to indicate channel order
  34. * when the value is greater than 0x10000. The Apple documentation has
  35. * some contradictions as to how this is actually supposed to be handled.
  36. *
  37. * Core Audio File Format Spec:
  38. * "The high 16 bits indicates a specific ordering of the channels."
  39. * Core Audio Data Types Reference:
  40. * "These identifiers specify the channels included in a layout but
  41. * do not specify a particular ordering of those channels."
  42. */
  43. enum MovChannelLayoutTag {
  44. MOV_CH_LAYOUT_UNKNOWN = 0xFFFF0000,
  45. MOV_CH_LAYOUT_USE_DESCRIPTIONS = ( 0 << 16) | 0,
  46. MOV_CH_LAYOUT_USE_BITMAP = ( 1 << 16) | 0,
  47. MOV_CH_LAYOUT_DISCRETEINORDER = (147 << 16) | 0,
  48. MOV_CH_LAYOUT_MONO = (100 << 16) | 1,
  49. MOV_CH_LAYOUT_STEREO = (101 << 16) | 2,
  50. MOV_CH_LAYOUT_STEREOHEADPHONES = (102 << 16) | 2,
  51. MOV_CH_LAYOUT_MATRIXSTEREO = (103 << 16) | 2,
  52. MOV_CH_LAYOUT_MIDSIDE = (104 << 16) | 2,
  53. MOV_CH_LAYOUT_XY = (105 << 16) | 2,
  54. MOV_CH_LAYOUT_BINAURAL = (106 << 16) | 2,
  55. MOV_CH_LAYOUT_AMBISONIC_B_FORMAT = (107 << 16) | 4,
  56. MOV_CH_LAYOUT_QUADRAPHONIC = (108 << 16) | 4,
  57. MOV_CH_LAYOUT_PENTAGONAL = (109 << 16) | 5,
  58. MOV_CH_LAYOUT_HEXAGONAL = (110 << 16) | 6,
  59. MOV_CH_LAYOUT_OCTAGONAL = (111 << 16) | 8,
  60. MOV_CH_LAYOUT_CUBE = (112 << 16) | 8,
  61. MOV_CH_LAYOUT_MPEG_3_0_A = (113 << 16) | 3,
  62. MOV_CH_LAYOUT_MPEG_3_0_B = (114 << 16) | 3,
  63. MOV_CH_LAYOUT_MPEG_4_0_A = (115 << 16) | 4,
  64. MOV_CH_LAYOUT_MPEG_4_0_B = (116 << 16) | 4,
  65. MOV_CH_LAYOUT_MPEG_5_0_A = (117 << 16) | 5,
  66. MOV_CH_LAYOUT_MPEG_5_0_B = (118 << 16) | 5,
  67. MOV_CH_LAYOUT_MPEG_5_0_C = (119 << 16) | 5,
  68. MOV_CH_LAYOUT_MPEG_5_0_D = (120 << 16) | 5,
  69. MOV_CH_LAYOUT_MPEG_5_1_A = (121 << 16) | 6,
  70. MOV_CH_LAYOUT_MPEG_5_1_B = (122 << 16) | 6,
  71. MOV_CH_LAYOUT_MPEG_5_1_C = (123 << 16) | 6,
  72. MOV_CH_LAYOUT_MPEG_5_1_D = (124 << 16) | 6,
  73. MOV_CH_LAYOUT_MPEG_6_1_A = (125 << 16) | 7,
  74. MOV_CH_LAYOUT_MPEG_7_1_A = (126 << 16) | 8,
  75. MOV_CH_LAYOUT_MPEG_7_1_B = (127 << 16) | 8,
  76. MOV_CH_LAYOUT_MPEG_7_1_C = (128 << 16) | 8,
  77. MOV_CH_LAYOUT_EMAGIC_DEFAULT_7_1 = (129 << 16) | 8,
  78. MOV_CH_LAYOUT_SMPTE_DTV = (130 << 16) | 8,
  79. MOV_CH_LAYOUT_ITU_2_1 = (131 << 16) | 3,
  80. MOV_CH_LAYOUT_ITU_2_2 = (132 << 16) | 4,
  81. MOV_CH_LAYOUT_DVD_4 = (133 << 16) | 3,
  82. MOV_CH_LAYOUT_DVD_5 = (134 << 16) | 4,
  83. MOV_CH_LAYOUT_DVD_6 = (135 << 16) | 5,
  84. MOV_CH_LAYOUT_DVD_10 = (136 << 16) | 4,
  85. MOV_CH_LAYOUT_DVD_11 = (137 << 16) | 5,
  86. MOV_CH_LAYOUT_DVD_18 = (138 << 16) | 5,
  87. MOV_CH_LAYOUT_AUDIOUNIT_6_0 = (139 << 16) | 6,
  88. MOV_CH_LAYOUT_AUDIOUNIT_7_0 = (140 << 16) | 7,
  89. MOV_CH_LAYOUT_AUDIOUNIT_7_0_FRONT = (148 << 16) | 7,
  90. MOV_CH_LAYOUT_AAC_6_0 = (141 << 16) | 6,
  91. MOV_CH_LAYOUT_AAC_6_1 = (142 << 16) | 7,
  92. MOV_CH_LAYOUT_AAC_7_0 = (143 << 16) | 7,
  93. MOV_CH_LAYOUT_AAC_OCTAGONAL = (144 << 16) | 8,
  94. MOV_CH_LAYOUT_TMH_10_2_STD = (145 << 16) | 16,
  95. MOV_CH_LAYOUT_TMH_10_2_FULL = (146 << 16) | 21,
  96. MOV_CH_LAYOUT_AC3_1_0_1 = (149 << 16) | 2,
  97. MOV_CH_LAYOUT_AC3_3_0 = (150 << 16) | 3,
  98. MOV_CH_LAYOUT_AC3_3_1 = (151 << 16) | 4,
  99. MOV_CH_LAYOUT_AC3_3_0_1 = (152 << 16) | 4,
  100. MOV_CH_LAYOUT_AC3_2_1_1 = (153 << 16) | 4,
  101. MOV_CH_LAYOUT_AC3_3_1_1 = (154 << 16) | 5,
  102. MOV_CH_LAYOUT_EAC3_6_0_A = (155 << 16) | 6,
  103. MOV_CH_LAYOUT_EAC3_7_0_A = (156 << 16) | 7,
  104. MOV_CH_LAYOUT_EAC3_6_1_A = (157 << 16) | 7,
  105. MOV_CH_LAYOUT_EAC3_6_1_B = (158 << 16) | 7,
  106. MOV_CH_LAYOUT_EAC3_6_1_C = (159 << 16) | 7,
  107. MOV_CH_LAYOUT_EAC3_7_1_A = (160 << 16) | 8,
  108. MOV_CH_LAYOUT_EAC3_7_1_B = (161 << 16) | 8,
  109. MOV_CH_LAYOUT_EAC3_7_1_C = (162 << 16) | 8,
  110. MOV_CH_LAYOUT_EAC3_7_1_D = (163 << 16) | 8,
  111. MOV_CH_LAYOUT_EAC3_7_1_E = (164 << 16) | 8,
  112. MOV_CH_LAYOUT_EAC3_7_1_F = (165 << 16) | 8,
  113. MOV_CH_LAYOUT_EAC3_7_1_G = (166 << 16) | 8,
  114. MOV_CH_LAYOUT_EAC3_7_1_H = (167 << 16) | 8,
  115. MOV_CH_LAYOUT_DTS_3_1 = (168 << 16) | 4,
  116. MOV_CH_LAYOUT_DTS_4_1 = (169 << 16) | 5,
  117. MOV_CH_LAYOUT_DTS_6_0_A = (170 << 16) | 6,
  118. MOV_CH_LAYOUT_DTS_6_0_B = (171 << 16) | 6,
  119. MOV_CH_LAYOUT_DTS_6_0_C = (172 << 16) | 6,
  120. MOV_CH_LAYOUT_DTS_6_1_A = (173 << 16) | 7,
  121. MOV_CH_LAYOUT_DTS_6_1_B = (174 << 16) | 7,
  122. MOV_CH_LAYOUT_DTS_6_1_C = (175 << 16) | 7,
  123. MOV_CH_LAYOUT_DTS_6_1_D = (182 << 16) | 7,
  124. MOV_CH_LAYOUT_DTS_7_0 = (176 << 16) | 7,
  125. MOV_CH_LAYOUT_DTS_7_1 = (177 << 16) | 8,
  126. MOV_CH_LAYOUT_DTS_8_0_A = (178 << 16) | 8,
  127. MOV_CH_LAYOUT_DTS_8_0_B = (179 << 16) | 8,
  128. MOV_CH_LAYOUT_DTS_8_1_A = (180 << 16) | 9,
  129. MOV_CH_LAYOUT_DTS_8_1_B = (181 << 16) | 9,
  130. };
  131. struct MovChannelLayoutMap {
  132. uint32_t tag;
  133. uint64_t layout;
  134. };
  135. static const struct MovChannelLayoutMap mov_ch_layout_map_misc[] = {
  136. { MOV_CH_LAYOUT_USE_DESCRIPTIONS, 0 },
  137. { MOV_CH_LAYOUT_USE_BITMAP, 0 },
  138. { MOV_CH_LAYOUT_DISCRETEINORDER, 0 },
  139. { MOV_CH_LAYOUT_UNKNOWN, 0 },
  140. { MOV_CH_LAYOUT_TMH_10_2_STD, 0 }, // L, R, C, Vhc, Lsd, Rsd,
  141. // Ls, Rs, Vhl, Vhr, Lw, Rw,
  142. // Csd, Cs, LFE1, LFE2
  143. { MOV_CH_LAYOUT_TMH_10_2_FULL, 0 }, // L, R, C, Vhc, Lsd, Rsd,
  144. // Ls, Rs, Vhl, Vhr, Lw, Rw,
  145. // Csd, Cs, LFE1, LFE2, Lc, Rc,
  146. // HI, VI, Haptic
  147. { 0, 0 },
  148. };
  149. static const struct MovChannelLayoutMap mov_ch_layout_map_1ch[] = {
  150. { MOV_CH_LAYOUT_MONO, AV_CH_LAYOUT_MONO }, // C
  151. { 0, 0 },
  152. };
  153. static const struct MovChannelLayoutMap mov_ch_layout_map_2ch[] = {
  154. { MOV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_STEREO }, // L, R
  155. { MOV_CH_LAYOUT_STEREOHEADPHONES, AV_CH_LAYOUT_STEREO }, // L, R
  156. { MOV_CH_LAYOUT_BINAURAL, AV_CH_LAYOUT_STEREO }, // L, R
  157. { MOV_CH_LAYOUT_MIDSIDE, AV_CH_LAYOUT_STEREO }, // C, sides
  158. { MOV_CH_LAYOUT_XY, AV_CH_LAYOUT_STEREO }, // X (left), Y (right)
  159. { MOV_CH_LAYOUT_MATRIXSTEREO, AV_CH_LAYOUT_STEREO_DOWNMIX }, // Lt, Rt
  160. { MOV_CH_LAYOUT_AC3_1_0_1, AV_CH_LAYOUT_MONO | // C, LFE
  161. AV_CH_LOW_FREQUENCY },
  162. { 0, 0 },
  163. };
  164. static const struct MovChannelLayoutMap mov_ch_layout_map_3ch[] = {
  165. { MOV_CH_LAYOUT_MPEG_3_0_A, AV_CH_LAYOUT_SURROUND }, // L, R, C
  166. { MOV_CH_LAYOUT_MPEG_3_0_B, AV_CH_LAYOUT_SURROUND }, // C, L, R
  167. { MOV_CH_LAYOUT_AC3_3_0, AV_CH_LAYOUT_SURROUND }, // L, C, R
  168. { MOV_CH_LAYOUT_ITU_2_1, AV_CH_LAYOUT_2_1 }, // L, R, Cs
  169. { MOV_CH_LAYOUT_DVD_4, AV_CH_LAYOUT_2POINT1 }, // L, R, LFE
  170. { 0, 0 },
  171. };
  172. static const struct MovChannelLayoutMap mov_ch_layout_map_4ch[] = {
  173. { MOV_CH_LAYOUT_AMBISONIC_B_FORMAT, 0 }, // W, X, Y, Z
  174. { MOV_CH_LAYOUT_QUADRAPHONIC, AV_CH_LAYOUT_QUAD }, // L, R, Rls, Rrs
  175. { MOV_CH_LAYOUT_MPEG_4_0_A, AV_CH_LAYOUT_4POINT0 }, // L, R, C, Cs
  176. { MOV_CH_LAYOUT_MPEG_4_0_B, AV_CH_LAYOUT_4POINT0 }, // C, L, R, Cs
  177. { MOV_CH_LAYOUT_AC3_3_1, AV_CH_LAYOUT_4POINT0 }, // L, C, R, Cs
  178. { MOV_CH_LAYOUT_ITU_2_2, AV_CH_LAYOUT_2_2 }, // L, R, Ls, Rs
  179. { MOV_CH_LAYOUT_DVD_5, AV_CH_LAYOUT_2_1 | // L, R, LFE, Cs
  180. AV_CH_LOW_FREQUENCY },
  181. { MOV_CH_LAYOUT_AC3_2_1_1, AV_CH_LAYOUT_2_1 | // L, R, Cs, LFE
  182. AV_CH_LOW_FREQUENCY },
  183. { MOV_CH_LAYOUT_DVD_10, AV_CH_LAYOUT_3POINT1 }, // L, R, C, LFE
  184. { MOV_CH_LAYOUT_AC3_3_0_1, AV_CH_LAYOUT_3POINT1 }, // L, C, R, LFE
  185. { MOV_CH_LAYOUT_DTS_3_1, AV_CH_LAYOUT_3POINT1 }, // C, L, R, LFE
  186. { 0, 0 },
  187. };
  188. static const struct MovChannelLayoutMap mov_ch_layout_map_5ch[] = {
  189. { MOV_CH_LAYOUT_PENTAGONAL, AV_CH_LAYOUT_5POINT0_BACK }, // L, R, Rls, Rrs, C
  190. { MOV_CH_LAYOUT_MPEG_5_0_A, AV_CH_LAYOUT_5POINT0 }, // L, R, C, Ls, Rs
  191. { MOV_CH_LAYOUT_MPEG_5_0_B, AV_CH_LAYOUT_5POINT0 }, // L, R, Ls, Rs, C
  192. { MOV_CH_LAYOUT_MPEG_5_0_C, AV_CH_LAYOUT_5POINT0 }, // L, C, R, Ls, Rs
  193. { MOV_CH_LAYOUT_MPEG_5_0_D, AV_CH_LAYOUT_5POINT0 }, // C, L, R, Ls, Rs
  194. { MOV_CH_LAYOUT_DVD_6, AV_CH_LAYOUT_2_2 | // L, R, LFE, Ls, Rs
  195. AV_CH_LOW_FREQUENCY },
  196. { MOV_CH_LAYOUT_DVD_18, AV_CH_LAYOUT_2_2 | // L, R, Ls, Rs, LFE
  197. AV_CH_LOW_FREQUENCY },
  198. { MOV_CH_LAYOUT_DVD_11, AV_CH_LAYOUT_4POINT1 }, // L, R, C, LFE, Cs
  199. { MOV_CH_LAYOUT_AC3_3_1_1, AV_CH_LAYOUT_4POINT1 }, // L, C, R, Cs, LFE
  200. { MOV_CH_LAYOUT_DTS_4_1, AV_CH_LAYOUT_4POINT1 }, // C, L, R, Cs, LFE
  201. { 0, 0 },
  202. };
  203. static const struct MovChannelLayoutMap mov_ch_layout_map_6ch[] = {
  204. { MOV_CH_LAYOUT_HEXAGONAL, AV_CH_LAYOUT_HEXAGONAL }, // L, R, Rls, Rrs, C, Cs
  205. { MOV_CH_LAYOUT_DTS_6_0_C, AV_CH_LAYOUT_HEXAGONAL }, // C, Cs, L, R, Rls, Rrs
  206. { MOV_CH_LAYOUT_MPEG_5_1_A, AV_CH_LAYOUT_5POINT1 }, // L, R, C, LFE, Ls, Rs
  207. { MOV_CH_LAYOUT_MPEG_5_1_B, AV_CH_LAYOUT_5POINT1 }, // L, R, Ls, Rs, C, LFE
  208. { MOV_CH_LAYOUT_MPEG_5_1_C, AV_CH_LAYOUT_5POINT1 }, // L, C, R, Ls, Rs, LFE
  209. { MOV_CH_LAYOUT_MPEG_5_1_D, AV_CH_LAYOUT_5POINT1 }, // C, L, R, Ls, Rs, LFE
  210. { MOV_CH_LAYOUT_AUDIOUNIT_6_0, AV_CH_LAYOUT_6POINT0 }, // L, R, Ls, Rs, C, Cs
  211. { MOV_CH_LAYOUT_AAC_6_0, AV_CH_LAYOUT_6POINT0 }, // C, L, R, Ls, Rs, Cs
  212. { MOV_CH_LAYOUT_EAC3_6_0_A, AV_CH_LAYOUT_6POINT0 }, // L, C, R, Ls, Rs, Cs
  213. { MOV_CH_LAYOUT_DTS_6_0_A, AV_CH_LAYOUT_6POINT0_FRONT }, // Lc, Rc, L, R, Ls, Rs
  214. { MOV_CH_LAYOUT_DTS_6_0_B, AV_CH_LAYOUT_5POINT0_BACK | // C, L, R, Rls, Rrs, Ts
  215. AV_CH_TOP_CENTER },
  216. { 0, 0 },
  217. };
  218. static const struct MovChannelLayoutMap mov_ch_layout_map_7ch[] = {
  219. { MOV_CH_LAYOUT_MPEG_6_1_A, AV_CH_LAYOUT_6POINT1 }, // L, R, C, LFE, Ls, Rs, Cs
  220. { MOV_CH_LAYOUT_AAC_6_1, AV_CH_LAYOUT_6POINT1 }, // C, L, R, Ls, Rs, Cs, LFE
  221. { MOV_CH_LAYOUT_EAC3_6_1_A, AV_CH_LAYOUT_6POINT1 }, // L, C, R, Ls, Rs, LFE, Cs
  222. { MOV_CH_LAYOUT_DTS_6_1_D, AV_CH_LAYOUT_6POINT1 }, // C, L, R, Ls, Rs, LFE, Cs
  223. { MOV_CH_LAYOUT_AUDIOUNIT_7_0, AV_CH_LAYOUT_7POINT0 }, // L, R, Ls, Rs, C, Rls, Rrs
  224. { MOV_CH_LAYOUT_AAC_7_0, AV_CH_LAYOUT_7POINT0 }, // C, L, R, Ls, Rs, Rls, Rrs
  225. { MOV_CH_LAYOUT_EAC3_7_0_A, AV_CH_LAYOUT_7POINT0 }, // L, C, R, Ls, Rs, Rls, Rrs
  226. { MOV_CH_LAYOUT_AUDIOUNIT_7_0_FRONT, AV_CH_LAYOUT_7POINT0_FRONT }, // L, R, Ls, Rs, C, Lc, Rc
  227. { MOV_CH_LAYOUT_DTS_7_0, AV_CH_LAYOUT_7POINT0_FRONT }, // Lc, C, Rc, L, R, Ls, Rs
  228. { MOV_CH_LAYOUT_EAC3_6_1_B, AV_CH_LAYOUT_5POINT1 | // L, C, R, Ls, Rs, LFE, Ts
  229. AV_CH_TOP_CENTER },
  230. { MOV_CH_LAYOUT_EAC3_6_1_C, AV_CH_LAYOUT_5POINT1 | // L, C, R, Ls, Rs, LFE, Vhc
  231. AV_CH_TOP_FRONT_CENTER },
  232. { MOV_CH_LAYOUT_DTS_6_1_A, AV_CH_LAYOUT_6POINT1_FRONT }, // Lc, Rc, L, R, Ls, Rs, LFE
  233. { MOV_CH_LAYOUT_DTS_6_1_B, AV_CH_LAYOUT_5POINT1_BACK | // C, L, R, Rls, Rrs, Ts, LFE
  234. AV_CH_TOP_CENTER },
  235. { MOV_CH_LAYOUT_DTS_6_1_C, AV_CH_LAYOUT_6POINT1_BACK }, // C, Cs, L, R, Rls, Rrs, LFE
  236. { 0, 0 },
  237. };
  238. static const struct MovChannelLayoutMap mov_ch_layout_map_8ch[] = {
  239. { MOV_CH_LAYOUT_OCTAGONAL, AV_CH_LAYOUT_OCTAGONAL }, // L, R, Rls, Rrs, C, Cs, Ls, Rs
  240. { MOV_CH_LAYOUT_AAC_OCTAGONAL, AV_CH_LAYOUT_OCTAGONAL }, // C, L, R, Ls, Rs, Rls, Rrs, Cs
  241. { MOV_CH_LAYOUT_CUBE, AV_CH_LAYOUT_QUAD | // L, R, Rls, Rrs, Vhl, Vhr, Rlt, Rrt
  242. AV_CH_TOP_FRONT_LEFT |
  243. AV_CH_TOP_FRONT_RIGHT |
  244. AV_CH_TOP_BACK_LEFT |
  245. AV_CH_TOP_BACK_RIGHT },
  246. { MOV_CH_LAYOUT_MPEG_7_1_A, AV_CH_LAYOUT_7POINT1_WIDE }, // L, R, C, LFE, Ls, Rs, Lc, Rc
  247. { MOV_CH_LAYOUT_MPEG_7_1_B, AV_CH_LAYOUT_7POINT1_WIDE }, // C, Lc, Rc, L, R, Ls, Rs, LFE
  248. { MOV_CH_LAYOUT_EMAGIC_DEFAULT_7_1, AV_CH_LAYOUT_7POINT1_WIDE }, // L, R, Ls, Rs, C, LFE, Lc, Rc
  249. { MOV_CH_LAYOUT_EAC3_7_1_B, AV_CH_LAYOUT_7POINT1_WIDE }, // L, C, R, Ls, Rs, LFE, Lc, Rc
  250. { MOV_CH_LAYOUT_DTS_7_1, AV_CH_LAYOUT_7POINT1_WIDE }, // Lc, C, Rc, L, R, Ls, Rs, LFE
  251. { MOV_CH_LAYOUT_MPEG_7_1_C, AV_CH_LAYOUT_7POINT1 }, // L, R, C, LFE, Ls, Rs, Rls, Rrs
  252. { MOV_CH_LAYOUT_EAC3_7_1_A, AV_CH_LAYOUT_7POINT1 }, // L, C, R, Ls, Rs, LFE, Rls, Rrs
  253. { MOV_CH_LAYOUT_SMPTE_DTV, AV_CH_LAYOUT_5POINT1 | // L, R, C, LFE, Ls, Rs, Lt, Rt
  254. AV_CH_LAYOUT_STEREO_DOWNMIX },
  255. { MOV_CH_LAYOUT_EAC3_7_1_C, AV_CH_LAYOUT_5POINT1 | // L, C, R, Ls, Rs, LFE, Lsd, Rsd
  256. AV_CH_SURROUND_DIRECT_LEFT |
  257. AV_CH_SURROUND_DIRECT_RIGHT },
  258. { MOV_CH_LAYOUT_EAC3_7_1_D, AV_CH_LAYOUT_5POINT1 | // L, C, R, Ls, Rs, LFE, Lw, Rw
  259. AV_CH_WIDE_LEFT |
  260. AV_CH_WIDE_RIGHT },
  261. { MOV_CH_LAYOUT_EAC3_7_1_E, AV_CH_LAYOUT_5POINT1 | // L, C, R, Ls, Rs, LFE, Vhl, Vhr
  262. AV_CH_TOP_FRONT_LEFT |
  263. AV_CH_TOP_FRONT_RIGHT },
  264. { MOV_CH_LAYOUT_EAC3_7_1_F, AV_CH_LAYOUT_5POINT1 | // L, C, R, Ls, Rs, LFE, Cs, Ts
  265. AV_CH_BACK_CENTER |
  266. AV_CH_TOP_CENTER },
  267. { MOV_CH_LAYOUT_EAC3_7_1_G, AV_CH_LAYOUT_5POINT1 | // L, C, R, Ls, Rs, LFE, Cs, Vhc
  268. AV_CH_BACK_CENTER |
  269. AV_CH_TOP_FRONT_CENTER },
  270. { MOV_CH_LAYOUT_EAC3_7_1_H, AV_CH_LAYOUT_5POINT1 | // L, C, R, Ls, Rs, LFE, Ts, Vhc
  271. AV_CH_TOP_CENTER |
  272. AV_CH_TOP_FRONT_CENTER },
  273. { MOV_CH_LAYOUT_DTS_8_0_A, AV_CH_LAYOUT_2_2 | // Lc, Rc, L, R, Ls, Rs, Rls, Rrs
  274. AV_CH_BACK_LEFT |
  275. AV_CH_BACK_RIGHT |
  276. AV_CH_FRONT_LEFT_OF_CENTER |
  277. AV_CH_FRONT_RIGHT_OF_CENTER },
  278. { MOV_CH_LAYOUT_DTS_8_0_B, AV_CH_LAYOUT_5POINT0 | // Lc, C, Rc, L, R, Ls, Cs, Rs
  279. AV_CH_FRONT_LEFT_OF_CENTER |
  280. AV_CH_FRONT_RIGHT_OF_CENTER |
  281. AV_CH_BACK_CENTER },
  282. { 0, 0 },
  283. };
  284. static const struct MovChannelLayoutMap mov_ch_layout_map_9ch[] = {
  285. { MOV_CH_LAYOUT_DTS_8_1_A, AV_CH_LAYOUT_2_2 | // Lc, Rc, L, R, Ls, Rs, Rls, Rrs, LFE
  286. AV_CH_BACK_LEFT |
  287. AV_CH_BACK_RIGHT |
  288. AV_CH_FRONT_LEFT_OF_CENTER |
  289. AV_CH_FRONT_RIGHT_OF_CENTER |
  290. AV_CH_LOW_FREQUENCY },
  291. { MOV_CH_LAYOUT_DTS_8_1_B, AV_CH_LAYOUT_7POINT1_WIDE | // Lc, C, Rc, L, R, Ls, Cs, Rs, LFE
  292. AV_CH_BACK_CENTER },
  293. { 0, 0 },
  294. };
  295. static const struct MovChannelLayoutMap *mov_ch_layout_map[] = {
  296. mov_ch_layout_map_misc,
  297. mov_ch_layout_map_1ch,
  298. mov_ch_layout_map_2ch,
  299. mov_ch_layout_map_3ch,
  300. mov_ch_layout_map_4ch,
  301. mov_ch_layout_map_5ch,
  302. mov_ch_layout_map_6ch,
  303. mov_ch_layout_map_7ch,
  304. mov_ch_layout_map_8ch,
  305. mov_ch_layout_map_9ch,
  306. };
  307. static const enum MovChannelLayoutTag mov_ch_layouts_aac[] = {
  308. MOV_CH_LAYOUT_MONO,
  309. MOV_CH_LAYOUT_STEREO,
  310. MOV_CH_LAYOUT_AC3_1_0_1,
  311. MOV_CH_LAYOUT_MPEG_3_0_B,
  312. MOV_CH_LAYOUT_ITU_2_1,
  313. MOV_CH_LAYOUT_DVD_4,
  314. MOV_CH_LAYOUT_QUADRAPHONIC,
  315. MOV_CH_LAYOUT_MPEG_4_0_B,
  316. MOV_CH_LAYOUT_ITU_2_2,
  317. MOV_CH_LAYOUT_AC3_2_1_1,
  318. MOV_CH_LAYOUT_DTS_3_1,
  319. MOV_CH_LAYOUT_MPEG_5_0_D,
  320. MOV_CH_LAYOUT_DVD_18,
  321. MOV_CH_LAYOUT_DTS_4_1,
  322. MOV_CH_LAYOUT_MPEG_5_1_D,
  323. MOV_CH_LAYOUT_AAC_6_0,
  324. MOV_CH_LAYOUT_DTS_6_0_A,
  325. MOV_CH_LAYOUT_AAC_6_1,
  326. MOV_CH_LAYOUT_AAC_7_0,
  327. MOV_CH_LAYOUT_DTS_6_1_A,
  328. MOV_CH_LAYOUT_AAC_OCTAGONAL,
  329. MOV_CH_LAYOUT_MPEG_7_1_B,
  330. MOV_CH_LAYOUT_DTS_8_0_A,
  331. 0,
  332. };
  333. static const enum MovChannelLayoutTag mov_ch_layouts_ac3[] = {
  334. MOV_CH_LAYOUT_MONO,
  335. MOV_CH_LAYOUT_STEREO,
  336. MOV_CH_LAYOUT_AC3_1_0_1,
  337. MOV_CH_LAYOUT_AC3_3_0,
  338. MOV_CH_LAYOUT_ITU_2_1,
  339. MOV_CH_LAYOUT_DVD_4,
  340. MOV_CH_LAYOUT_AC3_3_1,
  341. MOV_CH_LAYOUT_ITU_2_2,
  342. MOV_CH_LAYOUT_AC3_2_1_1,
  343. MOV_CH_LAYOUT_AC3_3_0_1,
  344. MOV_CH_LAYOUT_MPEG_5_0_C,
  345. MOV_CH_LAYOUT_DVD_18,
  346. MOV_CH_LAYOUT_AC3_3_1_1,
  347. MOV_CH_LAYOUT_MPEG_5_1_C,
  348. 0,
  349. };
  350. static const enum MovChannelLayoutTag mov_ch_layouts_alac[] = {
  351. MOV_CH_LAYOUT_MONO,
  352. MOV_CH_LAYOUT_STEREO,
  353. MOV_CH_LAYOUT_MPEG_3_0_B,
  354. MOV_CH_LAYOUT_MPEG_4_0_B,
  355. MOV_CH_LAYOUT_MPEG_5_0_D,
  356. MOV_CH_LAYOUT_MPEG_5_1_D,
  357. MOV_CH_LAYOUT_AAC_6_1,
  358. MOV_CH_LAYOUT_MPEG_7_1_B,
  359. 0,
  360. };
  361. static const enum MovChannelLayoutTag mov_ch_layouts_wav[] = {
  362. MOV_CH_LAYOUT_MONO,
  363. MOV_CH_LAYOUT_STEREO,
  364. MOV_CH_LAYOUT_MATRIXSTEREO,
  365. MOV_CH_LAYOUT_MPEG_3_0_A,
  366. MOV_CH_LAYOUT_QUADRAPHONIC,
  367. MOV_CH_LAYOUT_MPEG_5_0_A,
  368. MOV_CH_LAYOUT_MPEG_5_1_A,
  369. MOV_CH_LAYOUT_MPEG_6_1_A,
  370. MOV_CH_LAYOUT_MPEG_7_1_A,
  371. MOV_CH_LAYOUT_MPEG_7_1_C,
  372. MOV_CH_LAYOUT_SMPTE_DTV,
  373. };
  374. static const struct {
  375. enum AVCodecID codec_id;
  376. const enum MovChannelLayoutTag *layouts;
  377. } mov_codec_ch_layouts[] = {
  378. { AV_CODEC_ID_AAC, mov_ch_layouts_aac },
  379. { AV_CODEC_ID_AC3, mov_ch_layouts_ac3 },
  380. { AV_CODEC_ID_ALAC, mov_ch_layouts_alac },
  381. { AV_CODEC_ID_PCM_U8, mov_ch_layouts_wav },
  382. { AV_CODEC_ID_PCM_S8, mov_ch_layouts_wav },
  383. { AV_CODEC_ID_PCM_S16LE, mov_ch_layouts_wav },
  384. { AV_CODEC_ID_PCM_S16BE, mov_ch_layouts_wav },
  385. { AV_CODEC_ID_PCM_S24LE, mov_ch_layouts_wav },
  386. { AV_CODEC_ID_PCM_S24BE, mov_ch_layouts_wav },
  387. { AV_CODEC_ID_PCM_S32LE, mov_ch_layouts_wav },
  388. { AV_CODEC_ID_PCM_S32BE, mov_ch_layouts_wav },
  389. { AV_CODEC_ID_PCM_F32LE, mov_ch_layouts_wav },
  390. { AV_CODEC_ID_PCM_F32BE, mov_ch_layouts_wav },
  391. { AV_CODEC_ID_PCM_F64LE, mov_ch_layouts_wav },
  392. { AV_CODEC_ID_PCM_F64BE, mov_ch_layouts_wav },
  393. { AV_CODEC_ID_NONE, NULL },
  394. };
  395. uint64_t ff_mov_get_channel_layout(uint32_t tag, uint32_t bitmap)
  396. {
  397. int i, channels;
  398. const struct MovChannelLayoutMap *layout_map;
  399. /* use ff_mov_get_channel_label() to build a layout instead */
  400. if (tag == MOV_CH_LAYOUT_USE_DESCRIPTIONS)
  401. return 0;
  402. /* handle the use of the channel bitmap */
  403. if (tag == MOV_CH_LAYOUT_USE_BITMAP)
  404. return bitmap < 0x40000 ? bitmap : 0;
  405. /* get the layout map based on the channel count for the specified layout tag */
  406. channels = tag & 0xFFFF;
  407. if (channels > 9)
  408. channels = 0;
  409. layout_map = mov_ch_layout_map[channels];
  410. /* find the channel layout for the specified layout tag */
  411. for (i = 0; layout_map[i].tag != 0; i++) {
  412. if (layout_map[i].tag == tag)
  413. break;
  414. }
  415. return layout_map[i].layout;
  416. }
  417. static uint32_t mov_get_channel_label(uint32_t label)
  418. {
  419. if (label == 0)
  420. return 0;
  421. if (label <= 18)
  422. return 1U << (label - 1);
  423. if (label == 38)
  424. return AV_CH_STEREO_LEFT;
  425. if (label == 39)
  426. return AV_CH_STEREO_RIGHT;
  427. return 0;
  428. }
  429. uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id,
  430. uint64_t channel_layout,
  431. uint32_t *bitmap)
  432. {
  433. int i, j;
  434. uint32_t tag = 0;
  435. const enum MovChannelLayoutTag *layouts = NULL;
  436. /* find the layout list for the specified codec */
  437. for (i = 0; mov_codec_ch_layouts[i].codec_id != AV_CODEC_ID_NONE; i++) {
  438. if (mov_codec_ch_layouts[i].codec_id == codec_id)
  439. break;
  440. }
  441. if (mov_codec_ch_layouts[i].codec_id != AV_CODEC_ID_NONE)
  442. layouts = mov_codec_ch_layouts[i].layouts;
  443. if (layouts) {
  444. int channels;
  445. const struct MovChannelLayoutMap *layout_map;
  446. /* get the layout map based on the channel count */
  447. channels = av_get_channel_layout_nb_channels(channel_layout);
  448. if (channels > 9)
  449. channels = 0;
  450. layout_map = mov_ch_layout_map[channels];
  451. /* find the layout tag for the specified channel layout */
  452. for (i = 0; layouts[i] != 0; i++) {
  453. if ((layouts[i] & 0xFFFF) != channels)
  454. continue;
  455. for (j = 0; layout_map[j].tag != 0; j++) {
  456. if (layout_map[j].tag == layouts[i] &&
  457. layout_map[j].layout == channel_layout)
  458. break;
  459. }
  460. if (layout_map[j].tag)
  461. break;
  462. }
  463. tag = layouts[i];
  464. }
  465. /* if no tag was found, use channel bitmap as a backup if possible */
  466. if (tag == 0 && channel_layout > 0 && channel_layout < 0x40000) {
  467. tag = MOV_CH_LAYOUT_USE_BITMAP;
  468. *bitmap = (uint32_t)channel_layout;
  469. } else
  470. *bitmap = 0;
  471. /* TODO: set channel descriptions as a secondary backup */
  472. return tag;
  473. }
  474. int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st,
  475. int64_t size)
  476. {
  477. uint32_t layout_tag, bitmap, num_descr, label_mask;
  478. int i;
  479. if (size < 12)
  480. return AVERROR_INVALIDDATA;
  481. layout_tag = avio_rb32(pb);
  482. bitmap = avio_rb32(pb);
  483. num_descr = avio_rb32(pb);
  484. av_dlog(s, "chan: layout=%u bitmap=%u num_descr=%u\n",
  485. layout_tag, bitmap, num_descr);
  486. if (size < 12ULL + num_descr * 20ULL)
  487. return 0;
  488. label_mask = 0;
  489. for (i = 0; i < num_descr; i++) {
  490. uint32_t label;
  491. label = avio_rb32(pb); // mChannelLabel
  492. avio_rb32(pb); // mChannelFlags
  493. avio_rl32(pb); // mCoordinates[0]
  494. avio_rl32(pb); // mCoordinates[1]
  495. avio_rl32(pb); // mCoordinates[2]
  496. size -= 20;
  497. if (layout_tag == 0) {
  498. uint32_t mask_incr = mov_get_channel_label(label);
  499. if (mask_incr == 0) {
  500. label_mask = 0;
  501. break;
  502. }
  503. label_mask |= mask_incr;
  504. }
  505. }
  506. if (layout_tag == 0) {
  507. if (label_mask)
  508. st->codec->channel_layout = label_mask;
  509. } else
  510. st->codec->channel_layout = ff_mov_get_channel_layout(layout_tag, bitmap);
  511. avio_skip(pb, size - 12);
  512. return 0;
  513. }