/src/ffmpeg/libavformat/isom.c
Line | Count | Source |
1 | | /* |
2 | | * ISO Media common code |
3 | | * Copyright (c) 2001 Fabrice Bellard |
4 | | * Copyright (c) 2002 Francois Revol <revol@free.fr> |
5 | | * Copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@free.fr> |
6 | | * |
7 | | * This file is part of FFmpeg. |
8 | | * |
9 | | * FFmpeg is free software; you can redistribute it and/or |
10 | | * modify it under the terms of the GNU Lesser General Public |
11 | | * License as published by the Free Software Foundation; either |
12 | | * version 2.1 of the License, or (at your option) any later version. |
13 | | * |
14 | | * FFmpeg is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 | | * Lesser General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public |
20 | | * License along with FFmpeg; if not, write to the Free Software |
21 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 | | */ |
23 | | |
24 | | #include "avformat.h" |
25 | | #include "demux.h" |
26 | | #include "internal.h" |
27 | | #include "isom.h" |
28 | | #include "libavcodec/mpeg4audio.h" |
29 | | #include "libavcodec/mpegaudiodata.h" |
30 | | #include "libavutil/channel_layout.h" |
31 | | |
32 | | /* http://www.mp4ra.org */ |
33 | | /* ordered by muxing preference */ |
34 | | const AVCodecTag ff_mp4_obj_type[] = { |
35 | | { AV_CODEC_ID_MOV_TEXT , 0x08 }, |
36 | | { AV_CODEC_ID_MPEG4 , 0x20 }, |
37 | | { AV_CODEC_ID_H264 , 0x21 }, |
38 | | { AV_CODEC_ID_HEVC , 0x23 }, |
39 | | { AV_CODEC_ID_VVC , 0x33 }, |
40 | | { AV_CODEC_ID_AAC , 0x40 }, |
41 | | { AV_CODEC_ID_MP4ALS , 0x40 }, /* 14496-3 ALS */ |
42 | | { AV_CODEC_ID_MPEG2VIDEO , 0x61 }, /* MPEG-2 Main */ |
43 | | { AV_CODEC_ID_MPEG2VIDEO , 0x60 }, /* MPEG-2 Simple */ |
44 | | { AV_CODEC_ID_MPEG2VIDEO , 0x62 }, /* MPEG-2 SNR */ |
45 | | { AV_CODEC_ID_MPEG2VIDEO , 0x63 }, /* MPEG-2 Spatial */ |
46 | | { AV_CODEC_ID_MPEG2VIDEO , 0x64 }, /* MPEG-2 High */ |
47 | | { AV_CODEC_ID_MPEG2VIDEO , 0x65 }, /* MPEG-2 422 */ |
48 | | { AV_CODEC_ID_AAC , 0x66 }, /* MPEG-2 AAC Main */ |
49 | | { AV_CODEC_ID_AAC , 0x67 }, /* MPEG-2 AAC Low */ |
50 | | { AV_CODEC_ID_AAC , 0x68 }, /* MPEG-2 AAC SSR */ |
51 | | { AV_CODEC_ID_MP3 , 0x69 }, /* 13818-3 */ |
52 | | { AV_CODEC_ID_MP2 , 0x69 }, /* 11172-3 */ |
53 | | { AV_CODEC_ID_MPEG1VIDEO , 0x6A }, /* 11172-2 */ |
54 | | { AV_CODEC_ID_MP3 , 0x6B }, /* 11172-3 */ |
55 | | { AV_CODEC_ID_MJPEG , 0x6C }, /* 10918-1 */ |
56 | | { AV_CODEC_ID_PNG , 0x6D }, |
57 | | { AV_CODEC_ID_JPEG2000 , 0x6E }, /* 15444-1 */ |
58 | | { AV_CODEC_ID_VC1 , 0xA3 }, |
59 | | { AV_CODEC_ID_DIRAC , 0xA4 }, |
60 | | { AV_CODEC_ID_AC3 , 0xA5 }, |
61 | | { AV_CODEC_ID_EAC3 , 0xA6 }, |
62 | | { AV_CODEC_ID_DTS , 0xA9 }, /* mp4ra.org */ |
63 | | { AV_CODEC_ID_OPUS , 0xAD }, /* mp4ra.org */ |
64 | | { AV_CODEC_ID_VP9 , 0xB1 }, /* mp4ra.org */ |
65 | | { AV_CODEC_ID_TSCC2 , 0xD0 }, /* nonstandard, camtasia uses it */ |
66 | | { AV_CODEC_ID_EVRC , 0xD1 }, /* nonstandard, pvAuthor uses it */ |
67 | | { AV_CODEC_ID_VORBIS , 0xDD }, /* nonstandard, gpac uses it */ |
68 | | { AV_CODEC_ID_DVD_SUBTITLE, 0xE0 }, /* nonstandard, see unsupported-embedded-subs-2.mp4 */ |
69 | | { AV_CODEC_ID_QCELP , 0xE1 }, |
70 | | { AV_CODEC_ID_MPEG4SYSTEMS, 0x01 }, |
71 | | { AV_CODEC_ID_MPEG4SYSTEMS, 0x02 }, |
72 | | { AV_CODEC_ID_NONE , 0 }, |
73 | | }; |
74 | | |
75 | | const AVCodecTag ff_codec_movsubtitle_tags[] = { |
76 | | { AV_CODEC_ID_MOV_TEXT, MKTAG('t', 'e', 'x', 't') }, |
77 | | { AV_CODEC_ID_MOV_TEXT, MKTAG('t', 'x', '3', 'g') }, |
78 | | { AV_CODEC_ID_EIA_608, MKTAG('c', '6', '0', '8') }, |
79 | | { AV_CODEC_ID_NONE, 0 }, |
80 | | }; |
81 | | |
82 | | const AVCodecTag ff_codec_movdata_tags[] = { |
83 | | { AV_CODEC_ID_BIN_DATA, MKTAG('g', 'p', 'm', 'd') }, |
84 | | { AV_CODEC_ID_NONE, 0 }, |
85 | | }; |
86 | | |
87 | | /* map numeric codes from mdhd atom to ISO 639 */ |
88 | | /* cf. QTFileFormat.pdf p253, qtff.pdf p205 */ |
89 | | /* http://developer.apple.com/documentation/mac/Text/Text-368.html */ |
90 | | /* deprecated by putting the code as 3*5 bits ASCII */ |
91 | | static const char mov_mdhd_language_map[][4] = { |
92 | | "eng", /* 0 English */ |
93 | | "fra", /* 1 French */ |
94 | | "ger", /* 2 German */ |
95 | | "ita", /* 3 Italian */ |
96 | | "dut", /* 4 Dutch */ |
97 | | "sve", /* 5 Swedish */ |
98 | | "spa", /* 6 Spanish */ |
99 | | "dan", /* 7 Danish */ |
100 | | "por", /* 8 Portuguese */ |
101 | | "nor", /* 9 Norwegian */ |
102 | | "heb", /* 10 Hebrew */ |
103 | | "jpn", /* 11 Japanese */ |
104 | | "ara", /* 12 Arabic */ |
105 | | "fin", /* 13 Finnish */ |
106 | | "gre", /* 14 Greek */ |
107 | | "ice", /* 15 Icelandic */ |
108 | | "mlt", /* 16 Maltese */ |
109 | | "tur", /* 17 Turkish */ |
110 | | "hr ", /* 18 Croatian */ |
111 | | "chi", /* 19 Traditional Chinese */ |
112 | | "urd", /* 20 Urdu */ |
113 | | "hin", /* 21 Hindi */ |
114 | | "tha", /* 22 Thai */ |
115 | | "kor", /* 23 Korean */ |
116 | | "lit", /* 24 Lithuanian */ |
117 | | "pol", /* 25 Polish */ |
118 | | "hun", /* 26 Hungarian */ |
119 | | "est", /* 27 Estonian */ |
120 | | "lav", /* 28 Latvian */ |
121 | | "smi", /* 29 Sami */ |
122 | | "fo ", /* 30 Faroese */ |
123 | | "per", /* 31 Farsi */ |
124 | | "rus", /* 32 Russian */ |
125 | | "chi", /* 33 Simplified Chinese */ |
126 | | "", /* 34 Flemish */ |
127 | | "iri", /* 35 Irish */ |
128 | | "alb", /* 36 Albanian */ |
129 | | "ron", /* 37 Romanian */ |
130 | | "ces", /* 38 Czech */ |
131 | | "slk", /* 39 Slovak */ |
132 | | "slv", /* 40 Slovenian */ |
133 | | "yid", /* 41 Yiddish */ |
134 | | "sr ", /* 42 Serbian */ |
135 | | "mac", /* 43 Macedonian */ |
136 | | "bul", /* 44 Bulgarian */ |
137 | | "ukr", /* 45 Ukrainian */ |
138 | | "bel", /* 46 Belarusian */ |
139 | | "uzb", /* 47 Uzbek */ |
140 | | "kaz", /* 48 Kazakh */ |
141 | | "aze", /* 49 Azerbaijani */ |
142 | | "aze", /* 50 AzerbaijanAr */ |
143 | | "arm", /* 51 Armenian */ |
144 | | "geo", /* 52 Georgian */ |
145 | | "mol", /* 53 Moldavian */ |
146 | | "kir", /* 54 Kirghiz */ |
147 | | "tgk", /* 55 Tajiki */ |
148 | | "tuk", /* 56 Turkmen */ |
149 | | "mon", /* 57 Mongolian */ |
150 | | "", /* 58 MongolianCyr */ |
151 | | "pus", /* 59 Pashto */ |
152 | | "kur", /* 60 Kurdish */ |
153 | | "kas", /* 61 Kashmiri */ |
154 | | "snd", /* 62 Sindhi */ |
155 | | "tib", /* 63 Tibetan */ |
156 | | "nep", /* 64 Nepali */ |
157 | | "san", /* 65 Sanskrit */ |
158 | | "mar", /* 66 Marathi */ |
159 | | "ben", /* 67 Bengali */ |
160 | | "asm", /* 68 Assamese */ |
161 | | "guj", /* 69 Gujarati */ |
162 | | "pa ", /* 70 Punjabi */ |
163 | | "ori", /* 71 Oriya */ |
164 | | "mal", /* 72 Malayalam */ |
165 | | "kan", /* 73 Kannada */ |
166 | | "tam", /* 74 Tamil */ |
167 | | "tel", /* 75 Telugu */ |
168 | | "sin", /* 76 Sinhala */ |
169 | | "bur", /* 77 Burmese */ |
170 | | "khm", /* 78 Khmer */ |
171 | | "lao", /* 79 Lao */ |
172 | | "vie", /* 80 Vietnamese */ |
173 | | "ind", /* 81 Indonesian */ |
174 | | "tgl", /* 82 Tagalog */ |
175 | | "may", /* 83 MalayRoman */ |
176 | | "may", /* 84 MalayArabic */ |
177 | | "amh", /* 85 Amharic */ |
178 | | "tir", /* 86 Galla */ |
179 | | "orm", /* 87 Oromo */ |
180 | | "som", /* 88 Somali */ |
181 | | "swa", /* 89 Swahili */ |
182 | | "kin", /* 90 Kinyarwanda */ |
183 | | "run", /* 91 Rundi */ |
184 | | "nya", /* 92 Nyanja */ |
185 | | "mlg", /* 93 Malagasy */ |
186 | | "epo", /* 94 Esperanto */ |
187 | | "", /* 95 */ |
188 | | "", /* 96 */ |
189 | | "", /* 97 */ |
190 | | "", /* 98 */ |
191 | | "", /* 99 */ |
192 | | "", /* 100 */ |
193 | | "", /* 101 */ |
194 | | "", /* 102 */ |
195 | | "", /* 103 */ |
196 | | "", /* 104 */ |
197 | | "", /* 105 */ |
198 | | "", /* 106 */ |
199 | | "", /* 107 */ |
200 | | "", /* 108 */ |
201 | | "", /* 109 */ |
202 | | "", /* 110 */ |
203 | | "", /* 111 */ |
204 | | "", /* 112 */ |
205 | | "", /* 113 */ |
206 | | "", /* 114 */ |
207 | | "", /* 115 */ |
208 | | "", /* 116 */ |
209 | | "", /* 117 */ |
210 | | "", /* 118 */ |
211 | | "", /* 119 */ |
212 | | "", /* 120 */ |
213 | | "", /* 121 */ |
214 | | "", /* 122 */ |
215 | | "", /* 123 */ |
216 | | "", /* 124 */ |
217 | | "", /* 125 */ |
218 | | "", /* 126 */ |
219 | | "", /* 127 */ |
220 | | "wel", /* 128 Welsh */ |
221 | | "baq", /* 129 Basque */ |
222 | | "cat", /* 130 Catalan */ |
223 | | "lat", /* 131 Latin */ |
224 | | "que", /* 132 Quechua */ |
225 | | "grn", /* 133 Guarani */ |
226 | | "aym", /* 134 Aymara */ |
227 | | "tat", /* 135 Tatar */ |
228 | | "uig", /* 136 Uighur */ |
229 | | "dzo", /* 137 Dzongkha */ |
230 | | "jav", /* 138 JavaneseRom */ |
231 | | }; |
232 | | |
233 | | int ff_mov_iso639_to_lang(const char lang[4], int mp4) |
234 | 0 | { |
235 | 0 | int i, code = 0; |
236 | | |
237 | | /* old way, only for QT? */ |
238 | 0 | for (i = 0; lang[0] && !mp4 && i < FF_ARRAY_ELEMS(mov_mdhd_language_map); i++) { |
239 | 0 | if (!strcmp(lang, mov_mdhd_language_map[i])) |
240 | 0 | return i; |
241 | 0 | } |
242 | | /* XXX:can we do that in mov too? */ |
243 | 0 | if (!mp4) |
244 | 0 | return -1; |
245 | | /* handle undefined as such */ |
246 | 0 | if (lang[0] == '\0') |
247 | 0 | lang = "und"; |
248 | | /* 5 bits ASCII */ |
249 | 0 | for (i = 0; i < 3; i++) { |
250 | 0 | uint8_t c = lang[i]; |
251 | 0 | c -= 0x60; |
252 | 0 | if (c > 0x1f) |
253 | 0 | return -1; |
254 | 0 | code <<= 5; |
255 | 0 | code |= c; |
256 | 0 | } |
257 | 0 | return code; |
258 | 0 | } |
259 | | |
260 | | int ff_mov_lang_to_iso639(unsigned code, char to[4]) |
261 | 44.2k | { |
262 | 44.2k | int i; |
263 | 44.2k | memset(to, 0, 4); |
264 | | /* is it the mangled iso code? */ |
265 | | /* see http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt */ |
266 | 44.2k | if (code >= 0x400 && code != 0x7fff) { |
267 | 99.2k | for (i = 2; i >= 0; i--) { |
268 | 74.4k | to[i] = 0x60 + (code & 0x1f); |
269 | 74.4k | code >>= 5; |
270 | 74.4k | } |
271 | 24.8k | return 1; |
272 | 24.8k | } |
273 | | /* old fashion apple lang code */ |
274 | 19.3k | if (code >= FF_ARRAY_ELEMS(mov_mdhd_language_map)) |
275 | 2.83k | return 0; |
276 | 16.5k | if (!mov_mdhd_language_map[code][0]) |
277 | 2.32k | return 0; |
278 | 14.2k | memcpy(to, mov_mdhd_language_map[code], 4); |
279 | 14.2k | return 1; |
280 | 16.5k | } |
281 | | |
282 | | int ff_mp4_read_descr_len(AVIOContext *pb) |
283 | 6.90M | { |
284 | 6.90M | int len = 0; |
285 | 6.90M | int count = 4; |
286 | 8.80M | while (count--) { |
287 | 8.62M | int c = avio_r8(pb); |
288 | 8.62M | len = (len << 7) | (c & 0x7f); |
289 | 8.62M | if (!(c & 0x80)) |
290 | 6.72M | break; |
291 | 8.62M | } |
292 | 6.90M | return len; |
293 | 6.90M | } |
294 | | |
295 | | int ff_mp4_read_descr(void *logctx, AVIOContext *pb, int *tag) |
296 | 705k | { |
297 | 705k | int len; |
298 | 705k | *tag = avio_r8(pb); |
299 | 705k | len = ff_mp4_read_descr_len(pb); |
300 | 705k | av_log(logctx, AV_LOG_TRACE, "MPEG-4 description: tag=0x%02x len=%d\n", *tag, len); |
301 | 705k | return len; |
302 | 705k | } |
303 | | |
304 | | void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id) |
305 | 66.0k | { |
306 | 66.0k | int flags; |
307 | 66.0k | if (es_id) *es_id = avio_rb16(pb); |
308 | 66.0k | else avio_rb16(pb); |
309 | 66.0k | flags = avio_r8(pb); |
310 | 66.0k | if (flags & 0x80) //streamDependenceFlag |
311 | 7.31k | avio_rb16(pb); |
312 | 66.0k | if (flags & 0x40) { //URL_Flag |
313 | 45.5k | int len = avio_r8(pb); |
314 | 45.5k | avio_skip(pb, len); |
315 | 45.5k | } |
316 | 66.0k | if (flags & 0x20) //OCRstreamFlag |
317 | 10.5k | avio_rb16(pb); |
318 | 66.0k | } |
319 | | |
320 | | static const AVCodecTag mp4_audio_types[] = { |
321 | | { AV_CODEC_ID_MP3ON4, AOT_PS }, /* old mp3on4 draft */ |
322 | | { AV_CODEC_ID_MP3ON4, AOT_L1 }, /* layer 1 */ |
323 | | { AV_CODEC_ID_MP3ON4, AOT_L2 }, /* layer 2 */ |
324 | | { AV_CODEC_ID_MP3ON4, AOT_L3 }, /* layer 3 */ |
325 | | { AV_CODEC_ID_MP4ALS, AOT_ALS }, /* MPEG-4 ALS */ |
326 | | { AV_CODEC_ID_NONE, AOT_NULL }, |
327 | | }; |
328 | | |
329 | | int ff_mp4_read_dec_config_descr(void *logctx, AVStream *st, AVIOContext *pb) |
330 | 199k | { |
331 | 199k | enum AVCodecID codec_id; |
332 | 199k | int len, tag; |
333 | 199k | int ret; |
334 | 199k | int object_type_id = avio_r8(pb); |
335 | 199k | avio_r8(pb); /* stream type */ |
336 | 199k | avio_rb24(pb); /* buffer size db */ |
337 | 199k | avio_rb32(pb); /* rc_max_rate */ |
338 | | |
339 | 199k | st->codecpar->bit_rate = avio_rb32(pb); /* avg bitrate */ |
340 | | |
341 | 199k | codec_id= ff_codec_get_id(ff_mp4_obj_type, object_type_id); |
342 | 199k | if (codec_id) |
343 | 119k | st->codecpar->codec_id = codec_id; |
344 | 199k | av_log(logctx, AV_LOG_TRACE, "esds object type id 0x%02x\n", object_type_id); |
345 | 199k | len = ff_mp4_read_descr(logctx, pb, &tag); |
346 | 199k | if (tag == MP4DecSpecificDescrTag) { |
347 | 122k | av_log(logctx, AV_LOG_TRACE, "Specific MPEG-4 header len=%d\n", len); |
348 | | /* As per 14496-3:2009 9.D.2.2, No decSpecificInfo is defined |
349 | | for MPEG-1 Audio or MPEG-2 Audio; MPEG-2 AAC excluded. */ |
350 | 122k | if (object_type_id == 0x69 || object_type_id == 0x6b) |
351 | 360 | return 0; |
352 | 122k | if (!len || (uint64_t)len > (1<<30)) |
353 | 199 | return AVERROR_INVALIDDATA; |
354 | 121k | if ((ret = ff_get_extradata(logctx, st->codecpar, pb, len)) < 0) |
355 | 45 | return ret; |
356 | 121k | if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { |
357 | 96.5k | MPEG4AudioConfig cfg = {0}; |
358 | 96.5k | ret = avpriv_mpeg4audio_get_config2(&cfg, st->codecpar->extradata, |
359 | 96.5k | st->codecpar->extradata_size, 1, logctx); |
360 | 96.5k | if (ret < 0) |
361 | 1.19k | return ret; |
362 | 95.3k | if (cfg.channels != st->codecpar->ch_layout.nb_channels) { |
363 | 41.8k | av_channel_layout_uninit(&st->codecpar->ch_layout); |
364 | 41.8k | st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; |
365 | 41.8k | st->codecpar->ch_layout.nb_channels = cfg.channels; |
366 | 41.8k | } |
367 | 95.3k | if (cfg.object_type == 29 && cfg.sampling_index < 3) // old mp3on4 |
368 | 246 | st->codecpar->sample_rate = ff_mpa_freq_tab[cfg.sampling_index]; |
369 | 95.0k | else if (cfg.ext_sample_rate) |
370 | 41.6k | st->codecpar->sample_rate = cfg.ext_sample_rate; |
371 | 53.4k | else |
372 | 53.4k | st->codecpar->sample_rate = cfg.sample_rate; |
373 | 95.3k | av_log(logctx, AV_LOG_TRACE, "mp4a config channels %d obj %d ext obj %d " |
374 | 95.3k | "sample rate %d ext sample rate %d\n", cfg.channels, |
375 | 95.3k | cfg.object_type, cfg.ext_object_type, |
376 | 95.3k | cfg.sample_rate, cfg.ext_sample_rate); |
377 | 95.3k | if (!(st->codecpar->codec_id = ff_codec_get_id(mp4_audio_types, |
378 | 95.3k | cfg.object_type))) |
379 | 80.8k | st->codecpar->codec_id = AV_CODEC_ID_AAC; |
380 | 95.3k | } |
381 | 121k | } |
382 | 197k | return 0; |
383 | 199k | } |
384 | | |
385 | | typedef struct MovChannelLayout { |
386 | | int64_t channel_layout; |
387 | | uint32_t layout_tag; |
388 | | } MovChannelLayout; |
389 | | |
390 | | static const MovChannelLayout mov_channel_layout[] = { |
391 | | { AV_CH_LAYOUT_MONO, (100<<16) | 1}, // kCAFChannelLayoutTag_Mono |
392 | | { AV_CH_LAYOUT_STEREO, (101<<16) | 2}, // kCAFChannelLayoutTag_Stereo |
393 | | { AV_CH_LAYOUT_STEREO, (102<<16) | 2}, // kCAFChannelLayoutTag_StereoHeadphones |
394 | | { AV_CH_LAYOUT_2_1, (131<<16) | 3}, // kCAFChannelLayoutTag_ITU_2_1 |
395 | | { AV_CH_LAYOUT_QUAD, (132<<16) | 4}, // kCAFChannelLayoutTag_ITU_2_2 |
396 | | { AV_CH_LAYOUT_2_2, (132<<16) | 4}, // kCAFChannelLayoutTag_ITU_2_2 |
397 | | { AV_CH_LAYOUT_QUAD, (108<<16) | 4}, // kCAFChannelLayoutTag_Quadraphonic |
398 | | { AV_CH_LAYOUT_SURROUND, (113<<16) | 3}, // kCAFChannelLayoutTag_MPEG_3_0_A |
399 | | { AV_CH_LAYOUT_4POINT0, (115<<16) | 4}, // kCAFChannelLayoutTag_MPEG_4_0_A |
400 | | { AV_CH_LAYOUT_5POINT0_BACK, (117<<16) | 5}, // kCAFChannelLayoutTag_MPEG_5_0_A |
401 | | { AV_CH_LAYOUT_5POINT0, (117<<16) | 5}, // kCAFChannelLayoutTag_MPEG_5_0_A |
402 | | { AV_CH_LAYOUT_5POINT1_BACK, (121<<16) | 6}, // kCAFChannelLayoutTag_MPEG_5_1_A |
403 | | { AV_CH_LAYOUT_5POINT1, (121<<16) | 6}, // kCAFChannelLayoutTag_MPEG_5_1_A |
404 | | { AV_CH_LAYOUT_7POINT1, (128<<16) | 8}, // kCAFChannelLayoutTag_MPEG_7_1_C |
405 | | { AV_CH_LAYOUT_7POINT1_WIDE, (126<<16) | 8}, // kCAFChannelLayoutTag_MPEG_7_1_A |
406 | | { AV_CH_LAYOUT_5POINT1_BACK|AV_CH_LAYOUT_STEREO_DOWNMIX, (130<<16) | 8}, // kCAFChannelLayoutTag_SMPTE_DTV |
407 | | { AV_CH_LAYOUT_2POINT1, (133<<16) | 3}, // kCAFChannelLayoutTag_DVD_4 |
408 | | { AV_CH_LAYOUT_2_1|AV_CH_LOW_FREQUENCY, (134<<16) | 4}, // kCAFChannelLayoutTag_DVD_5 |
409 | | { AV_CH_LAYOUT_QUAD|AV_CH_LOW_FREQUENCY, (135<<16) | 4}, // kCAFChannelLayoutTag_DVD_6 |
410 | | { AV_CH_LAYOUT_2_2|AV_CH_LOW_FREQUENCY, (135<<16) | 4}, // kCAFChannelLayoutTag_DVD_6 |
411 | | { AV_CH_LAYOUT_3POINT1, (136<<16) | 4}, // kCAFChannelLayoutTag_DVD_10 |
412 | | { AV_CH_LAYOUT_4POINT1, (137<<16) | 5}, // kCAFChannelLayoutTag_DVD_11 |
413 | | { 0, 0}, |
414 | | }; |
415 | | |
416 | | void ff_mov_write_chan(AVIOContext *pb, int64_t channel_layout) |
417 | 0 | { |
418 | 0 | const MovChannelLayout *layouts; |
419 | 0 | uint32_t layout_tag = 0; |
420 | |
|
421 | 0 | for (layouts = mov_channel_layout; layouts->channel_layout; layouts++) |
422 | 0 | if (channel_layout == layouts->channel_layout) { |
423 | 0 | layout_tag = layouts->layout_tag; |
424 | 0 | break; |
425 | 0 | } |
426 | |
|
427 | 0 | if (layout_tag) { |
428 | 0 | avio_wb32(pb, layout_tag); // mChannelLayoutTag |
429 | 0 | avio_wb32(pb, 0); // mChannelBitmap |
430 | 0 | } else { |
431 | 0 | avio_wb32(pb, 0x10000); // kCAFChannelLayoutTag_UseChannelBitmap |
432 | 0 | avio_wb32(pb, channel_layout); |
433 | 0 | } |
434 | 0 | avio_wb32(pb, 0); // mNumberChannelDescriptions |
435 | 0 | } |
436 | | |
437 | | static const struct MP4TrackKindValueMapping dash_role_map[] = { |
438 | | { AV_DISPOSITION_HEARING_IMPAIRED|AV_DISPOSITION_CAPTIONS, |
439 | | "caption" }, |
440 | | { AV_DISPOSITION_COMMENT, |
441 | | "commentary" }, |
442 | | { AV_DISPOSITION_VISUAL_IMPAIRED|AV_DISPOSITION_DESCRIPTIONS, |
443 | | "description" }, |
444 | | { AV_DISPOSITION_DUB, |
445 | | "dub" }, |
446 | | { AV_DISPOSITION_FORCED, |
447 | | "forced-subtitle" }, |
448 | | { 0, NULL } |
449 | | }; |
450 | | |
451 | | const struct MP4TrackKindMapping ff_mov_track_kind_table[] = { |
452 | | { "urn:mpeg:dash:role:2011", dash_role_map }, |
453 | | { 0, NULL } |
454 | | }; |