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