1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.android.exoplayer2.extractor.mp4;
17 
18 import androidx.annotation.Nullable;
19 import com.google.android.exoplayer2.util.ParsableByteArray;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.List;
23 
24 @SuppressWarnings("ConstantField")
25 /* package */ abstract class Atom {
26 
27   /**
28    * Size of an atom header, in bytes.
29    */
30   public static final int HEADER_SIZE = 8;
31 
32   /**
33    * Size of a full atom header, in bytes.
34    */
35   public static final int FULL_HEADER_SIZE = 12;
36 
37   /**
38    * Size of a long atom header, in bytes.
39    */
40   public static final int LONG_HEADER_SIZE = 16;
41 
42   /**
43    * Value for the size field in an atom that defines its size in the largesize field.
44    */
45   public static final int DEFINES_LARGE_SIZE = 1;
46 
47   /**
48    * Value for the size field in an atom that extends to the end of the file.
49    */
50   public static final int EXTENDS_TO_END_SIZE = 0;
51 
52   @SuppressWarnings("ConstantCaseForConstants")
53   public static final int TYPE_ftyp = 0x66747970;
54 
55   @SuppressWarnings("ConstantCaseForConstants")
56   public static final int TYPE_avc1 = 0x61766331;
57 
58   @SuppressWarnings("ConstantCaseForConstants")
59   public static final int TYPE_avc3 = 0x61766333;
60 
61   @SuppressWarnings("ConstantCaseForConstants")
62   public static final int TYPE_avcC = 0x61766343;
63 
64   @SuppressWarnings("ConstantCaseForConstants")
65   public static final int TYPE_hvc1 = 0x68766331;
66 
67   @SuppressWarnings("ConstantCaseForConstants")
68   public static final int TYPE_hev1 = 0x68657631;
69 
70   @SuppressWarnings("ConstantCaseForConstants")
71   public static final int TYPE_hvcC = 0x68766343;
72 
73   @SuppressWarnings("ConstantCaseForConstants")
74   public static final int TYPE_vp08 = 0x76703038;
75 
76   @SuppressWarnings("ConstantCaseForConstants")
77   public static final int TYPE_vp09 = 0x76703039;
78 
79   @SuppressWarnings("ConstantCaseForConstants")
80   public static final int TYPE_vpcC = 0x76706343;
81 
82   @SuppressWarnings("ConstantCaseForConstants")
83   public static final int TYPE_av01 = 0x61763031;
84 
85   @SuppressWarnings("ConstantCaseForConstants")
86   public static final int TYPE_av1C = 0x61763143;
87 
88   @SuppressWarnings("ConstantCaseForConstants")
89   public static final int TYPE_dvav = 0x64766176;
90 
91   @SuppressWarnings("ConstantCaseForConstants")
92   public static final int TYPE_dva1 = 0x64766131;
93 
94   @SuppressWarnings("ConstantCaseForConstants")
95   public static final int TYPE_dvhe = 0x64766865;
96 
97   @SuppressWarnings("ConstantCaseForConstants")
98   public static final int TYPE_dvh1 = 0x64766831;
99 
100   @SuppressWarnings("ConstantCaseForConstants")
101   public static final int TYPE_dvcC = 0x64766343;
102 
103   @SuppressWarnings("ConstantCaseForConstants")
104   public static final int TYPE_dvvC = 0x64767643;
105 
106   @SuppressWarnings("ConstantCaseForConstants")
107   public static final int TYPE_s263 = 0x73323633;
108 
109   @SuppressWarnings("ConstantCaseForConstants")
110   public static final int TYPE_d263 = 0x64323633;
111 
112   @SuppressWarnings("ConstantCaseForConstants")
113   public static final int TYPE_mdat = 0x6d646174;
114 
115   @SuppressWarnings("ConstantCaseForConstants")
116   public static final int TYPE_mp4a = 0x6d703461;
117 
118   @SuppressWarnings("ConstantCaseForConstants")
119   public static final int TYPE__mp3 = 0x2e6d7033;
120 
121   @SuppressWarnings("ConstantCaseForConstants")
122   public static final int TYPE_wave = 0x77617665;
123 
124   @SuppressWarnings("ConstantCaseForConstants")
125   public static final int TYPE_lpcm = 0x6c70636d;
126 
127   @SuppressWarnings("ConstantCaseForConstants")
128   public static final int TYPE_sowt = 0x736f7774;
129 
130   @SuppressWarnings("ConstantCaseForConstants")
131   public static final int TYPE_ac_3 = 0x61632d33;
132 
133   @SuppressWarnings("ConstantCaseForConstants")
134   public static final int TYPE_dac3 = 0x64616333;
135 
136   @SuppressWarnings("ConstantCaseForConstants")
137   public static final int TYPE_ec_3 = 0x65632d33;
138 
139   @SuppressWarnings("ConstantCaseForConstants")
140   public static final int TYPE_dec3 = 0x64656333;
141 
142   @SuppressWarnings("ConstantCaseForConstants")
143   public static final int TYPE_ac_4 = 0x61632d34;
144 
145   @SuppressWarnings("ConstantCaseForConstants")
146   public static final int TYPE_dac4 = 0x64616334;
147 
148   @SuppressWarnings("ConstantCaseForConstants")
149   public static final int TYPE_dtsc = 0x64747363;
150 
151   @SuppressWarnings("ConstantCaseForConstants")
152   public static final int TYPE_dtsh = 0x64747368;
153 
154   @SuppressWarnings("ConstantCaseForConstants")
155   public static final int TYPE_dtsl = 0x6474736c;
156 
157   @SuppressWarnings("ConstantCaseForConstants")
158   public static final int TYPE_dtse = 0x64747365;
159 
160   @SuppressWarnings("ConstantCaseForConstants")
161   public static final int TYPE_ddts = 0x64647473;
162 
163   @SuppressWarnings("ConstantCaseForConstants")
164   public static final int TYPE_tfdt = 0x74666474;
165 
166   @SuppressWarnings("ConstantCaseForConstants")
167   public static final int TYPE_tfhd = 0x74666864;
168 
169   @SuppressWarnings("ConstantCaseForConstants")
170   public static final int TYPE_trex = 0x74726578;
171 
172   @SuppressWarnings("ConstantCaseForConstants")
173   public static final int TYPE_trun = 0x7472756e;
174 
175   @SuppressWarnings("ConstantCaseForConstants")
176   public static final int TYPE_sidx = 0x73696478;
177 
178   @SuppressWarnings("ConstantCaseForConstants")
179   public static final int TYPE_moov = 0x6d6f6f76;
180 
181   @SuppressWarnings("ConstantCaseForConstants")
182   public static final int TYPE_mvhd = 0x6d766864;
183 
184   @SuppressWarnings("ConstantCaseForConstants")
185   public static final int TYPE_trak = 0x7472616b;
186 
187   @SuppressWarnings("ConstantCaseForConstants")
188   public static final int TYPE_mdia = 0x6d646961;
189 
190   @SuppressWarnings("ConstantCaseForConstants")
191   public static final int TYPE_minf = 0x6d696e66;
192 
193   @SuppressWarnings("ConstantCaseForConstants")
194   public static final int TYPE_stbl = 0x7374626c;
195 
196   @SuppressWarnings("ConstantCaseForConstants")
197   public static final int TYPE_esds = 0x65736473;
198 
199   @SuppressWarnings("ConstantCaseForConstants")
200   public static final int TYPE_moof = 0x6d6f6f66;
201 
202   @SuppressWarnings("ConstantCaseForConstants")
203   public static final int TYPE_traf = 0x74726166;
204 
205   @SuppressWarnings("ConstantCaseForConstants")
206   public static final int TYPE_mvex = 0x6d766578;
207 
208   @SuppressWarnings("ConstantCaseForConstants")
209   public static final int TYPE_mehd = 0x6d656864;
210 
211   @SuppressWarnings("ConstantCaseForConstants")
212   public static final int TYPE_tkhd = 0x746b6864;
213 
214   @SuppressWarnings("ConstantCaseForConstants")
215   public static final int TYPE_edts = 0x65647473;
216 
217   @SuppressWarnings("ConstantCaseForConstants")
218   public static final int TYPE_elst = 0x656c7374;
219 
220   @SuppressWarnings("ConstantCaseForConstants")
221   public static final int TYPE_mdhd = 0x6d646864;
222 
223   @SuppressWarnings("ConstantCaseForConstants")
224   public static final int TYPE_hdlr = 0x68646c72;
225 
226   @SuppressWarnings("ConstantCaseForConstants")
227   public static final int TYPE_stsd = 0x73747364;
228 
229   @SuppressWarnings("ConstantCaseForConstants")
230   public static final int TYPE_pssh = 0x70737368;
231 
232   @SuppressWarnings("ConstantCaseForConstants")
233   public static final int TYPE_sinf = 0x73696e66;
234 
235   @SuppressWarnings("ConstantCaseForConstants")
236   public static final int TYPE_schm = 0x7363686d;
237 
238   @SuppressWarnings("ConstantCaseForConstants")
239   public static final int TYPE_schi = 0x73636869;
240 
241   @SuppressWarnings("ConstantCaseForConstants")
242   public static final int TYPE_tenc = 0x74656e63;
243 
244   @SuppressWarnings("ConstantCaseForConstants")
245   public static final int TYPE_encv = 0x656e6376;
246 
247   @SuppressWarnings("ConstantCaseForConstants")
248   public static final int TYPE_enca = 0x656e6361;
249 
250   @SuppressWarnings("ConstantCaseForConstants")
251   public static final int TYPE_frma = 0x66726d61;
252 
253   @SuppressWarnings("ConstantCaseForConstants")
254   public static final int TYPE_saiz = 0x7361697a;
255 
256   @SuppressWarnings("ConstantCaseForConstants")
257   public static final int TYPE_saio = 0x7361696f;
258 
259   @SuppressWarnings("ConstantCaseForConstants")
260   public static final int TYPE_sbgp = 0x73626770;
261 
262   @SuppressWarnings("ConstantCaseForConstants")
263   public static final int TYPE_sgpd = 0x73677064;
264 
265   @SuppressWarnings("ConstantCaseForConstants")
266   public static final int TYPE_uuid = 0x75756964;
267 
268   @SuppressWarnings("ConstantCaseForConstants")
269   public static final int TYPE_senc = 0x73656e63;
270 
271   @SuppressWarnings("ConstantCaseForConstants")
272   public static final int TYPE_pasp = 0x70617370;
273 
274   @SuppressWarnings("ConstantCaseForConstants")
275   public static final int TYPE_TTML = 0x54544d4c;
276 
277   @SuppressWarnings("ConstantCaseForConstants")
278   public static final int TYPE_vmhd = 0x766d6864;
279 
280   @SuppressWarnings("ConstantCaseForConstants")
281   public static final int TYPE_mp4v = 0x6d703476;
282 
283   @SuppressWarnings("ConstantCaseForConstants")
284   public static final int TYPE_stts = 0x73747473;
285 
286   @SuppressWarnings("ConstantCaseForConstants")
287   public static final int TYPE_stss = 0x73747373;
288 
289   @SuppressWarnings("ConstantCaseForConstants")
290   public static final int TYPE_ctts = 0x63747473;
291 
292   @SuppressWarnings("ConstantCaseForConstants")
293   public static final int TYPE_stsc = 0x73747363;
294 
295   @SuppressWarnings("ConstantCaseForConstants")
296   public static final int TYPE_stsz = 0x7374737a;
297 
298   @SuppressWarnings("ConstantCaseForConstants")
299   public static final int TYPE_stz2 = 0x73747a32;
300 
301   @SuppressWarnings("ConstantCaseForConstants")
302   public static final int TYPE_stco = 0x7374636f;
303 
304   @SuppressWarnings("ConstantCaseForConstants")
305   public static final int TYPE_co64 = 0x636f3634;
306 
307   @SuppressWarnings("ConstantCaseForConstants")
308   public static final int TYPE_tx3g = 0x74783367;
309 
310   @SuppressWarnings("ConstantCaseForConstants")
311   public static final int TYPE_wvtt = 0x77767474;
312 
313   @SuppressWarnings("ConstantCaseForConstants")
314   public static final int TYPE_stpp = 0x73747070;
315 
316   @SuppressWarnings("ConstantCaseForConstants")
317   public static final int TYPE_c608 = 0x63363038;
318 
319   @SuppressWarnings("ConstantCaseForConstants")
320   public static final int TYPE_samr = 0x73616d72;
321 
322   @SuppressWarnings("ConstantCaseForConstants")
323   public static final int TYPE_sawb = 0x73617762;
324 
325   @SuppressWarnings("ConstantCaseForConstants")
326   public static final int TYPE_udta = 0x75647461;
327 
328   @SuppressWarnings("ConstantCaseForConstants")
329   public static final int TYPE_meta = 0x6d657461;
330 
331   @SuppressWarnings("ConstantCaseForConstants")
332   public static final int TYPE_keys = 0x6b657973;
333 
334   @SuppressWarnings("ConstantCaseForConstants")
335   public static final int TYPE_ilst = 0x696c7374;
336 
337   @SuppressWarnings("ConstantCaseForConstants")
338   public static final int TYPE_mean = 0x6d65616e;
339 
340   @SuppressWarnings("ConstantCaseForConstants")
341   public static final int TYPE_name = 0x6e616d65;
342 
343   @SuppressWarnings("ConstantCaseForConstants")
344   public static final int TYPE_data = 0x64617461;
345 
346   @SuppressWarnings("ConstantCaseForConstants")
347   public static final int TYPE_emsg = 0x656d7367;
348 
349   @SuppressWarnings("ConstantCaseForConstants")
350   public static final int TYPE_st3d = 0x73743364;
351 
352   @SuppressWarnings("ConstantCaseForConstants")
353   public static final int TYPE_sv3d = 0x73763364;
354 
355   @SuppressWarnings("ConstantCaseForConstants")
356   public static final int TYPE_proj = 0x70726f6a;
357 
358   @SuppressWarnings("ConstantCaseForConstants")
359   public static final int TYPE_camm = 0x63616d6d;
360 
361   @SuppressWarnings("ConstantCaseForConstants")
362   public static final int TYPE_alac = 0x616c6163;
363 
364   @SuppressWarnings("ConstantCaseForConstants")
365   public static final int TYPE_alaw = 0x616c6177;
366 
367   @SuppressWarnings("ConstantCaseForConstants")
368   public static final int TYPE_ulaw = 0x756c6177;
369 
370   @SuppressWarnings("ConstantCaseForConstants")
371   public static final int TYPE_Opus = 0x4f707573;
372 
373   @SuppressWarnings("ConstantCaseForConstants")
374   public static final int TYPE_dOps = 0x644f7073;
375 
376   @SuppressWarnings("ConstantCaseForConstants")
377   public static final int TYPE_fLaC = 0x664c6143;
378 
379   @SuppressWarnings("ConstantCaseForConstants")
380   public static final int TYPE_dfLa = 0x64664c61;
381 
382   @SuppressWarnings("ConstantCaseForConstants")
383   public static final int TYPE_twos = 0x74776f73;
384 
385   public final int type;
386 
Atom(int type)387   public Atom(int type) {
388     this.type = type;
389   }
390 
391   @Override
toString()392   public String toString() {
393     return getAtomTypeString(type);
394   }
395 
396   /**
397    * An MP4 atom that is a leaf.
398    */
399   /* package */ static final class LeafAtom extends Atom {
400 
401     /**
402      * The atom data.
403      */
404     public final ParsableByteArray data;
405 
406     /**
407      * @param type The type of the atom.
408      * @param data The atom data.
409      */
LeafAtom(int type, ParsableByteArray data)410     public LeafAtom(int type, ParsableByteArray data) {
411       super(type);
412       this.data = data;
413     }
414 
415   }
416 
417   /**
418    * An MP4 atom that has child atoms.
419    */
420   /* package */ static final class ContainerAtom extends Atom {
421 
422     public final long endPosition;
423     public final List<LeafAtom> leafChildren;
424     public final List<ContainerAtom> containerChildren;
425 
426     /**
427      * @param type The type of the atom.
428      * @param endPosition The position of the first byte after the end of the atom.
429      */
ContainerAtom(int type, long endPosition)430     public ContainerAtom(int type, long endPosition) {
431       super(type);
432       this.endPosition = endPosition;
433       leafChildren = new ArrayList<>();
434       containerChildren = new ArrayList<>();
435     }
436 
437     /**
438      * Adds a child leaf to this container.
439      *
440      * @param atom The child to add.
441      */
add(LeafAtom atom)442     public void add(LeafAtom atom) {
443       leafChildren.add(atom);
444     }
445 
446     /**
447      * Adds a child container to this container.
448      *
449      * @param atom The child to add.
450      */
add(ContainerAtom atom)451     public void add(ContainerAtom atom) {
452       containerChildren.add(atom);
453     }
454 
455     /**
456      * Returns the child leaf of the given type.
457      *
458      * <p>If no child exists with the given type then null is returned. If multiple children exist
459      * with the given type then the first one to have been added is returned.
460      *
461      * @param type The leaf type.
462      * @return The child leaf of the given type, or null if no such child exists.
463      */
464     @Nullable
getLeafAtomOfType(int type)465     public LeafAtom getLeafAtomOfType(int type) {
466       int childrenSize = leafChildren.size();
467       for (int i = 0; i < childrenSize; i++) {
468         LeafAtom atom = leafChildren.get(i);
469         if (atom.type == type) {
470           return atom;
471         }
472       }
473       return null;
474     }
475 
476     /**
477      * Returns the child container of the given type.
478      *
479      * <p>If no child exists with the given type then null is returned. If multiple children exist
480      * with the given type then the first one to have been added is returned.
481      *
482      * @param type The container type.
483      * @return The child container of the given type, or null if no such child exists.
484      */
485     @Nullable
getContainerAtomOfType(int type)486     public ContainerAtom getContainerAtomOfType(int type) {
487       int childrenSize = containerChildren.size();
488       for (int i = 0; i < childrenSize; i++) {
489         ContainerAtom atom = containerChildren.get(i);
490         if (atom.type == type) {
491           return atom;
492         }
493       }
494       return null;
495     }
496 
497     /**
498      * Returns the total number of leaf/container children of this atom with the given type.
499      *
500      * @param type The type of child atoms to count.
501      * @return The total number of leaf/container children of this atom with the given type.
502      */
getChildAtomOfTypeCount(int type)503     public int getChildAtomOfTypeCount(int type) {
504       int count = 0;
505       int size = leafChildren.size();
506       for (int i = 0; i < size; i++) {
507         LeafAtom atom = leafChildren.get(i);
508         if (atom.type == type) {
509           count++;
510         }
511       }
512       size = containerChildren.size();
513       for (int i = 0; i < size; i++) {
514         ContainerAtom atom = containerChildren.get(i);
515         if (atom.type == type) {
516           count++;
517         }
518       }
519       return count;
520     }
521 
522     @Override
toString()523     public String toString() {
524       return getAtomTypeString(type)
525           + " leaves: " + Arrays.toString(leafChildren.toArray())
526           + " containers: " + Arrays.toString(containerChildren.toArray());
527     }
528 
529   }
530 
531   /**
532    * Parses the version number out of the additional integer component of a full atom.
533    */
parseFullAtomVersion(int fullAtomInt)534   public static int parseFullAtomVersion(int fullAtomInt) {
535     return 0x000000FF & (fullAtomInt >> 24);
536   }
537 
538   /**
539    * Parses the atom flags out of the additional integer component of a full atom.
540    */
parseFullAtomFlags(int fullAtomInt)541   public static int parseFullAtomFlags(int fullAtomInt) {
542     return 0x00FFFFFF & fullAtomInt;
543   }
544 
545   /**
546    * Converts a numeric atom type to the corresponding four character string.
547    *
548    * @param type The numeric atom type.
549    * @return The corresponding four character string.
550    */
getAtomTypeString(int type)551   public static String getAtomTypeString(int type) {
552     return "" + (char) ((type >> 24) & 0xFF)
553         + (char) ((type >> 16) & 0xFF)
554         + (char) ((type >> 8) & 0xFF)
555         + (char) (type & 0xFF);
556   }
557 
558 }
559