Created
July 9, 2017 10:34
-
-
Save karanlyons/a196433c6cf6ba4a036af77c47d980e2 to your computer and use it in GitHub Desktop.
Javascript QTFF/MP4 Parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<body> | |
<script> | |
'use strict'; | |
ArrayBuffer.prototype.toSource = function(hex) { | |
var buf = this, | |
bytes = Array.prototype.slice.call(new Uint8Array(buf)), | |
i = buf.byteLength, | |
blank = true; | |
while (i--) { | |
if (blank && bytes[i]) { | |
blank = false; | |
} | |
if (hex) { | |
bytes[i] = ("00" + bytes[i].toString(16)).slice(-2); | |
} | |
} | |
if (blank) { | |
return "ArrayBuffer(" + buf.byteLength + ")"; | |
} else { | |
return "Uint8Array([" + bytes.join(" ") + "])"; | |
} | |
}; | |
// Constants | |
var QT_EPOCH = new Date('January 1 1904 00:00:00 UTC'); | |
var ATOM_NAMES = { | |
'ftyp': 'File Type', | |
'moov': 'Movie', | |
'mvhd': 'Movie Header', | |
'iods': 'Inital Object Descriptor', | |
'trak': 'Track', | |
'tkhd': 'Track Header', | |
'mdia': 'Media', | |
'mdhd': 'Media Header', | |
'hdlr': 'Handler Description', | |
'minf': 'Media Information', | |
'vmhd': 'Video Media Header', | |
'dinf': 'Data Information', | |
'dref': 'Data Reference', | |
'stbl': 'Sample Table', | |
'stsd': 'Sample Descriptions', | |
'stts': 'Sample to Time', | |
'stsz': 'Sample Sizes', | |
'stsc': 'Sample to Chunk', | |
'stco': 'Chunk Offset Table', | |
'ctts': 'Composition Offsets', | |
'stss': 'Sync Samples', | |
'sdtp': 'Independent/Disposable Samples', | |
'edts': 'Edits', | |
'elst': 'Edit List', | |
'udta': 'User Data', | |
'meta': 'Metadata', | |
'mdat': 'Media Data', | |
}; | |
var USER_TAG_DESCRIPTIONS = { | |
'AllF': "Play all frames—byte indicating that all frames of video should be played, regardless of timing", | |
'hinf': "Hint track information—statistical data for real-time streaming of a particular track.", | |
'hnti': "Hint info atom—data used for real-time streaming of a movie or a track.", | |
'LOOP': "Long integer indicating looping style. This atom is not present unless the movie is set to loop. Values are 0 for normal looping, 1 for palindromic looping.", | |
'name': "Name of object", | |
'ptv ': "Print to video—display movie in full screen mode. This atom contains a 16-byte structure, described in Print to Video (Full Screen Mode).", | |
'SelO': "Play selection only—byte indicating that only the selected area of the movie should be played", | |
'tagc': "Media characteristic optionally present in Track user data—specialized text that describes something of interest about the track.", | |
'tnam': "Localized track name optionally present in Track user data. The payload is described in Track Name.", | |
'WLOC': "Default window location for movie—two 16-bit values, {x,y}", | |
'©arg': "Name of arranger", | |
'©ark': "Keywords for arranger", | |
'©cok': "Keywords for composer", | |
'©com': "Name of composer", | |
'©cpy': "Copyright statement", | |
'©day': "Date the movie content was created", | |
'©dir': "Name of movie's director", | |
'©ed1': "Edit dates and descriptions", | |
'©ed2': "Edit dates and descriptions", | |
'©ed3': "Edit dates and descriptions", | |
'©ed4': "Edit dates and descriptions", | |
'©ed5': "Edit dates and descriptions", | |
'©ed6': "Edit dates and descriptions", | |
'©ed7': "Edit dates and descriptions", | |
'©ed8': "Edit dates and descriptions", | |
'©ed9': "Edit dates and descriptions", | |
'©fmt': "Indication of movie format (computer-generated, digitized, and so on)", | |
'©inf': "Information about the movie", | |
'©isr': "ISRC code", | |
'©lab': "Name of record label", | |
'©lal': "URL of record label", | |
'©mak': "Name of file creator or maker", | |
'©mal': "URL of file creator or maker", | |
'©nak': "Title keywords of the content", | |
'©nam': "Title of the content", | |
'©pdk': "Keywords for producer", | |
'©phg': "Recording copyright statement, normally preceded by the symbol (P)", | |
'©prd': "Name of producer", | |
'©prf': "Names of performers", | |
'©prk': "Keywords of main artist and performer", | |
'©prl': "URL of main artist and performer", | |
'©req': "Special hardware and software requirements", | |
'©snk': "Subtitle keywords of the content", | |
'©snm': "Subtitle of content", | |
'©src': "Credits for those who provided movie source content", | |
'©swf': "Name of songwriter", | |
'©swk': "Keywords for songwriter", | |
'©swr': "Name and version number of the software (or hardware) that generated this movie", | |
'©wrt': "Name of movie's writer", | |
}; | |
var MACINTOSH_LANGUAGE_CODES = { | |
0: 'English', | |
1: 'French', | |
2: 'German', | |
3: 'Italian', | |
4: 'Dutch', | |
5: 'Swedish', | |
6: 'Spanish', | |
7: 'Danish', | |
8: 'Portuguese', | |
9: 'Norwegian', | |
10: 'Hebrew', | |
11: 'Japanese', | |
12: 'Arabic', | |
13: 'Finnish', | |
14: 'Greek', | |
15: 'Icelandic', | |
16: 'Maltese', | |
17: 'Turkish', | |
18: 'Croatian', | |
19: 'Traditional Chinese', | |
20: 'Urdu', | |
21: 'Hindi', | |
22: 'Thai', | |
23: 'Korean', | |
24: 'Lithuanian', | |
25: 'Polish', | |
26: 'Hungarian', | |
27: 'Estonian', | |
28: 'Latvian', | |
28: 'Lettish', | |
29: 'Saami', | |
29: 'Sami', | |
30: 'Faroese', | |
31: 'Farsi', | |
32: 'Russian', | |
33: 'Simplified Chinese', | |
34: 'Flemish', | |
35: 'Irish', | |
36: 'Albanian', | |
37: 'Romanian', | |
38: 'Czech', | |
39: 'Slovak', | |
40: 'Slovenian', | |
41: 'Yiddish', | |
42: 'Serbian', | |
43: 'Macedonian', | |
44: 'Bulgarian', | |
45: 'Ukrainian', | |
46: 'Belarusian', | |
47: 'Uzbek', | |
48: 'Kazakh', | |
49: 'Azerbaijani', | |
50: 'AzerbaijanAr', | |
51: 'Armenian', | |
52: 'Georgian', | |
53: 'Moldavian', | |
54: 'Kirghiz', | |
55: 'Tajiki', | |
56: 'Turkmen', | |
57: 'Mongolian', | |
58: 'MongolianCyr', | |
59: 'Pashto', | |
60: 'Kurdish', | |
61: 'Kashmiri', | |
62: 'Sindhi', | |
63: 'Tibetan', | |
64: 'Nepali', | |
65: 'Sanskrit', | |
66: 'Marathi', | |
67: 'Bengali', | |
68: 'Assamese', | |
69: 'Gujarati', | |
70: 'Punjabi', | |
71: 'Oriya', | |
72: 'Malayalam', | |
73: 'Kannada', | |
74: 'Tamil', | |
75: 'Telugu', | |
76: 'Sinhala', | |
77: 'Burmese', | |
78: 'Khmer', | |
79: 'Lao', | |
80: 'Vietnamese', | |
81: 'Indonesian', | |
82: 'Tagalog', | |
83: 'MalayRoman', | |
84: 'MalayArabic', | |
85: 'Amharic', | |
87: 'Galla', | |
87: 'Oromo', | |
88: 'Somali', | |
89: 'Swahili', | |
90: 'Kinyarwanda', | |
91: 'Rundi', | |
92: 'Nyanja', | |
93: 'Malagasy', | |
94: 'Esperanto', | |
128: 'Welsh', | |
129: 'Basque', | |
130: 'Catalan', | |
131: 'Latin', | |
132: 'Quechua', | |
133: 'Guarani', | |
134: 'Aymara', | |
135: 'Tatar', | |
136: 'Uighur', | |
137: 'Dzongkha', | |
138: 'JavaneseRom', | |
32767: 'Unspecified', | |
}; | |
var MACINTOSH_CODE_POINTS = { | |
128: 'Ä', | |
129: 'Å', | |
130: 'Ç', | |
131: 'É', | |
132: 'Ñ', | |
133: 'Ö', | |
134: 'Ü', | |
135: 'á', | |
136: 'à', | |
137: 'â', | |
138: 'ä', | |
139: 'ã', | |
140: 'å', | |
141: 'ç', | |
142: 'é', | |
143: 'è', | |
144: 'ê', | |
145: 'ë', | |
146: 'í', | |
147: 'ì', | |
148: 'î', | |
149: 'ï', | |
150: 'ñ', | |
151: 'ó', | |
152: 'ò', | |
153: 'ô', | |
154: 'ö', | |
155: 'õ', | |
156: 'ú', | |
157: 'ù', | |
158: 'û', | |
159: 'ü', | |
160: '†', | |
161: '°', | |
162: '¢', | |
163: '£', | |
164: '§', | |
165: '•', | |
166: '¶', | |
167: 'ß', | |
168: '®', | |
169: '©', | |
170: '™', | |
171: '´', | |
172: '¨', | |
173: '≠', | |
174: 'Æ', | |
175: 'Ø', | |
176: '∞', | |
177: '±', | |
178: '≤', | |
179: '≥', | |
180: '¥', | |
181: 'µ', | |
182: '∂', | |
183: '∑', | |
184: '∏', | |
185: 'π', | |
186: '∫', | |
187: 'ª', | |
188: 'º', | |
189: 'Ω', | |
190: 'æ', | |
191: 'ø', | |
192: '¿', | |
193: '¡', | |
194: '¬', | |
195: '√', | |
196: 'ƒ', | |
197: '≈', | |
198: '∆', | |
199: '«', | |
200: '»', | |
201: '…', | |
202: ' ', | |
203: 'À', | |
204: 'Ã', | |
205: 'Õ', | |
206: 'Œ', | |
207: 'œ', | |
208: '–', | |
209: '—', | |
210: '“', | |
211: '”', | |
212: '‘', | |
213: '’', | |
214: '÷', | |
215: '◊', | |
216: 'ÿ', | |
217: 'Ÿ', | |
218: '⁄', | |
219: '€', | |
220: '‹', | |
221: '›', | |
222: 'fi', | |
223: 'fl', | |
224: '‡', | |
225: '·', | |
226: '‚', | |
227: '„', | |
228: '‰', | |
229: 'Â', | |
230: 'Ê', | |
231: 'Á', | |
232: 'Ë', | |
233: 'È', | |
234: 'Í', | |
235: 'Î', | |
236: 'Ï', | |
237: 'Ì', | |
238: 'Ó', | |
239: 'Ô', | |
240: '', | |
241: 'Ò', | |
242: 'Ú', | |
243: 'Û', | |
244: 'Ù', | |
245: 'ı', | |
246: 'ˆ', | |
247: '˜', | |
248: '¯', | |
249: '˘', | |
250: '˙', | |
251: '˚', | |
252: '¸', | |
253: '˝', | |
254: '˛', | |
255: 'ˇ', | |
}; | |
var ISO_LANGUAGE_CODES = { | |
'aar': "Afar", | |
'abk': "Abkhazian", | |
'ace': "Achinese", | |
'ach': "Acoli", | |
'ada': "Adangme", | |
'ady': "Adyghe; Adygei", | |
'afa': "Afro-Asiatic languages", | |
'afh': "Afrihili", | |
'afr': "Afrikaans", | |
'ain': "Ainu", | |
'aka': "Akan", | |
'akk': "Akkadian", | |
'ale': "Aleut", | |
'alg': "Algonquian languages", | |
'alt': "Southern Altai", | |
'amh': "Amharic", | |
'ang': "English, Old (ca.450-1100)", | |
'anp': "Angika", | |
'apa': "Apache languages", | |
'ara': "Arabic", | |
'arc': "Official Aramaic (700-300 BCE); Imperial Aramaic (700-300 BCE)", | |
'arg': "Aragonese", | |
'arn': "Mapudungun; Mapuche", | |
'arp': "Arapaho", | |
'art': "Artificial languages", | |
'arw': "Arawak", | |
'asm': "Assamese", | |
'ast': "Asturian; Bable; Leonese; Asturleonese", | |
'ath': "Athapascan languages", | |
'aus': "Australian languages", | |
'ava': "Avaric", | |
'ave': "Avestan", | |
'awa': "Awadhi", | |
'aym': "Aymara", | |
'aze': "Azerbaijani", | |
'bad': "Banda languages", | |
'bai': "Bamileke languages", | |
'bak': "Bashkir", | |
'bal': "Baluchi", | |
'bam': "Bambara", | |
'ban': "Balinese", | |
'bas': "Basa", | |
'bat': "Baltic languages", | |
'bej': "Beja; Bedawiyet", | |
'bel': "Belarusian", | |
'bem': "Bemba", | |
'ben': "Bengali", | |
'ber': "Berber languages", | |
'bho': "Bhojpuri", | |
'bih': "Bihari languages", | |
'bik': "Bikol", | |
'bin': "Bini; Edo", | |
'bis': "Bislama", | |
'bla': "Siksika", | |
'bnt': "Bantu languages", | |
'bod': "Tibetan", | |
'bod': "Tibetan", | |
'bos': "Bosnian", | |
'bra': "Braj", | |
'bre': "Breton", | |
'btk': "Batak languages", | |
'bua': "Buriat", | |
'bug': "Buginese", | |
'bul': "Bulgarian", | |
'byn': "Blin; Bilin", | |
'cad': "Caddo", | |
'cai': "Central American Indian languages", | |
'car': "Galibi Carib", | |
'cat': "Catalan; Valencian", | |
'cau': "Caucasian languages", | |
'ceb': "Cebuano", | |
'cel': "Celtic languages", | |
'ces': "Czech", | |
'ces': "Czech", | |
'cha': "Chamorro", | |
'chb': "Chibcha", | |
'che': "Chechen", | |
'chg': "Chagatai", | |
'chk': "Chuukese", | |
'chm': "Mari", | |
'chn': "Chinook jargon", | |
'cho': "Choctaw", | |
'chp': "Chipewyan; Dene Suline", | |
'chr': "Cherokee", | |
'chu': "Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic", | |
'chv': "Chuvash", | |
'chy': "Cheyenne", | |
'cmc': "Chamic languages", | |
'cop': "Coptic", | |
'cor': "Cornish", | |
'cos': "Corsican", | |
'cpe': "Creoles and pidgins, English based", | |
'cpf': "Creoles and pidgins, French-based", | |
'cpp': "Creoles and pidgins, Portuguese-based", | |
'cre': "Cree", | |
'crh': "Crimean Tatar; Crimean Turkish", | |
'crp': "Creoles and pidgins", | |
'csb': "Kashubian", | |
'cus': "Cushitic languages", | |
'cym': "Welsh", | |
'cym': "Welsh", | |
'dak': "Dakota", | |
'dan': "Danish", | |
'dar': "Dargwa", | |
'day': "Land Dayak languages", | |
'del': "Delaware", | |
'den': "Slave (Athapascan)", | |
'deu': "German", | |
'deu': "German", | |
'dgr': "Dogrib", | |
'din': "Dinka", | |
'div': "Divehi; Dhivehi; Maldivian", | |
'doi': "Dogri", | |
'dra': "Dravidian languages", | |
'dsb': "Lower Sorbian", | |
'dua': "Duala", | |
'dum': "Dutch, Middle (ca.1050-1350)", | |
'dyu': "Dyula", | |
'dzo': "Dzongkha", | |
'efi': "Efik", | |
'egy': "Egyptian (Ancient)", | |
'eka': "Ekajuk", | |
'ell': "Greek, Modern (1453-)", | |
'ell': "Greek, Modern (1453-)", | |
'elx': "Elamite", | |
'eng': "English", | |
'enm': "English, Middle (1100-1500)", | |
'epo': "Esperanto", | |
'est': "Estonian", | |
'eus': "Basque", | |
'eus': "Basque", | |
'ewe': "Ewe", | |
'ewo': "Ewondo", | |
'fan': "Fang", | |
'fao': "Faroese", | |
'fas': "Persian", | |
'fas': "Persian", | |
'fat': "Fanti", | |
'fij': "Fijian", | |
'fil': "Filipino; Pilipino", | |
'fin': "Finnish", | |
'fiu': "Finno-Ugrian languages", | |
'fon': "Fon", | |
'fra': "French", | |
'fra': "French", | |
'frm': "French, Middle (ca.1400-1600)", | |
'fro': "French, Old (842-ca.1400)", | |
'frr': "Northern Frisian", | |
'frs': "Eastern Frisian", | |
'fry': "Western Frisian", | |
'ful': "Fulah", | |
'fur': "Friulian", | |
'gaa': "Ga", | |
'gay': "Gayo", | |
'gba': "Gbaya", | |
'gem': "Germanic languages", | |
'gez': "Geez", | |
'gil': "Gilbertese", | |
'gla': "Gaelic; Scottish Gaelic", | |
'gle': "Irish", | |
'glg': "Galician", | |
'glv': "Manx", | |
'gmh': "German, Middle High (ca.1050-1500)", | |
'goh': "German, Old High (ca.750-1050)", | |
'gon': "Gondi", | |
'gor': "Gorontalo", | |
'got': "Gothic", | |
'grb': "Grebo", | |
'grc': "Greek, Ancient (to 1453)", | |
'grn': "Guarani", | |
'gsw': "Swiss German; Alemannic; Alsatian", | |
'guj': "Gujarati", | |
'gwi': "Gwich'in", | |
'hai': "Haida", | |
'hat': "Haitian; Haitian Creole", | |
'hau': "Hausa", | |
'haw': "Hawaiian", | |
'heb': "Hebrew", | |
'her': "Herero", | |
'hil': "Hiligaynon", | |
'him': "Himachali languages; Western Pahari languages", | |
'hin': "Hindi", | |
'hit': "Hittite", | |
'hmn': "Hmong; Mong", | |
'hmo': "Hiri Motu", | |
'hrv': "Croatian", | |
'hsb': "Upper Sorbian", | |
'hun': "Hungarian", | |
'hup': "Hupa", | |
'hye': "Armenian", | |
'hye': "Armenian", | |
'iba': "Iban", | |
'ibo': "Igbo", | |
'ido': "Ido", | |
'iii': "Sichuan Yi; Nuosu", | |
'ijo': "Ijo languages", | |
'iku': "Inuktitut", | |
'ile': "Interlingue; Occidental", | |
'ilo': "Iloko", | |
'ina': "Interlingua (International Auxiliary Language Association)", | |
'inc': "Indic languages", | |
'ind': "Indonesian", | |
'ine': "Indo-European languages", | |
'inh': "Ingush", | |
'ipk': "Inupiaq", | |
'ira': "Iranian languages", | |
'iro': "Iroquoian languages", | |
'isl': "Icelandic", | |
'isl': "Icelandic", | |
'ita': "Italian", | |
'jav': "Javanese", | |
'jbo': "Lojban", | |
'jpn': "Japanese", | |
'jpr': "Judeo-Persian", | |
'jrb': "Judeo-Arabic", | |
'kaa': "Kara-Kalpak", | |
'kab': "Kabyle", | |
'kac': "Kachin; Jingpho", | |
'kal': "Kalaallisut; Greenlandic", | |
'kam': "Kamba", | |
'kan': "Kannada", | |
'kar': "Karen languages", | |
'kas': "Kashmiri", | |
'kat': "Georgian", | |
'kat': "Georgian", | |
'kau': "Kanuri", | |
'kaw': "Kawi", | |
'kaz': "Kazakh", | |
'kbd': "Kabardian", | |
'kha': "Khasi", | |
'khi': "Khoisan languages", | |
'khm': "Central Khmer", | |
'kho': "Khotanese; Sakan", | |
'kik': "Kikuyu; Gikuyu", | |
'kin': "Kinyarwanda", | |
'kir': "Kirghiz; Kyrgyz", | |
'kmb': "Kimbundu", | |
'kok': "Konkani", | |
'kom': "Komi", | |
'kon': "Kongo", | |
'kor': "Korean", | |
'kos': "Kosraean", | |
'kpe': "Kpelle", | |
'krc': "Karachay-Balkar", | |
'krl': "Karelian", | |
'kro': "Kru languages", | |
'kru': "Kurukh", | |
'kua': "Kuanyama; Kwanyama", | |
'kum': "Kumyk", | |
'kur': "Kurdish", | |
'kut': "Kutenai", | |
'lad': "Ladino", | |
'lah': "Lahnda", | |
'lam': "Lamba", | |
'lao': "Lao", | |
'lat': "Latin", | |
'lav': "Latvian", | |
'lez': "Lezghian", | |
'lim': "Limburgan; Limburger; Limburgish", | |
'lin': "Lingala", | |
'lit': "Lithuanian", | |
'lol': "Mongo", | |
'loz': "Lozi", | |
'ltz': "Luxembourgish; Letzeburgesch", | |
'lua': "Luba-Lulua", | |
'lub': "Luba-Katanga", | |
'lug': "Ganda", | |
'lui': "Luiseno", | |
'lun': "Lunda", | |
'luo': "Luo (Kenya and Tanzania)", | |
'lus': "Lushai", | |
'mad': "Madurese", | |
'mag': "Magahi", | |
'mah': "Marshallese", | |
'mai': "Maithili", | |
'mak': "Makasar", | |
'mal': "Malayalam", | |
'man': "Mandingo", | |
'map': "Austronesian languages", | |
'mar': "Marathi", | |
'mas': "Masai", | |
'mdf': "Moksha", | |
'mdr': "Mandar", | |
'men': "Mende", | |
'mga': "Irish, Middle (900-1200)", | |
'mic': "Mi'kmaq; Micmac", | |
'min': "Minangkabau", | |
'mis': "Uncoded languages", | |
'mkd': "Macedonian", | |
'mkd': "Macedonian", | |
'mkh': "Mon-Khmer languages", | |
'mlg': "Malagasy", | |
'mlt': "Maltese", | |
'mnc': "Manchu", | |
'mni': "Manipuri", | |
'mno': "Manobo languages", | |
'moh': "Mohawk", | |
'mon': "Mongolian", | |
'mos': "Mossi", | |
'mri': "Maori", | |
'mri': "Maori", | |
'msa': "Malay", | |
'msa': "Malay", | |
'mul': "Multiple languages", | |
'mun': "Munda languages", | |
'mus': "Creek", | |
'mwl': "Mirandese", | |
'mwr': "Marwari", | |
'mya': "Burmese", | |
'mya': "Burmese", | |
'myn': "Mayan languages", | |
'myv': "Erzya", | |
'nah': "Nahuatl languages", | |
'nai': "North American Indian languages", | |
'nap': "Neapolitan", | |
'nau': "Nauru", | |
'nav': "Navajo; Navaho", | |
'nbl': "Ndebele, South; South Ndebele", | |
'nde': "Ndebele, North; North Ndebele", | |
'ndo': "Ndonga", | |
'nds': "Low German; Low Saxon; German, Low; Saxon, Low", | |
'nep': "Nepali", | |
'new': "Nepal Bhasa; Newari", | |
'nia': "Nias", | |
'nic': "Niger-Kordofanian languages", | |
'niu': "Niuean", | |
'nld': "Dutch; Flemish", | |
'nld': "Dutch; Flemish", | |
'nno': "Norwegian Nynorsk; Nynorsk, Norwegian", | |
'nob': "Bokmål, Norwegian; Norwegian Bokmål", | |
'nog': "Nogai", | |
'non': "Norse, Old", | |
'nor': "Norwegian", | |
'nqo': "N'Ko", | |
'nso': "Pedi; Sepedi; Northern Sotho", | |
'nub': "Nubian languages", | |
'nwc': "Classical Newari; Old Newari; Classical Nepal Bhasa", | |
'nya': "Chichewa; Chewa; Nyanja", | |
'nym': "Nyamwezi", | |
'nyn': "Nyankole", | |
'nyo': "Nyoro", | |
'nzi': "Nzima", | |
'oci': "Occitan (post 1500)", | |
'oji': "Ojibwa", | |
'ori': "Oriya", | |
'orm': "Oromo", | |
'osa': "Osage", | |
'oss': "Ossetian; Ossetic", | |
'ota': "Turkish, Ottoman (1500-1928)", | |
'oto': "Otomian languages", | |
'paa': "Papuan languages", | |
'pag': "Pangasinan", | |
'pal': "Pahlavi", | |
'pam': "Pampanga; Kapampangan", | |
'pan': "Panjabi; Punjabi", | |
'pap': "Papiamento", | |
'pau': "Palauan", | |
'peo': "Persian, Old (ca.600-400 B.C.)", | |
'phi': "Philippine languages", | |
'phn': "Phoenician", | |
'pli': "Pali", | |
'pol': "Polish", | |
'pon': "Pohnpeian", | |
'por': "Portuguese", | |
'pra': "Prakrit languages", | |
'pro': "Provençal, Old (to 1500);Occitan, Old (to 1500)", | |
'pus': "Pushto; Pashto", | |
'que': "Quechua", | |
'raj': "Rajasthani", | |
'rap': "Rapanui", | |
'rar': "Rarotongan; Cook Islands Maori", | |
'roa': "Romance languages", | |
'roh': "Romansh", | |
'rom': "Romany", | |
'ron': "Romanian; Moldavian; Moldovan", | |
'ron': "Romanian; Moldavian; Moldovan", | |
'run': "Rundi", | |
'rup': "Aromanian; Arumanian; Macedo-Romanian", | |
'rus': "Russian", | |
'sad': "Sandawe", | |
'sag': "Sango", | |
'sah': "Yakut", | |
'sai': "South American Indian languages", | |
'sal': "Salishan languages", | |
'sam': "Samaritan Aramaic", | |
'san': "Sanskrit", | |
'sas': "Sasak", | |
'sat': "Santali", | |
'scn': "Sicilian", | |
'sco': "Scots", | |
'sel': "Selkup", | |
'sem': "Semitic languages", | |
'sga': "Irish, Old (to 900)", | |
'sgn': "Sign Languages", | |
'shn': "Shan", | |
'sid': "Sidamo", | |
'sin': "Sinhala; Sinhalese", | |
'sio': "Siouan languages", | |
'sit': "Sino-Tibetan languages", | |
'sla': "Slavic languages", | |
'slk': "Slovak", | |
'slk': "Slovak", | |
'slv': "Slovenian", | |
'sma': "Southern Sami", | |
'sme': "Northern Sami", | |
'smi': "Sami languages", | |
'smj': "Lule Sami", | |
'smn': "Inari Sami", | |
'smo': "Samoan", | |
'sms': "Skolt Sami", | |
'sna': "Shona", | |
'snd': "Sindhi", | |
'snk': "Soninke", | |
'sog': "Sogdian", | |
'som': "Somali", | |
'son': "Songhai languages", | |
'sot': "Sotho, Southern", | |
'spa': "Spanish; Castilian", | |
'sqi': "Albanian", | |
'sqi': "Albanian", | |
'srd': "Sardinian", | |
'srn': "Sranan Tongo", | |
'srp': "Serbian", | |
'srr': "Serer", | |
'ssa': "Nilo-Saharan languages", | |
'ssw': "Swati", | |
'suk': "Sukuma", | |
'sun': "Sundanese", | |
'sus': "Susu", | |
'sux': "Sumerian", | |
'swa': "Swahili", | |
'swe': "Swedish", | |
'syc': "Classical Syriac", | |
'syr': "Syriac", | |
'tah': "Tahitian", | |
'tai': "Tai languages", | |
'tam': "Tamil", | |
'tat': "Tatar", | |
'tel': "Telugu", | |
'tem': "Timne", | |
'ter': "Tereno", | |
'tet': "Tetum", | |
'tgk': "Tajik", | |
'tgl': "Tagalog", | |
'tha': "Thai", | |
'tig': "Tigre", | |
'tir': "Tigrinya", | |
'tiv': "Tiv", | |
'tkl': "Tokelau", | |
'tlh': "Klingon; tlhIngan-Hol", | |
'tli': "Tlingit", | |
'tmh': "Tamashek", | |
'tog': "Tonga (Nyasa)", | |
'ton': "Tonga (Tonga Islands)", | |
'tpi': "Tok Pisin", | |
'tsi': "Tsimshian", | |
'tsn': "Tswana", | |
'tso': "Tsonga", | |
'tuk': "Turkmen", | |
'tum': "Tumbuka", | |
'tup': "Tupi languages", | |
'tur': "Turkish", | |
'tut': "Altaic languages", | |
'tvl': "Tuvalu", | |
'twi': "Twi", | |
'tyv': "Tuvinian", | |
'udm': "Udmurt", | |
'uga': "Ugaritic", | |
'uig': "Uighur; Uyghur", | |
'ukr': "Ukrainian", | |
'umb': "Umbundu", | |
'und': "Undetermined", | |
'urd': "Urdu", | |
'uzb': "Uzbek", | |
'vai': "Vai", | |
'ven': "Venda", | |
'vie': "Vietnamese", | |
'vol': "Volapük", | |
'vot': "Votic", | |
'wak': "Wakashan languages", | |
'wal': "Wolaitta; Wolaytta", | |
'war': "Waray", | |
'was': "Washo", | |
'wen': "Sorbian languages", | |
'wln': "Walloon", | |
'wol': "Wolof", | |
'xal': "Kalmyk; Oirat", | |
'xho': "Xhosa", | |
'yao': "Yao", | |
'yap': "Yapese", | |
'yid': "Yiddish", | |
'yor': "Yoruba", | |
'ypk': "Yupik languages", | |
'zap': "Zapotec", | |
'zbl': "Blissymbols; Blissymbolics; Bliss", | |
'zen': "Zenaga", | |
'zgh': "Standard Moroccan Tamazight", | |
'zha': "Zhuang; Chuang", | |
'zho': "Chinese", | |
'zho': "Chinese", | |
'znd': "Zande languages", | |
'zul': "Zulu", | |
'zun': "Zuni", | |
'zxx': "No linguistic content; Not applicable", | |
'zza': "Zaza; Dimili; Dimli; Kirdki; Kirmanjki; Zazaki", | |
}; | |
var PACKED_TO_ISO_CODE = {} | |
for (var code in ISO_LANGUAGE_CODES) { | |
PACKED_TO_ISO_CODE[( | |
((code.charCodeAt(0) - 0x60) * 0x400) + | |
((code.charCodeAt(1) - 0x60) * 0x20) + | |
((code.charCodeAt(2) - 0x60)) | |
)] = code; | |
} | |
// Utility | |
var sliceDataView = function (view, offset, length) { | |
length = length || (view.byteLength - offset); | |
if ((offset + length) > view.byteLength) { | |
throw 'Length is out of view bounds.'; | |
} else if (length === 0) { | |
return undefined; | |
} else { | |
return new DataView(view.buffer, view.byteOffset + offset, length); | |
} | |
} | |
var bytesToString = function (view, offset, length) { | |
var string = '', | |
i; | |
offset = offset || 0; | |
length = length || (view.byteLength - offset); | |
for (i=0; i < length; i++) { | |
string += String.fromCharCode(view.getUint8(offset + i)); | |
} | |
return string; | |
} | |
// Parsers | |
var parseMatrix = function (view) { | |
return [ | |
[view.getInt32(0) / Math.pow(2, 16), view.getInt32(4) / Math.pow(2, 16), view.getInt32(8) / Math.pow(2, 30)], | |
[view.getInt32(12) / Math.pow(2, 16), view.getInt32(16) / Math.pow(2, 16), view.getInt32(20) / Math.pow(2, 30)], | |
[view.getInt32(24) / Math.pow(2, 16), view.getInt32(28) / Math.pow(2, 16), view.getInt32(32) / Math.pow(2, 30)], | |
] | |
} | |
var parseColors = function (view) { | |
var i, | |
colors = []; | |
for (i = 0; i < view.byteLength; i += 8) { | |
colors.push([ | |
view.getUint16(i), | |
view.getUint16(i + 2), | |
view.getUint16(i + 4), | |
view.getUint16(i + 6), | |
]); | |
} | |
return colors; | |
} | |
var parseRaw = function (atom) { | |
atom.raw_data = new DataView(atom.stream.buffer, atom.stream.byteOffset, atom.stream.byteLength); | |
return atom; | |
} | |
var parseChildren = function (atom) { | |
var last_child; | |
atom.children = parseQuickTime(atom.stream, undefined, undefined, undefined, atom.level + 1).parsed_atoms; | |
last_child = atom.children.length? atom.children[atom.children.length - 1] : undefined; | |
if (last_child) { | |
atom.stream = sliceDataView(atom.stream, last_child.offset + last_child.length); | |
} else { | |
atom.children = undefined; | |
} | |
return atom; | |
} | |
var parseAtomContainer = function (atom) { | |
atom.reserved = sliceDataView(atom.stream, 8, 18); | |
atom.lock_count = atom.stream.getUint16(18); | |
atom.stream = sliceDataView(atom.stream, 20); | |
return atom; | |
} | |
var parseFTYP = function (atom) { | |
var i; | |
atom.major_brand = bytesToString(atom.stream, 0, 4); | |
atom.minor_version = atom.stream.getUint32(4); | |
atom.compatible_brands = []; | |
for (i=8; i<atom.stream.byteLength; i+=4) { | |
atom.compatible_brands.push(bytesToString(atom.stream, i, 4)); | |
} | |
if (i == atom.stream.byteLength) { | |
atom.stream = undefined; | |
} else { | |
atom.stream = sliceDataView(atom.stream, i); | |
} | |
return atom; | |
} | |
var parseMVHD = function (atom) { | |
atom.version = atom.stream.getInt8(0); | |
atom.flags = sliceDataView(atom.stream, 1, 3); | |
atom.creation_time = new Date(QT_EPOCH); atom.creation_time.setSeconds(atom.stream.getUint32(4)); | |
atom.modification_time = new Date(QT_EPOCH); atom.modification_time.setSeconds(atom.stream.getUint32(8)); | |
atom.time_scale = atom.stream.getUint32(12); | |
atom.duration = atom.stream.getUint32(16); | |
atom.preferred_rate = atom.stream.getUint32(20) / Math.pow(2, 16); | |
atom.preferred_volume = atom.stream.getUint16(24) / Math.pow(2, 8); | |
atom.reserved = sliceDataView(atom.stream, 26, 10); | |
atom.matrix_structure = parseMatrix(sliceDataView(atom.stream, 36, 36)); | |
atom.preview_time = atom.stream.getUint32(72); | |
atom.preview_duration = atom.stream.getUint32(76); | |
atom.poster_time = atom.stream.getUint32(80); | |
atom.selection_time = atom.stream.getUint32(84); | |
atom.selection_duration = atom.stream.getUint32(88); | |
atom.current_time = atom.stream.getUint32(92); | |
atom.next_track_id = atom.stream.getUint32(96); | |
atom.stream = sliceDataView(atom.stream, 100); | |
return atom; | |
} | |
var parseCTAB = function (atom) { | |
atom.color_table_seed = atom.stream.getUint32(0); | |
atom.color_table_flags = atom.stream.getUint16(4); | |
atom.color_table_size = atom.stream.getUint16(6); | |
atom.color_array = parseColors(sliceDataView(atom.stream, 8, (atom.color_table_size + 1) * 8)); | |
atom.stream = sliceDataView(8 + (atom.color_array.length * 8)); | |
return atom; | |
} | |
var parseUserTag = function (atom) { | |
var value, | |
sub_atom, | |
attr, | |
i, | |
j; | |
if (USER_TAG_DESCRIPTIONS[atom.type] !== undefined) { | |
atom.description = USER_TAG_DESCRIPTIONS[atom.type]; | |
if (atom.type[0] !== '©') { | |
atom.value = bytesToString(atom.stream); | |
atom.stream = sliceDataView(atom.stream, atom.value.length); | |
} | |
else { | |
atom.children = []; | |
i = 0; | |
while (i < atom.stream.byteLength) { | |
sub_atom = { | |
'language_code': atom.stream.getUint16(i + 2), | |
'language': undefined, | |
'offset': i, | |
'length': atom.stream.getUint16(i), | |
'raw_data': sliceDataView(atom.stream, i + 4, atom.stream.getUint16(i) - 4), | |
'value': undefined, | |
} | |
if (sub_atom_language_code in MACINTOSH_LANGUAGE_CODES) { | |
sub_atom.language = MACINTOSH_LANGUAGE_CODES[sub_atom_language_code]; | |
sub_atom.value = '' | |
for (j=0; j < sub_atom_data.byteLength; j++) { | |
sub_atom.value += MACINTOSH_CODE_POINTS[sub_atom_data.getUint32(j)] || String.fromCharCode(j); | |
} | |
} | |
else if (sub_atom_language_code in PACKED_TO_ISO_CODE) { | |
sub_atom.unpacked_language_code = PACKED_TO_ISO_CODE[sub_atom.language_code]; | |
sub_atom.language = ISO_LANGUAGE_CODES[sub_atom.unpacked_language_code]; | |
if (sub_atom_data.getUint32(0) == 0xfeff) { | |
value = String.fromCharCode.apply(null, new Uint16Array(sub_atom_data.buffer, sub_atom_data.byteOffset, sub_atom_data.byteLength)); | |
} else { | |
value = String.fromCharCode.apply(null, new Uint8Array(sub_atom_data.buffer, sub_atom_data.byteOffset, sub_atom_data.byteLength)); | |
} | |
} | |
for (attr in sub_atom) { | |
if (sub_atom[attr] === undefined) { | |
delete sub_atom[attr]; | |
} | |
} | |
atom.children.push(sub_atom); | |
i += sub_atom_length; | |
} | |
atom.stream = sliceDataView(atom.stream, i); | |
} | |
} | |
return atom; | |
} | |
var parseTAGC = function (atom) { | |
atom.value = bytesToString(atom.stream); | |
atom.stream = sliceDataView(atom.stream, atom.value.length); | |
return atom; | |
} | |
var parseTNAM = function (atom) { | |
atom.reserved = atom.stream.getUint32(0); | |
atom.language_code = atom.stream.getUint16(4); | |
atom.unpacked_language_code = PACKED_TO_ISO_CODE[atom.language_code]; | |
if (sub_atom_data.getUint32(0) == 0xfeff) { | |
atom.name = String.fromCharCode.apply(null, new Uint16Array(atom.stream.buffer, atom.stream.byteOffset + 6, atom.stream.byteLength - 6)); | |
} else { | |
atom.name = String.fromCharCode.apply(null, new Uint8Array(atom.stream.buffer, atom.stream.byteOffset + 6, atom.stream.byteLength - 6)); | |
} | |
atom.stream = undefined; | |
return atom; | |
} | |
var parsePTV = function (atom) { | |
atom.display_size = ['normal', 'double', 'half', 'fill', 'current'][atom.stream.getUint16(0, true)]; | |
atom.reserved_1 = atom.stream.getUint16(2); | |
atom.reserved_2 = atom.stream.getUint16(4); | |
atom.slide_show = atom.stream.getUint8(6) === 1; | |
atom.play_on_open = atom.stream.getUint8(8) === 1; | |
atom.stream = sliceDataView(atom.stream, 10); | |
return atom; | |
} | |
var parsePRFL = function (atom) { | |
var i, | |
feature_entry; | |
atom.version = atom.stream.getUint32(0); | |
atom.flags = sliceDataView(atom.stream, 1, 3); | |
atom.number_of_feature_entries = atom.stream.getUint32(4); | |
if (atom.number_of_feature_entries) { | |
atom.feature_entries = []; | |
for (i = 0; i < atom.number_of_feature_entries; i += 16) { | |
feature_entry = { | |
'offset': i, | |
'length': 16, | |
'reserved': atom.stream.getUint32(4 + i), | |
'part_id': bytesToString(sliceDataView(atom.stream, 4 + i + 4, 4)), | |
'feature_code': bytesToString(sliceDataView(atom.stream, 4 + i + 8, 4)), | |
'feature_value': atom.stream.getUint32(4 + i + 12), | |
'raw_data': sliceDataView(atom.stream, i, 16), | |
} | |
atom.feature_entries.push(feature_entry); | |
} | |
} | |
atom.stream = sliceDataView(atom.stream, 4 + (atom.number_of_feature_entries * 16)); | |
return atom; | |
} | |
var parseTKHD = function (atom) { | |
var flags; | |
atom.version = atom.stream.getUint8(0); | |
atom.flags = { | |
'enabled': false, | |
'in_movie': false, | |
'in_preview': false, | |
'in_poster': false, | |
'raw_data': sliceDataView(atom.stream, 1, 3), | |
} | |
flags = atom.stream.getUint16(2); | |
if (flags >= 0x0008) { atom.flags.in_poster = true; flags -= 0x0008; } | |
if (flags >= 0x0004) { atom.flags.in_preview = true; flags -= 0x0004; } | |
if (flags >= 0x0002) { atom.flags.in_movie = true; flags -= 0x0002; } | |
if (flags >= 0x0001) { atom.flags.enabled = true; flags -= 0x0001; } | |
atom.creation_time = new Date(QT_EPOCH); atom.creation_time.setSeconds(atom.stream.getUint32(4)); | |
atom.modification_time = new Date(QT_EPOCH); atom.modification_time.setSeconds(atom.stream.getUint32(8)); | |
atom.track_id = atom.stream.getUint32(12); | |
atom.reserved = atom.stream.getUint32(16); | |
atom.duration = atom.stream.getUint32(20); | |
atom.reserved_1 = sliceDataView(atom.stream, 24, 8); | |
atom.layer = atom.stream.getUint16(32); | |
atom.alternate_group = atom.stream.getUint16(34); | |
atom.volume = atom.stream.getUint16(36) / Math.pow(2, 8); | |
atom.reserved_2 = atom.stream.getUint16(38); | |
atom.matrix_structure = parseMatrix(sliceDataView(atom.stream, 40, 36)); | |
atom.track_width = atom.stream.getUint32(76) / Math.pow(2, 16); | |
atom.track_height = atom.stream.getUint32(80) / Math.pow(2, 16); | |
atom.stream = sliceDataView(atom.stream, 84); | |
return atom; | |
} | |
var parseTAPTTypes = function (atom) { | |
atom.version = atom.stream.getUint8(0); | |
atom.flags = sliceDataView(atom.stream, 1, 3); | |
atom.width = atom.stream.getUint32(4) / Math.pow(2, 16); | |
atom.height = atom.stream.getUint32(8) / Math.pow(2, 16); | |
atom.stream = sliceDataView(atom.stream, 8); | |
return atom; | |
} | |
var parseCRGN = function (atom) { | |
region_size = atom.stream.getUint16(0); | |
region_boundary_box = sliceDataView(atom.stream, 2, 8); | |
clipping_region_data = sliceDataView(atom.stream, 10); | |
atom.stream = undefined; | |
return atom; | |
} | |
var parseKMAT = function (atom) { | |
atom.version = atom.stream.getUint8(0); | |
atom.flags = sliceDataView(atom.stream, 1, 3); | |
// There are two more fields: | |
// - Matte image description structure | |
// - Matte data | |
// Both are of variable length, and neither are elaborated upon | |
// in the spec. So... | |
atom.stream = sliceDataView(atom.stream, 4); | |
return atom; | |
} | |
var parseELST = function (atom) { | |
var i; | |
atom.version = atom.stream.getUint8(0); | |
atom.flags = sliceDataView(atom.stream, 1, 3); | |
atom.number_of_entries = atom.stream.getUint32(4); | |
atom.edit_list_table = []; | |
for (i = 0; i < (atom.number_of_entries * 12); i += 12) { | |
atom.edit_list_table.push({ | |
'offset': i, | |
'length': 12, | |
'track_duration': atom.stream.getUint32(8 + i), | |
'media_time': atom.stream.getInt32(8 + i + 4), | |
'media_rate': atom.stream.getUint32(8 + i + 8) / Math.pow(2, 16), | |
'raw_data': sliceDataView(atom.stream, i, 12), | |
}); | |
} | |
atom.stream = sliceDataView(atom.stream, 8 + (atom.number_of_entries * 12)); | |
return atom; | |
} | |
var parseLOAD = function (atom) { | |
var flags; | |
atom.preload_start_time = atom.stream.getUint32(0); | |
atom.preload_duration = atom.stream.getInt32(4); | |
atom.preload_flags = ['never', 'regardless', 'if_enabled'][atom.stream.getUint32(8)]; | |
atom.default_hints = { | |
'double_buffer': false, | |
'high_quality': false, | |
}; | |
flags = atom.stream.getUint32(12); | |
if (flags >= 0x0100) { atom.default_hints.high_quality = true; flags -= 0x0100; } | |
if (flags >= 0x0020) { atom.default_hints.double_buffer = true; flags -= 0x0020; } | |
return atom; | |
} | |
var ignore = function (atom) { | |
atom.stream = undefined; | |
return atom; | |
} | |
// Parser Flows | |
var atom_processors_for_type = { | |
undefined: [parseRaw], | |
'ftyp': [parseRaw, parseFTYP], | |
'mvhd': [parseRaw, parseMVHD], | |
'ctab': [parseRaw, parseCTAB], | |
'moov': [parseRaw, parseChildren], | |
'udta': [parseRaw, parseChildren], | |
'tagc': [parseRaw, parseTAGC], | |
'tnam': [parseRaw, parseTNAM], | |
'ptv ': [parseRaw, parsePTV], | |
'trak': [parseRaw, parseChildren], | |
'tkhd': [parseRaw, parseTKHD], | |
'txas': [parseRaw], | |
'tapt': [parseRaw, parseChildren], | |
'clef': [parseRaw, parseTAPTTypes], | |
'prof': [parseRaw, parseTAPTTypes], | |
'enof': [parseRaw, parseTAPTTypes], | |
'clip': [parseRaw, parseChildren], | |
'crgn': [parseRaw, parseCRGN], | |
'matt': [parseRaw, parseChildren], | |
'edts': [parseRaw, parseChildren], | |
'elst': [parseRaw, parseELST], | |
'load': [parseRaw, parseLOAD], | |
// To Finish. | |
'prfl': [parseRaw, parsePRFL], | |
'kmat': [parseRaw, parseKMAT], | |
// To Do. | |
'mdia': [parseRaw, parseChildren], | |
'minf': [parseRaw, parseChildren], | |
'dinf': [parseRaw, parseChildren], | |
'stbl': [parseRaw, parseChildren], | |
'edts': [parseRaw, parseChildren], | |
'tref': [parseRaw], | |
// Ignore | |
'mdat': [parseRaw, ignore], | |
}; | |
for (var type in USER_TAG_DESCRIPTIONS) { | |
if (atom_processors_for_type[type] === undefined) { | |
atom_processors_for_type[type] = [parseRaw, parseUserTag]; | |
} | |
} | |
// Main Loop | |
var parseQuickTime = function (view, offset, length, state, level) { | |
var state, | |
view, | |
i, | |
stream_offset, | |
possible_length, | |
atom_processors, | |
attr, | |
state; | |
offset = offset || 0; | |
length = length || view.byteLength; | |
level = level || 0; | |
state = state || { | |
'parsed_atoms': [], | |
'current_atom': { | |
'level': level, | |
'type': undefined, | |
'name': undefined, | |
'offset': undefined, | |
'length': undefined, | |
'length_type': undefined, | |
}, | |
'needed_bytes': 0, | |
}; | |
i = 0; | |
while (i < 50 && length >= state.needed_bytes) { | |
if (state.current_atom.length !== undefined && (state.current_atom.offset + state.current_atom.length) <= view.byteLength) { | |
state.current_atom.type = bytesToString(view, state.current_atom.offset + 4, 4); | |
state.current_atom.name = ATOM_NAMES[state.current_atom.type]; | |
stream_offset = state.current_atom.length_type === 'extended'? 16 : 8; | |
state.current_atom.stream = new DataView( | |
view.buffer, | |
view.byteOffset + state.current_atom.offset + stream_offset, | |
state.current_atom.length - stream_offset | |
); | |
atom_processors = [state.current_atom].concat(atom_processors_for_type[state.current_atom.type] || atom_processors_for_type[undefined]); | |
state.current_atom = atom_processors.reduce(function (atom, processor) { return processor(atom); }); | |
for (attr in state.current_atom) { | |
if (state.current_atom[attr] === undefined) { | |
delete state.current_atom[attr]; | |
} | |
} | |
state.parsed_atoms.push(state.current_atom); | |
state.current_atom = { | |
'level': level, | |
'type': undefined, | |
'offset': state.current_atom.offset + state.current_atom.length, | |
'length': undefined, | |
'length_type': undefined, | |
} | |
state.needed_bytes = state.current_atom.offset + 4; | |
} | |
else if (state.current_atom.offset !== undefined && (state.current_atom.offset + 4) <= view.byteLength) { | |
if (state.current_atom.length_type === 'extended') { | |
state.current_atom.length = view.getUint64(state.current_atom.offset + 8); | |
} | |
else { | |
possible_length = view.getUint32(state.current_atom.offset); | |
if (possible_length === 0) { | |
// Runs to end of file. | |
state.current_atom.length_type = 'end'; | |
state.current_atom.length = (length - state.current_atom.offset); | |
} | |
else if (possible_length === 1) { | |
// Extended size: True size is 8 bytes after the type. | |
state.current_atom.length_type = 'extended'; | |
state.needed_bytes = state.current_atom.offset + 8; | |
} | |
else { | |
// Standard size. | |
state.current_atom.length_type = 'standard'; | |
state.current_atom.length = view.getUint32(state.current_atom.offset); | |
} | |
} | |
if (state.current_atom.length) { | |
state.needed_bytes = state.current_atom.offset + state.current_atom.length; | |
} | |
} | |
else { | |
state.current_atom.offset = (state.current_atom.offset || offset); | |
// 4 bytes for the length. | |
state.needed_bytes = state.current_atom.offset + 4; | |
} | |
i++; | |
} | |
return state; | |
} | |
// Example | |
var SOURCE_URL = 'https://raw.githubusercontent.com/mediaelement/mediaelement-files/master/big_buck_bunny.mp4'; | |
var xhr = new XMLHttpRequest(); | |
xhr.open('GET', SOURCE_URL); | |
xhr.responseType = 'arraybuffer'; | |
xhr.addEventListener('load', function () { | |
var state = parseQuickTime(new DataView(xhr.response)); | |
print(state.parsed_atoms); | |
}) | |
var print = function (parsed_atoms) { | |
for (var atom in parsed_atoms) { | |
for (var attr in parsed_atoms[atom]) { | |
if (attr === 'stream') { | |
console.log( | |
"\t\t\t\t\t\t\t\t\t\t\t\t".slice(0, parsed_atoms[atom].level) + attr, | |
parsed_atoms[atom].stream.buffer.slice(parsed_atoms[atom].stream.byteOffset, parsed_atoms[atom].stream.byteLength).toSource(true) | |
); | |
} | |
else { | |
console.log( | |
"\t\t\t\t\t\t\t\t\t\t\t\t".slice(0, parsed_atoms[atom].level) + attr, | |
parsed_atoms[atom][attr], | |
); | |
} | |
} | |
console.log(''); | |
if (parsed_atoms[atom].children !== undefined) { | |
print(parsed_atoms[atom].children); | |
} | |
} | |
}; | |
xhr.send(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment