| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "media/mp4/box_definitions.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "media/mp4/box_reader.h" |
| 9 #include "media/mp4/rcheck.h" |
| 10 #include "media/mp4/fourccs.h" |
| 11 |
| 12 namespace media { |
| 13 namespace mp4 { |
| 14 |
| 15 bool Parse(BoxReader* r, FileType* type) { |
| 16 RCHECK(r->Read(&type->major_brand) && r->Read(&type->minor_version)); |
| 17 size_t num_brands = (r->size() - r->pos()) / sizeof(FourCC); |
| 18 return r->SkipBytes(sizeof(FourCC) * num_brands); // compatible_brands |
| 19 } |
| 20 |
| 21 ProtectionSystemSpecificHeader::ProtectionSystemSpecificHeader() {} |
| 22 ProtectionSystemSpecificHeader::~ProtectionSystemSpecificHeader() {} |
| 23 |
| 24 bool Parse(BoxReader* r, ProtectionSystemSpecificHeader* pssh) { |
| 25 uint32 size; |
| 26 return r->SkipBytes(4) && |
| 27 r->ReadVec(&pssh->system_id, 16) && |
| 28 r->Read(&size) && |
| 29 r->ReadVec(&pssh->data, size); |
| 30 } |
| 31 |
| 32 SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() {} |
| 33 SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() {} |
| 34 |
| 35 bool Parse(BoxReader* r, SampleAuxiliaryInformationOffset* saio) { |
| 36 RCHECK(r->ReadFullBoxHeader()); |
| 37 if (r->flags() & 1) |
| 38 RCHECK(r->SkipBytes(8)); |
| 39 |
| 40 uint32 count; |
| 41 RCHECK(r->Read(&count) && |
| 42 r->HasBytes(count * (r->version() == 1 ? 8 : 4))); |
| 43 saio->offsets.resize(count); |
| 44 |
| 45 for (uint32 i = 0; i < count; i++) { |
| 46 if (r->version() == 1) { |
| 47 RCHECK(r->Read(&saio->offsets[i])); |
| 48 } else { |
| 49 RCHECK(r->Read4(&saio->offsets[i])); |
| 50 } |
| 51 } |
| 52 return true; |
| 53 } |
| 54 |
| 55 SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize() |
| 56 : default_sample_info_size(0), sample_count(0) { |
| 57 } |
| 58 |
| 59 SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() {} |
| 60 |
| 61 bool Parse(BoxReader* r, SampleAuxiliaryInformationSize* saiz) { |
| 62 RCHECK(r->ReadFullBoxHeader()); |
| 63 if (r->flags() & 1) |
| 64 RCHECK(r->SkipBytes(8)); |
| 65 |
| 66 RCHECK(r->Read(&saiz->default_sample_info_size) && |
| 67 r->Read(&saiz->sample_count)); |
| 68 if (saiz->default_sample_info_size == 0) |
| 69 return r->ReadVec(&saiz->sample_info_sizes, saiz->sample_count); |
| 70 return true; |
| 71 } |
| 72 |
| 73 bool Parse(BoxReader* r, OriginalFormat* format) { |
| 74 return r->Read(&format->format); |
| 75 } |
| 76 |
| 77 bool Parse(BoxReader* r, SchemeType* schm) { |
| 78 RCHECK(r->SkipBytes(4) && r->Read(&schm->type) && r->Read(&schm->version)); |
| 79 RCHECK(schm->type == FOURCC_CENC); |
| 80 return true; |
| 81 } |
| 82 |
| 83 TrackEncryption::TrackEncryption() |
| 84 : is_encrypted(false), default_iv_size(0) { |
| 85 } |
| 86 |
| 87 TrackEncryption::~TrackEncryption() {} |
| 88 |
| 89 bool Parse(BoxReader* r, TrackEncryption* tenc) { |
| 90 uint8 flag; |
| 91 RCHECK(r->SkipBytes(2) && |
| 92 r->Read(&flag) && |
| 93 r->Read(&tenc->default_iv_size) && |
| 94 r->ReadVec(&tenc->default_kid, 16)); |
| 95 tenc->is_encrypted = (flag != 0); |
| 96 if (tenc->is_encrypted) { |
| 97 RCHECK(tenc->default_iv_size == 8 || tenc->default_iv_size == 16); |
| 98 } else { |
| 99 RCHECK(tenc->default_iv_size == 0); |
| 100 } |
| 101 return true; |
| 102 } |
| 103 |
| 104 bool Parse(BoxReader* r, SchemeInfo* schi) { |
| 105 return r->ScanChildren() && r->ReadChild(&schi->track_encryption); |
| 106 } |
| 107 |
| 108 bool Parse(BoxReader* r, ProtectionSchemeInfo* sinf) { |
| 109 return r->ScanChildren() && |
| 110 r->ReadChild(&sinf->type) && |
| 111 r->ReadChild(&sinf->info); |
| 112 } |
| 113 |
| 114 bool Parse(BoxReader* r, MovieHeader* mvhd) { |
| 115 RCHECK(r->ReadFullBoxHeader()); |
| 116 |
| 117 if (r->version() == 1) { |
| 118 RCHECK(r->Read(&mvhd->creation_time) && |
| 119 r->Read(&mvhd->modification_time) && |
| 120 r->Read(&mvhd->timescale) && |
| 121 r->Read(&mvhd->duration)); |
| 122 } else { |
| 123 RCHECK(r->Read4(&mvhd->creation_time) && |
| 124 r->Read4(&mvhd->modification_time) && |
| 125 r->Read(&mvhd->timescale) && |
| 126 r->Read4(&mvhd->duration)); |
| 127 } |
| 128 |
| 129 RCHECK(r->Read(&mvhd->rate) && |
| 130 r->Read(&mvhd->volume) && |
| 131 r->SkipBytes(10) && // reserved |
| 132 r->SkipBytes(36) && // matrix |
| 133 r->SkipBytes(24) && // predefined zero |
| 134 r->Read(&mvhd->next_track_id)); |
| 135 return true; |
| 136 } |
| 137 |
| 138 TrackHeader::TrackHeader() {} |
| 139 TrackHeader::~TrackHeader() {} |
| 140 |
| 141 |
| 142 bool Parse(BoxReader* r, TrackHeader* tkhd) { |
| 143 RCHECK(r->ReadFullBoxHeader()); |
| 144 if (r->version() == 1) { |
| 145 RCHECK(r->Read(&tkhd->creation_time) && |
| 146 r->Read(&tkhd->modification_time) && |
| 147 r->Read(&tkhd->track_id) && |
| 148 r->SkipBytes(4) && // reserved |
| 149 r->Read(&tkhd->duration)); |
| 150 } else { |
| 151 RCHECK(r->Read4(&tkhd->creation_time) && |
| 152 r->Read4(&tkhd->modification_time) && |
| 153 r->Read(&tkhd->track_id) && |
| 154 r->SkipBytes(4) && // reserved |
| 155 r->Read4(&tkhd->duration)); |
| 156 } |
| 157 |
| 158 RCHECK(r->SkipBytes(8) && // reserved |
| 159 r->Read(&tkhd->layer) && |
| 160 r->Read(&tkhd->alternate_group) && |
| 161 r->Read(&tkhd->volume) && |
| 162 r->SkipBytes(2) && // reserved |
| 163 r->SkipBytes(36) && // matrix |
| 164 r->Read(&tkhd->width) && |
| 165 r->Read(&tkhd->height)); |
| 166 tkhd->width >>= 16; |
| 167 tkhd->height >>= 16; |
| 168 return true; |
| 169 } |
| 170 |
| 171 SampleDescription::SampleDescription() {} |
| 172 SampleDescription::~SampleDescription() {} |
| 173 |
| 174 bool Parse(BoxReader* r, SampleDescription* desc) { |
| 175 uint32 count; |
| 176 RCHECK(r->SkipBytes(4) && r->Read(&count) && r->ScanChildren()); |
| 177 desc->video_entries.clear(); |
| 178 desc->audio_entries.clear(); |
| 179 |
| 180 // Note: this value is preset before scanning begins. See comments in the |
| 181 // Parse(Media*) function. |
| 182 if (desc->type == kVideo) { |
| 183 RCHECK(r->ReadAllChildren(&desc->video_entries)); |
| 184 } else if (desc->type == kAudio) { |
| 185 RCHECK(r->ReadAllChildren(&desc->audio_entries)); |
| 186 } |
| 187 return true; |
| 188 } |
| 189 |
| 190 SampleTable::SampleTable() {} |
| 191 SampleTable::~SampleTable() {} |
| 192 |
| 193 bool Parse(BoxReader* r, SampleTable* table) { |
| 194 return r->ScanChildren() && |
| 195 r->ReadChild(&table->description); |
| 196 } |
| 197 |
| 198 EditList::EditList() {} |
| 199 EditList::~EditList() {} |
| 200 |
| 201 bool Parse(BoxReader* r, EditList* list) { |
| 202 uint32 count; |
| 203 RCHECK(r->ReadFullBoxHeader() && r->Read(&count)); |
| 204 |
| 205 if (r->version() == 1) { |
| 206 RCHECK(r->HasBytes(count * 20)); |
| 207 } else { |
| 208 RCHECK(r->HasBytes(count * 12)); |
| 209 } |
| 210 list->edits.resize(count); |
| 211 |
| 212 for (auto edit = list->edits.begin(); edit != list->edits.end(); ++edit) { |
| 213 if (r->version() == 1) { |
| 214 RCHECK(r->Read(&edit->segment_duration) && |
| 215 r->Read(&edit->media_time)); |
| 216 } else { |
| 217 RCHECK(r->Read4(&edit->segment_duration) && |
| 218 r->Read4(&edit->media_time)); |
| 219 } |
| 220 RCHECK(r->Read(&edit->media_rate_integer) && |
| 221 r->Read(&edit->media_rate_fraction)); |
| 222 } |
| 223 return true; |
| 224 } |
| 225 |
| 226 Edit::Edit() {} |
| 227 Edit::~Edit() {} |
| 228 |
| 229 bool Parse(BoxReader* r, Edit* box) { |
| 230 return r->ScanChildren() && r->ReadChild(&box->list); |
| 231 } |
| 232 |
| 233 bool Parse(BoxReader* r, HandlerReference* reference) { |
| 234 FourCC type; |
| 235 RCHECK(r->SkipBytes(8) && r->Read(&type)); |
| 236 // Note: remaining fields in box ignored |
| 237 if (type == FOURCC_VIDE) { |
| 238 |
| 239 reference->type = kVideo; |
| 240 } else if (type == FOURCC_SOUN) { |
| 241 reference->type = kAudio; |
| 242 } else { |
| 243 reference->type = kInvalid; |
| 244 } |
| 245 return true; |
| 246 } |
| 247 |
| 248 SampleEntry::SampleEntry() {} |
| 249 SampleEntry::~SampleEntry() {} |
| 250 |
| 251 bool ParseSampleEntryHead(BoxReader* r, SampleEntry* entry) { |
| 252 entry->format = r->type(); |
| 253 return r->SkipBytes(6) && r->Read(&entry->data_reference_index); |
| 254 } |
| 255 |
| 256 AudioSampleEntry::AudioSampleEntry() {} |
| 257 AudioSampleEntry::~AudioSampleEntry() {} |
| 258 |
| 259 bool Parse(BoxReader* r, AudioSampleEntry* entry) { |
| 260 RCHECK(ParseSampleEntryHead(r, entry) && |
| 261 r->SkipBytes(8) && |
| 262 r->Read(&entry->channelcount) && |
| 263 r->Read(&entry->samplesize) && |
| 264 r->SkipBytes(4) && |
| 265 r->Read(&entry->samplerate)); |
| 266 // Convert from 16.16 fixed point to integer |
| 267 entry->samplerate >>= 16; |
| 268 |
| 269 RCHECK(r->ScanChildren()); |
| 270 if (entry->format == FOURCC_ENCA) { |
| 271 RCHECK(r->ReadChild(&entry->sinf)); |
| 272 } |
| 273 return true; |
| 274 } |
| 275 |
| 276 VideoSampleEntry::VideoSampleEntry() {} |
| 277 VideoSampleEntry::~VideoSampleEntry() {} |
| 278 |
| 279 bool Parse(BoxReader* r, VideoSampleEntry* entry) { |
| 280 RCHECK(ParseSampleEntryHead(r, entry) && |
| 281 r->SkipBytes(16) && |
| 282 r->Read(&entry->width) && |
| 283 r->Read(&entry->height) && |
| 284 r->SkipBytes(50)); |
| 285 |
| 286 RCHECK(r->ScanChildren()); |
| 287 if (entry->format == FOURCC_ENCV) { |
| 288 RCHECK(r->ReadChild(&entry->sinf)); |
| 289 } |
| 290 |
| 291 // TODO(strobe): Widevine test files do not follow spec here; check disabled |
| 292 //if (entry->format == FOURCC_AVC1 || |
| 293 // (entry->format == FOURCC_ENCV && |
| 294 // entry->sinf.format.format == FOURCC_AVC1)) { |
| 295 RCHECK(r->ReadChild(&entry->avcc)); |
| 296 //} |
| 297 return true; |
| 298 } |
| 299 |
| 300 MediaHeader::MediaHeader() {} |
| 301 MediaHeader::~MediaHeader() {} |
| 302 |
| 303 bool Parse(BoxReader* r, MediaHeader* header) { |
| 304 RCHECK(r->ReadFullBoxHeader()); |
| 305 |
| 306 if (r->version() == 1) { |
| 307 RCHECK(r->Read(&header->creation_time) && |
| 308 r->Read(&header->modification_time) && |
| 309 r->Read(&header->timescale) && |
| 310 r->Read(&header->duration)); |
| 311 } else { |
| 312 RCHECK(r->Read4(&header->creation_time) && |
| 313 r->Read4(&header->modification_time) && |
| 314 r->Read(&header->timescale) && |
| 315 r->Read4(&header->duration)); |
| 316 } |
| 317 // Skip language information |
| 318 return r->SkipBytes(4); |
| 319 } |
| 320 |
| 321 bool Parse(BoxReader* r, MediaInformation* information) { |
| 322 return r->ScanChildren() && |
| 323 r->ReadChild(&information->sample_table); |
| 324 } |
| 325 |
| 326 bool Parse(BoxReader* r, Media* media) { |
| 327 RCHECK(r->ScanChildren() && |
| 328 r->ReadChild(&media->header) && |
| 329 r->ReadChild(&media->handler)); |
| 330 |
| 331 // Maddeningly, the HandlerReference box specifies how to parse the |
| 332 // SampleDescription box, making the latter the only box (of those that we |
| 333 // support) which cannot be parsed correctly on its own (or even with |
| 334 // information from its strict ancestor tree). We thus copy the handler type |
| 335 // to the sample description box *before* parsing it to provide this |
| 336 // information while parsing. |
| 337 media->information.sample_table.description.type = media->handler.type; |
| 338 RCHECK(r->ReadChild(&media->information)); |
| 339 return true; |
| 340 } |
| 341 |
| 342 bool Parse(BoxReader* r, Track* track) { |
| 343 RCHECK(r->ScanChildren() && |
| 344 r->ReadChild(&track->header) && |
| 345 r->ReadChild(&track->media) && |
| 346 r->MaybeReadChild(&track->edit)); |
| 347 return true; |
| 348 } |
| 349 |
| 350 bool Parse(BoxReader* r, MovieExtendsHeader* header) { |
| 351 RCHECK(r->Read(&header->fragment_duration)); |
| 352 return true; |
| 353 } |
| 354 |
| 355 bool Parse(BoxReader* r, TrackExtends* extends) { |
| 356 RCHECK(r->ReadFullBoxHeader() && |
| 357 r->Read(&extends->track_id) && |
| 358 r->Read(&extends->default_sample_description_index) && |
| 359 r->Read(&extends->default_sample_duration) && |
| 360 r->Read(&extends->default_sample_size) && |
| 361 r->Read(&extends->default_sample_flags)); |
| 362 return true; |
| 363 } |
| 364 |
| 365 MovieExtends::MovieExtends() {}; |
| 366 MovieExtends::~MovieExtends() {}; |
| 367 |
| 368 bool Parse(BoxReader* r, MovieExtends* extends) { |
| 369 extends->header.fragment_duration = 0; |
| 370 return r->ScanChildren() && |
| 371 r->MaybeReadChild(&extends->header) && |
| 372 // TODO(strobe): does not detect correspondence rule (trex must match |
| 373 // one-to-one with trak) |
| 374 r->ReadChildren(&extends->tracks); |
| 375 } |
| 376 |
| 377 Movie::Movie() {}; |
| 378 Movie::~Movie() {}; |
| 379 |
| 380 bool Parse(BoxReader* r, Movie* moov) { |
| 381 return r->ScanChildren() && |
| 382 r->ReadChild(&moov->header) && |
| 383 r->ReadChildren(&moov->tracks) && |
| 384 // Media Source specific: 'mvex' required |
| 385 r->ReadChild(&moov->extends) && |
| 386 r->MaybeReadChildren(&moov->pssh); |
| 387 } |
| 388 |
| 389 bool Parse(BoxReader* r, TrackFragmentDecodeTime* tfdt) { |
| 390 RCHECK(r->ReadFullBoxHeader()); |
| 391 if (r->version() == 1) |
| 392 return r->Read(&tfdt->decode_time); |
| 393 else |
| 394 return r->Read4(&tfdt->decode_time); |
| 395 } |
| 396 |
| 397 bool Parse(BoxReader* r, MovieFragmentHeader* mfhd) { |
| 398 return r->SkipBytes(4) && r->Read(&mfhd->sequence_number); |
| 399 } |
| 400 |
| 401 bool Parse(BoxReader* r, TrackFragmentHeader* tfhd) { |
| 402 memset(tfhd, 0, sizeof(TrackFragmentHeader)); |
| 403 |
| 404 RCHECK(r->ReadFullBoxHeader() && r->Read(&tfhd->track_id)); |
| 405 |
| 406 // Media Source specific: we require that 'default-base-is-moof' (14496-12 |
| 407 // Amendment 2) be set, and reject tracks that set 'base-data-offset-present'. |
| 408 // |
| 409 // TODO(strobe): Test files do not have 'default-base-is-moof' set explicitly |
| 410 // (although they are structured as if it is set). Because this flag is hidden |
| 411 // in Amendment 2, it might not be set by all implementors. Should we reject |
| 412 // such files, or try them anyway? |
| 413 // |
| 414 // RCHECK((flags & 0x020000) && !(flags & 0x1)); |
| 415 RCHECK(!(r->flags() & 0x1)); |
| 416 |
| 417 if (r->flags() & 0x2) |
| 418 RCHECK(r->SkipBytes(4)); // sample_description_index |
| 419 |
| 420 if (r->flags() & 0x8) |
| 421 RCHECK(r->Read(&tfhd->default_sample_duration)); |
| 422 |
| 423 if (r->flags() & 0x10) |
| 424 RCHECK(r->Read(&tfhd->default_sample_size)); |
| 425 |
| 426 if (r->flags() & 0x20) |
| 427 RCHECK(r->Read(&tfhd->default_sample_flags)); |
| 428 |
| 429 return true; |
| 430 } |
| 431 |
| 432 TrackFragmentRun::TrackFragmentRun() {} |
| 433 TrackFragmentRun::~TrackFragmentRun() {} |
| 434 |
| 435 bool Parse(BoxReader* r, TrackFragmentRun* trun) { |
| 436 RCHECK(r->ReadFullBoxHeader() && |
| 437 r->Read(&trun->sample_count)); |
| 438 const uint32 flags = r->flags(); |
| 439 |
| 440 bool data_offset_present = flags & 0x1; |
| 441 bool first_sample_flags_present = flags & 0x4; |
| 442 bool sample_duration_present = flags & 0x100; |
| 443 bool sample_size_present = flags & 0x200; |
| 444 bool sample_flags_present = flags & 0x400; |
| 445 bool sample_composition_time_offsets_present = flags & 0x800; |
| 446 |
| 447 if (data_offset_present) { |
| 448 RCHECK(r->Read(&trun->data_offset)); |
| 449 } else { |
| 450 trun->data_offset = 0; |
| 451 } |
| 452 |
| 453 uint32 first_sample_flags; |
| 454 if (first_sample_flags_present) |
| 455 RCHECK(r->Read(&first_sample_flags)); |
| 456 |
| 457 int fields = sample_duration_present + sample_size_present + |
| 458 sample_flags_present + sample_composition_time_offsets_present; |
| 459 RCHECK(r->HasBytes(fields * trun->sample_count)); |
| 460 |
| 461 if (sample_duration_present) |
| 462 trun->sample_durations.resize(trun->sample_count); |
| 463 if (sample_size_present) |
| 464 trun->sample_sizes.resize(trun->sample_count); |
| 465 if (sample_flags_present) |
| 466 trun->sample_flags.resize(trun->sample_count); |
| 467 if (sample_composition_time_offsets_present) |
| 468 trun->sample_composition_time_offsets.resize(trun->sample_count); |
| 469 |
| 470 for (uint32 i = 0; i < trun->sample_count; ++i) { |
| 471 if (sample_duration_present) |
| 472 RCHECK(r->Read(&trun->sample_durations[i])); |
| 473 if (sample_size_present) |
| 474 RCHECK(r->Read(&trun->sample_sizes[i])); |
| 475 if (sample_flags_present) |
| 476 RCHECK(r->Read(&trun->sample_flags[i])); |
| 477 if (sample_composition_time_offsets_present) |
| 478 RCHECK(r->Read(&trun->sample_composition_time_offsets[i])); |
| 479 } |
| 480 |
| 481 if (first_sample_flags_present) { |
| 482 if (trun->sample_flags.size() == 0) { |
| 483 trun->sample_flags.push_back(first_sample_flags); |
| 484 } else { |
| 485 trun->sample_flags[0] = first_sample_flags; |
| 486 } |
| 487 } |
| 488 return true; |
| 489 } |
| 490 |
| 491 TrackFragment::TrackFragment() {} |
| 492 TrackFragment::~TrackFragment() {} |
| 493 |
| 494 bool Parse(BoxReader* r, TrackFragment* traf) { |
| 495 return r->ScanChildren() && |
| 496 r->ReadChild(&traf->header) && |
| 497 // Media Source specific: 'tfdt' required |
| 498 r->ReadChild(&traf->decode_time) && |
| 499 r->MaybeReadChildren(&traf->runs) && |
| 500 r->MaybeReadChild(&traf->auxiliary_offset) && |
| 501 r->MaybeReadChild(&traf->auxiliary_size); |
| 502 } |
| 503 |
| 504 MovieFragment::MovieFragment() {} |
| 505 MovieFragment::~MovieFragment() {} |
| 506 |
| 507 bool Parse(BoxReader* r, MovieFragment* moof) { |
| 508 RCHECK(r->ScanChildren() && |
| 509 r->ReadChild(&moof->header) && |
| 510 r->ReadChildren(&moof->tracks) && |
| 511 r->MaybeReadChildren(&moof->pssh)); |
| 512 return true; |
| 513 } |
| 514 |
| 515 bool Parse(BoxReader* r, SegmentIndex* sidx) { |
| 516 RCHECK(r->ReadFullBoxHeader() && |
| 517 r->Read(&sidx->reference_id) && |
| 518 r->Read(&sidx->timescale)); |
| 519 |
| 520 if (r->version() == 0) { |
| 521 RCHECK(r->Read4(&sidx->earliest_presentation_time) && |
| 522 r->Read4(&sidx->first_offset)); |
| 523 } else { |
| 524 RCHECK(r->Read(&sidx->earliest_presentation_time) && |
| 525 r->Read(&sidx->first_offset)); |
| 526 } |
| 527 |
| 528 uint32 reference_count; |
| 529 RCHECK(r->SkipBytes(2) && // reserved |
| 530 r->Read(&reference_count) && |
| 531 r->HasBytes(12 * reference_count)); |
| 532 |
| 533 for (uint32 i = 0; i < reference_count; ++i) { |
| 534 uint32 flags; |
| 535 RCHECK(r->Read(&sidx->sizes[i]) && |
| 536 r->Read(&sidx->durations[i]) && |
| 537 r->Read(&flags)); |
| 538 |
| 539 uint32 type = flags / 0x10000000 % 8; |
| 540 |
| 541 RCHECK(!(sidx->sizes[i] & 0x8000000) != 0 || |
| 542 (flags & 0x80000000) != 0x80000000 || |
| 543 (type != 0 && type != 1) || |
| 544 (flags % 0x10000000 != 0)); |
| 545 } |
| 546 return true; |
| 547 } |
| 548 |
| 549 } // namespace mp4 |
| 550 } // namespace media |
| OLD | NEW |