1 /* 2 * Copyright (C) 2009 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 17 #define LOG_TAG "SampleTable" 18 //#define LOG_NDEBUG 0 19 #include <utils/Log.h> 20 21 #include <limits> 22 23 #include "SampleTable.h" 24 #include "SampleIterator.h" 25 26 #include <arpa/inet.h> 27 28 #include <media/MediaExtractorPluginApi.h> 29 #include <media/stagefright/foundation/ADebug.h> 30 #include <media/stagefright/foundation/ByteUtils.h> 31 32 /* TODO: remove after being merged into other branches */ 33 #ifndef UINT32_MAX 34 #define UINT32_MAX (4294967295U) 35 #endif 36 37 namespace android { 38 39 // static 40 const uint32_t SampleTable::kChunkOffsetType32 = FOURCC("stco"); 41 // static 42 const uint32_t SampleTable::kChunkOffsetType64 = FOURCC("co64"); 43 // static 44 const uint32_t SampleTable::kSampleSizeType32 = FOURCC("stsz"); 45 // static 46 const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC("stz2"); 47 48 //////////////////////////////////////////////////////////////////////////////// 49 50 const off64_t kMaxOffset = std::numeric_limits<off64_t>::max(); 51 52 struct SampleTable::CompositionDeltaLookup { 53 CompositionDeltaLookup(); 54 55 void setEntries( 56 const int32_t *deltaEntries, size_t numDeltaEntries); 57 58 int32_t getCompositionTimeOffset(uint32_t sampleIndex); 59 60 private: 61 Mutex mLock; 62 63 const int32_t *mDeltaEntries; 64 size_t mNumDeltaEntries; 65 66 size_t mCurrentDeltaEntry; 67 size_t mCurrentEntrySampleIndex; 68 69 DISALLOW_EVIL_CONSTRUCTORS(CompositionDeltaLookup); 70 }; 71 72 SampleTable::CompositionDeltaLookup::CompositionDeltaLookup() 73 : mDeltaEntries(NULL), 74 mNumDeltaEntries(0), 75 mCurrentDeltaEntry(0), 76 mCurrentEntrySampleIndex(0) { 77 } 78 79 void SampleTable::CompositionDeltaLookup::setEntries( 80 const int32_t *deltaEntries, size_t numDeltaEntries) { 81 Mutex::Autolock autolock(mLock); 82 83 mDeltaEntries = deltaEntries; 84 mNumDeltaEntries = numDeltaEntries; 85 mCurrentDeltaEntry = 0; 86 mCurrentEntrySampleIndex = 0; 87 } 88 89 int32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset( 90 uint32_t sampleIndex) { 91 Mutex::Autolock autolock(mLock); 92 93 if (mDeltaEntries == NULL) { 94 return 0; 95 } 96 97 if (sampleIndex < mCurrentEntrySampleIndex) { 98 mCurrentDeltaEntry = 0; 99 mCurrentEntrySampleIndex = 0; 100 } 101 102 while (mCurrentDeltaEntry < mNumDeltaEntries) { 103 uint32_t sampleCount = mDeltaEntries[2 * mCurrentDeltaEntry]; 104 if (sampleIndex < mCurrentEntrySampleIndex + sampleCount) { 105 return mDeltaEntries[2 * mCurrentDeltaEntry + 1]; 106 } 107 108 mCurrentEntrySampleIndex += sampleCount; 109 ++mCurrentDeltaEntry; 110 } 111 112 return 0; 113 } 114 115 //////////////////////////////////////////////////////////////////////////////// 116 117 SampleTable::SampleTable(DataSourceHelper *source) 118 : mDataSource(source), 119 mChunkOffsetOffset(-1), 120 mChunkOffsetType(0), 121 mNumChunkOffsets(0), 122 mSampleToChunkOffset(-1), 123 mNumSampleToChunkOffsets(0), 124 mSampleSizeOffset(-1), 125 mSampleSizeFieldSize(0), 126 mDefaultSampleSize(0), 127 mNumSampleSizes(0), 128 mHasTimeToSample(false), 129 mTimeToSampleCount(0), 130 mTimeToSample(NULL), 131 mSampleTimeEntries(NULL), 132 mCompositionTimeDeltaEntries(NULL), 133 mNumCompositionTimeDeltaEntries(0), 134 mCompositionDeltaLookup(new CompositionDeltaLookup), 135 mSyncSampleOffset(-1), 136 mNumSyncSamples(0), 137 mSyncSamples(NULL), 138 mLastSyncSampleIndex(0), 139 mSampleToChunkEntries(NULL), 140 mTotalSize(0) { 141 mSampleIterator = new SampleIterator(this); 142 } 143 144 SampleTable::~SampleTable() { 145 delete[] mSampleToChunkEntries; 146 mSampleToChunkEntries = NULL; 147 148 delete[] mSyncSamples; 149 mSyncSamples = NULL; 150 151 delete[] mTimeToSample; 152 mTimeToSample = NULL; 153 154 delete mCompositionDeltaLookup; 155 mCompositionDeltaLookup = NULL; 156 157 delete[] mCompositionTimeDeltaEntries; 158 mCompositionTimeDeltaEntries = NULL; 159 160 delete[] mSampleTimeEntries; 161 mSampleTimeEntries = NULL; 162 163 delete mSampleIterator; 164 mSampleIterator = NULL; 165 } 166 167 bool SampleTable::isValid() const { 168 return mChunkOffsetOffset >= 0 169 && mSampleToChunkOffset >= 0 170 && mSampleSizeOffset >= 0 171 && mHasTimeToSample; 172 } 173 174 status_t SampleTable::setChunkOffsetParams( 175 uint32_t type, off64_t data_offset, size_t data_size) { 176 if (mChunkOffsetOffset >= 0) { 177 return ERROR_MALFORMED; 178 } 179 180 CHECK(type == kChunkOffsetType32 || type == kChunkOffsetType64); 181 182 mChunkOffsetOffset = data_offset; 183 mChunkOffsetType = type; 184 185 if (data_size < 8) { 186 return ERROR_MALFORMED; 187 } 188 189 uint8_t header[8]; 190 if (mDataSource->readAt( 191 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { 192 return ERROR_IO; 193 } 194 195 if (U32_AT(header) != 0) { 196 // Expected version = 0, flags = 0. 197 return ERROR_MALFORMED; 198 } 199 200 mNumChunkOffsets = U32_AT(&header[4]); 201 202 if (mChunkOffsetType == kChunkOffsetType32) { 203 if ((data_size - 8) / 4 < mNumChunkOffsets) { 204 return ERROR_MALFORMED; 205 } 206 } else { 207 if ((data_size - 8) / 8 < mNumChunkOffsets) { 208 return ERROR_MALFORMED; 209 } 210 } 211 212 return OK; 213 } 214 215 status_t SampleTable::setSampleToChunkParams( 216 off64_t data_offset, size_t data_size) { 217 if (mSampleToChunkOffset >= 0) { 218 // already set 219 return ERROR_MALFORMED; 220 } 221 222 if (data_offset < 0) { 223 return ERROR_MALFORMED; 224 } 225 226 mSampleToChunkOffset = data_offset; 227 228 if (data_size < 8) { 229 return ERROR_MALFORMED; 230 } 231 232 uint8_t header[8]; 233 if (mDataSource->readAt( 234 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { 235 return ERROR_IO; 236 } 237 238 if (U32_AT(header) != 0) { 239 // Expected version = 0, flags = 0. 240 return ERROR_MALFORMED; 241 } 242 243 mNumSampleToChunkOffsets = U32_AT(&header[4]); 244 245 if ((data_size - 8) / sizeof(SampleToChunkEntry) < mNumSampleToChunkOffsets) { 246 return ERROR_MALFORMED; 247 } 248 249 if ((uint64_t)kMaxTotalSize / sizeof(SampleToChunkEntry) <= 250 (uint64_t)mNumSampleToChunkOffsets) { 251 ALOGE("Sample-to-chunk table size too large."); 252 return ERROR_OUT_OF_RANGE; 253 } 254 255 mTotalSize += (uint64_t)mNumSampleToChunkOffsets * 256 sizeof(SampleToChunkEntry); 257 if (mTotalSize > kMaxTotalSize) { 258 ALOGE("Sample-to-chunk table size would make sample table too large.\n" 259 " Requested sample-to-chunk table size = %llu\n" 260 " Eventual sample table size >= %llu\n" 261 " Allowed sample table size = %llu\n", 262 (unsigned long long)mNumSampleToChunkOffsets * 263 sizeof(SampleToChunkEntry), 264 (unsigned long long)mTotalSize, 265 (unsigned long long)kMaxTotalSize); 266 return ERROR_OUT_OF_RANGE; 267 } 268 269 mSampleToChunkEntries = 270 new (std::nothrow) SampleToChunkEntry[mNumSampleToChunkOffsets]; 271 if (!mSampleToChunkEntries) { 272 ALOGE("Cannot allocate sample-to-chunk table with %llu entries.", 273 (unsigned long long)mNumSampleToChunkOffsets); 274 return ERROR_OUT_OF_RANGE; 275 } 276 277 if (mNumSampleToChunkOffsets == 0) { 278 return OK; 279 } 280 281 if ((off64_t)(kMaxOffset - 8 - 282 ((mNumSampleToChunkOffsets - 1) * sizeof(SampleToChunkEntry))) 283 < mSampleToChunkOffset) { 284 return ERROR_MALFORMED; 285 } 286 287 for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) { 288 uint8_t buffer[sizeof(SampleToChunkEntry)]; 289 290 if (mDataSource->readAt( 291 mSampleToChunkOffset + 8 + i * sizeof(SampleToChunkEntry), 292 buffer, 293 sizeof(buffer)) 294 != (ssize_t)sizeof(buffer)) { 295 return ERROR_IO; 296 } 297 // chunk index is 1 based in the spec. 298 if (U32_AT(buffer) < 1) { 299 ALOGE("b/23534160"); 300 return ERROR_OUT_OF_RANGE; 301 } 302 303 // We want the chunk index to be 0-based. 304 mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1; 305 mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]); 306 mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]); 307 } 308 309 return OK; 310 } 311 312 status_t SampleTable::setSampleSizeParams( 313 uint32_t type, off64_t data_offset, size_t data_size) { 314 if (mSampleSizeOffset >= 0) { 315 return ERROR_MALFORMED; 316 } 317 318 CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact); 319 320 mSampleSizeOffset = data_offset; 321 322 if (data_size < 12) { 323 return ERROR_MALFORMED; 324 } 325 326 uint8_t header[12]; 327 if (mDataSource->readAt( 328 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { 329 return ERROR_IO; 330 } 331 332 if (U32_AT(header) != 0) { 333 // Expected version = 0, flags = 0. 334 return ERROR_MALFORMED; 335 } 336 337 mDefaultSampleSize = U32_AT(&header[4]); 338 mNumSampleSizes = U32_AT(&header[8]); 339 if (mNumSampleSizes > (UINT32_MAX - 12) / 16) { 340 ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes); 341 return ERROR_MALFORMED; 342 } 343 344 if (type == kSampleSizeType32) { 345 mSampleSizeFieldSize = 32; 346 347 if (mDefaultSampleSize != 0) { 348 return OK; 349 } 350 351 if (data_size < 12 + mNumSampleSizes * 4) { 352 return ERROR_MALFORMED; 353 } 354 } else { 355 if ((mDefaultSampleSize & 0xffffff00) != 0) { 356 // The high 24 bits are reserved and must be 0. 357 return ERROR_MALFORMED; 358 } 359 360 mSampleSizeFieldSize = mDefaultSampleSize & 0xff; 361 mDefaultSampleSize = 0; 362 363 if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8 364 && mSampleSizeFieldSize != 16) { 365 return ERROR_MALFORMED; 366 } 367 368 if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) { 369 return ERROR_MALFORMED; 370 } 371 } 372 373 return OK; 374 } 375 376 status_t SampleTable::setTimeToSampleParams( 377 off64_t data_offset, size_t data_size) { 378 if (mHasTimeToSample || data_size < 8) { 379 return ERROR_MALFORMED; 380 } 381 382 uint8_t header[8]; 383 if (mDataSource->readAt( 384 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { 385 return ERROR_IO; 386 } 387 388 if (U32_AT(header) != 0) { 389 // Expected version = 0, flags = 0. 390 return ERROR_MALFORMED; 391 } 392 393 mTimeToSampleCount = U32_AT(&header[4]); 394 if (mTimeToSampleCount > UINT32_MAX / (2 * sizeof(uint32_t))) { 395 // Choose this bound because 396 // 1) 2 * sizeof(uint32_t) is the amount of memory needed for one 397 // time-to-sample entry in the time-to-sample table. 398 // 2) mTimeToSampleCount is the number of entries of the time-to-sample 399 // table. 400 // 3) We hope that the table size does not exceed UINT32_MAX. 401 ALOGE("Time-to-sample table size too large."); 402 return ERROR_OUT_OF_RANGE; 403 } 404 405 // Note: At this point, we know that mTimeToSampleCount * 2 will not 406 // overflow because of the above condition. 407 408 uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t); 409 mTotalSize += allocSize; 410 if (mTotalSize > kMaxTotalSize) { 411 ALOGE("Time-to-sample table size would make sample table too large.\n" 412 " Requested time-to-sample table size = %llu\n" 413 " Eventual sample table size >= %llu\n" 414 " Allowed sample table size = %llu\n", 415 (unsigned long long)allocSize, 416 (unsigned long long)mTotalSize, 417 (unsigned long long)kMaxTotalSize); 418 return ERROR_OUT_OF_RANGE; 419 } 420 421 mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2]; 422 if (!mTimeToSample) { 423 ALOGE("Cannot allocate time-to-sample table with %llu entries.", 424 (unsigned long long)mTimeToSampleCount); 425 return ERROR_OUT_OF_RANGE; 426 } 427 428 if (mDataSource->readAt(data_offset + 8, mTimeToSample, 429 (size_t)allocSize) < (ssize_t)allocSize) { 430 ALOGE("Incomplete data read for time-to-sample table."); 431 return ERROR_IO; 432 } 433 434 for (size_t i = 0; i < mTimeToSampleCount * 2; ++i) { 435 mTimeToSample[i] = ntohl(mTimeToSample[i]); 436 } 437 438 mHasTimeToSample = true; 439 return OK; 440 } 441 442 // NOTE: per 14996-12, version 0 ctts contains unsigned values, while version 1 443 // contains signed values, however some software creates version 0 files that 444 // contain signed values, so we're always treating the values as signed, 445 // regardless of version. 446 status_t SampleTable::setCompositionTimeToSampleParams( 447 off64_t data_offset, size_t data_size) { 448 ALOGI("There are reordered frames present."); 449 450 if (mCompositionTimeDeltaEntries != NULL || data_size < 8) { 451 return ERROR_MALFORMED; 452 } 453 454 uint8_t header[8]; 455 if (mDataSource->readAt( 456 data_offset, header, sizeof(header)) 457 < (ssize_t)sizeof(header)) { 458 return ERROR_IO; 459 } 460 461 uint32_t flags = U32_AT(header); 462 uint32_t version = flags >> 24; 463 flags &= 0xffffff; 464 465 if ((version != 0 && version != 1) || flags != 0) { 466 // Expected version = 0 or 1, flags = 0. 467 return ERROR_MALFORMED; 468 } 469 470 size_t numEntries = U32_AT(&header[4]); 471 472 if (((SIZE_MAX / 8) - 1 < numEntries) || (data_size != (numEntries + 1) * 8)) { 473 return ERROR_MALFORMED; 474 } 475 476 mNumCompositionTimeDeltaEntries = numEntries; 477 uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(int32_t); 478 if (allocSize > kMaxTotalSize) { 479 ALOGE("Composition-time-to-sample table size too large."); 480 return ERROR_OUT_OF_RANGE; 481 } 482 483 mTotalSize += allocSize; 484 if (mTotalSize > kMaxTotalSize) { 485 ALOGE("Composition-time-to-sample table would make sample table too large.\n" 486 " Requested composition-time-to-sample table size = %llu\n" 487 " Eventual sample table size >= %llu\n" 488 " Allowed sample table size = %llu\n", 489 (unsigned long long)allocSize, 490 (unsigned long long)mTotalSize, 491 (unsigned long long)kMaxTotalSize); 492 return ERROR_OUT_OF_RANGE; 493 } 494 495 mCompositionTimeDeltaEntries = new (std::nothrow) int32_t[2 * numEntries]; 496 if (!mCompositionTimeDeltaEntries) { 497 ALOGE("Cannot allocate composition-time-to-sample table with %llu " 498 "entries.", (unsigned long long)numEntries); 499 return ERROR_OUT_OF_RANGE; 500 } 501 502 if (mDataSource->readAt(data_offset + 8, mCompositionTimeDeltaEntries, 503 (size_t)allocSize) < (ssize_t)allocSize) { 504 delete[] mCompositionTimeDeltaEntries; 505 mCompositionTimeDeltaEntries = NULL; 506 507 return ERROR_IO; 508 } 509 510 for (size_t i = 0; i < 2 * numEntries; ++i) { 511 mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]); 512 } 513 514 mCompositionDeltaLookup->setEntries( 515 mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries); 516 517 return OK; 518 } 519 520 status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) { 521 if (mSyncSampleOffset >= 0 || data_size < 8) { 522 return ERROR_MALFORMED; 523 } 524 525 uint8_t header[8]; 526 if (mDataSource->readAt( 527 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { 528 return ERROR_IO; 529 } 530 531 if (U32_AT(header) != 0) { 532 // Expected version = 0, flags = 0. 533 return ERROR_MALFORMED; 534 } 535 536 uint32_t numSyncSamples = U32_AT(&header[4]); 537 538 if (numSyncSamples < 2) { 539 ALOGV("Table of sync samples is empty or has only a single entry!"); 540 } 541 542 uint64_t allocSize = (uint64_t)numSyncSamples * sizeof(uint32_t); 543 if (allocSize > kMaxTotalSize) { 544 ALOGE("Sync sample table size too large."); 545 return ERROR_OUT_OF_RANGE; 546 } 547 548 mTotalSize += allocSize; 549 if (mTotalSize > kMaxTotalSize) { 550 ALOGE("Sync sample table size would make sample table too large.\n" 551 " Requested sync sample table size = %llu\n" 552 " Eventual sample table size >= %llu\n" 553 " Allowed sample table size = %llu\n", 554 (unsigned long long)allocSize, 555 (unsigned long long)mTotalSize, 556 (unsigned long long)kMaxTotalSize); 557 return ERROR_OUT_OF_RANGE; 558 } 559 560 mSyncSamples = new (std::nothrow) uint32_t[numSyncSamples]; 561 if (!mSyncSamples) { 562 ALOGE("Cannot allocate sync sample table with %llu entries.", 563 (unsigned long long)numSyncSamples); 564 return ERROR_OUT_OF_RANGE; 565 } 566 567 if (mDataSource->readAt(data_offset + 8, mSyncSamples, 568 (size_t)allocSize) != (ssize_t)allocSize) { 569 delete[] mSyncSamples; 570 mSyncSamples = NULL; 571 return ERROR_IO; 572 } 573 574 for (size_t i = 0; i < numSyncSamples; ++i) { 575 if (mSyncSamples[i] == 0) { 576 ALOGE("b/32423862, unexpected zero value in stss"); 577 continue; 578 } 579 mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1; 580 } 581 582 mSyncSampleOffset = data_offset; 583 mNumSyncSamples = numSyncSamples; 584 585 return OK; 586 } 587 588 uint32_t SampleTable::countChunkOffsets() const { 589 return mNumChunkOffsets; 590 } 591 592 uint32_t SampleTable::countSamples() const { 593 return mNumSampleSizes; 594 } 595 596 status_t SampleTable::getMaxSampleSize(size_t *max_size) { 597 Mutex::Autolock autoLock(mLock); 598 599 *max_size = 0; 600 601 for (uint32_t i = 0; i < mNumSampleSizes; ++i) { 602 size_t sample_size; 603 status_t err = getSampleSize_l(i, &sample_size); 604 605 if (err != OK) { 606 return err; 607 } 608 609 if (sample_size > *max_size) { 610 *max_size = sample_size; 611 } 612 } 613 614 return OK; 615 } 616 617 uint32_t abs_difference(uint64_t time1, uint64_t time2) { 618 return time1 > time2 ? time1 - time2 : time2 - time1; 619 } 620 621 // static 622 int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) { 623 const SampleTimeEntry *a = (const SampleTimeEntry *)_a; 624 const SampleTimeEntry *b = (const SampleTimeEntry *)_b; 625 626 if (a->mCompositionTime < b->mCompositionTime) { 627 return -1; 628 } else if (a->mCompositionTime > b->mCompositionTime) { 629 return 1; 630 } 631 632 return 0; 633 } 634 635 void SampleTable::buildSampleEntriesTable() { 636 Mutex::Autolock autoLock(mLock); 637 638 if (mSampleTimeEntries != NULL || mNumSampleSizes == 0) { 639 if (mNumSampleSizes == 0) { 640 ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes); 641 } 642 return; 643 } 644 645 mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry); 646 if (mTotalSize > kMaxTotalSize) { 647 ALOGE("Sample entry table size would make sample table too large.\n" 648 " Requested sample entry table size = %llu\n" 649 " Eventual sample table size >= %llu\n" 650 " Allowed sample table size = %llu\n", 651 (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry), 652 (unsigned long long)mTotalSize, 653 (unsigned long long)kMaxTotalSize); 654 return; 655 } 656 657 mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes]; 658 if (!mSampleTimeEntries) { 659 ALOGE("Cannot allocate sample entry table with %llu entries.", 660 (unsigned long long)mNumSampleSizes); 661 return; 662 } 663 664 uint32_t sampleIndex = 0; 665 uint64_t sampleTime = 0; 666 667 for (uint32_t i = 0; i < mTimeToSampleCount; ++i) { 668 uint32_t n = mTimeToSample[2 * i]; 669 uint32_t delta = mTimeToSample[2 * i + 1]; 670 671 for (uint32_t j = 0; j < n; ++j) { 672 if (sampleIndex < mNumSampleSizes) { 673 // Technically this should always be the case if the file 674 // is well-formed, but you know... there's (gasp) malformed 675 // content out there. 676 677 mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex; 678 679 int32_t compTimeDelta = 680 mCompositionDeltaLookup->getCompositionTimeOffset( 681 sampleIndex); 682 683 if ((compTimeDelta < 0 && sampleTime < 684 (compTimeDelta == INT32_MIN ? 685 INT32_MAX : uint32_t(-compTimeDelta))) 686 || (compTimeDelta > 0 && 687 sampleTime > UINT64_MAX - compTimeDelta)) { 688 ALOGE("%llu + %d would overflow, clamping", 689 (unsigned long long) sampleTime, compTimeDelta); 690 if (compTimeDelta < 0) { 691 sampleTime = 0; 692 } else { 693 sampleTime = UINT64_MAX; 694 } 695 compTimeDelta = 0; 696 } 697 698 mSampleTimeEntries[sampleIndex].mCompositionTime = 699 compTimeDelta > 0 ? sampleTime + compTimeDelta: 700 sampleTime - (-compTimeDelta); 701 } 702 703 ++sampleIndex; 704 if (sampleTime > UINT64_MAX - delta) { 705 ALOGE("%llu + %u would overflow, clamping", 706 (unsigned long long) sampleTime, delta); 707 sampleTime = UINT64_MAX; 708 } else { 709 sampleTime += delta; 710 } 711 } 712 } 713 714 qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry), 715 CompareIncreasingTime); 716 } 717 718 status_t SampleTable::findSampleAtTime( 719 uint64_t req_time, uint64_t scale_num, uint64_t scale_den, 720 uint32_t *sample_index, uint32_t flags) { 721 buildSampleEntriesTable(); 722 723 if (mSampleTimeEntries == NULL) { 724 return ERROR_OUT_OF_RANGE; 725 } 726 727 if (flags == kFlagFrameIndex) { 728 if (req_time >= mNumSampleSizes) { 729 return ERROR_OUT_OF_RANGE; 730 } 731 *sample_index = mSampleTimeEntries[req_time].mSampleIndex; 732 return OK; 733 } 734 735 uint32_t left = 0; 736 uint32_t right_plus_one = mNumSampleSizes; 737 while (left < right_plus_one) { 738 uint32_t center = left + (right_plus_one - left) / 2; 739 uint64_t centerTime = 740 getSampleTime(center, scale_num, scale_den); 741 742 if (req_time < centerTime) { 743 right_plus_one = center; 744 } else if (req_time > centerTime) { 745 left = center + 1; 746 } else { 747 *sample_index = mSampleTimeEntries[center].mSampleIndex; 748 return OK; 749 } 750 } 751 752 uint32_t closestIndex = left; 753 754 if (closestIndex == mNumSampleSizes) { 755 if (flags == kFlagAfter) { 756 return ERROR_OUT_OF_RANGE; 757 } 758 flags = kFlagBefore; 759 } else if (closestIndex == 0) { 760 if (flags == kFlagBefore) { 761 // normally we should return out of range, but that is 762 // treated as end-of-stream. instead return first sample 763 // 764 // return ERROR_OUT_OF_RANGE; 765 } 766 flags = kFlagAfter; 767 } 768 769 switch (flags) { 770 case kFlagBefore: 771 { 772 --closestIndex; 773 break; 774 } 775 776 case kFlagAfter: 777 { 778 // nothing to do 779 break; 780 } 781 782 default: 783 { 784 CHECK(flags == kFlagClosest); 785 // pick closest based on timestamp. use abs_difference for safety 786 if (abs_difference( 787 getSampleTime(closestIndex, scale_num, scale_den), req_time) > 788 abs_difference( 789 req_time, getSampleTime(closestIndex - 1, scale_num, scale_den))) { 790 --closestIndex; 791 } 792 break; 793 } 794 } 795 796 *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex; 797 return OK; 798 } 799 800 status_t SampleTable::findSyncSampleNear( 801 uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) { 802 Mutex::Autolock autoLock(mLock); 803 804 *sample_index = 0; 805 806 if (mSyncSampleOffset < 0) { 807 // All samples are sync-samples. 808 *sample_index = start_sample_index; 809 return OK; 810 } 811 812 if (mNumSyncSamples == 0) { 813 *sample_index = 0; 814 return OK; 815 } 816 817 uint32_t left = 0; 818 uint32_t right_plus_one = mNumSyncSamples; 819 while (left < right_plus_one) { 820 uint32_t center = left + (right_plus_one - left) / 2; 821 uint32_t x = mSyncSamples[center]; 822 823 if (start_sample_index < x) { 824 right_plus_one = center; 825 } else if (start_sample_index > x) { 826 left = center + 1; 827 } else { 828 *sample_index = x; 829 return OK; 830 } 831 } 832 833 if (left == mNumSyncSamples) { 834 if (flags == kFlagAfter) { 835 ALOGE("tried to find a sync frame after the last one: %d", left); 836 return ERROR_OUT_OF_RANGE; 837 } 838 flags = kFlagBefore; 839 } 840 else if (left == 0) { 841 if (flags == kFlagBefore) { 842 ALOGE("tried to find a sync frame before the first one: %d", left); 843 844 // normally we should return out of range, but that is 845 // treated as end-of-stream. instead seek to first sync 846 // 847 // return ERROR_OUT_OF_RANGE; 848 } 849 flags = kFlagAfter; 850 } 851 852 // Now ssi[left - 1] <(=) start_sample_index <= ssi[left] 853 switch (flags) { 854 case kFlagBefore: 855 { 856 --left; 857 break; 858 } 859 case kFlagAfter: 860 { 861 // nothing to do 862 break; 863 } 864 default: 865 { 866 // this route is not used, but implement it nonetheless 867 CHECK(flags == kFlagClosest); 868 869 status_t err = mSampleIterator->seekTo(start_sample_index); 870 if (err != OK) { 871 return err; 872 } 873 uint64_t sample_time = mSampleIterator->getSampleTime(); 874 875 err = mSampleIterator->seekTo(mSyncSamples[left]); 876 if (err != OK) { 877 return err; 878 } 879 uint64_t upper_time = mSampleIterator->getSampleTime(); 880 881 err = mSampleIterator->seekTo(mSyncSamples[left - 1]); 882 if (err != OK) { 883 return err; 884 } 885 uint64_t lower_time = mSampleIterator->getSampleTime(); 886 887 // use abs_difference for safety 888 if (abs_difference(upper_time, sample_time) > 889 abs_difference(sample_time, lower_time)) { 890 --left; 891 } 892 break; 893 } 894 } 895 896 *sample_index = mSyncSamples[left]; 897 return OK; 898 } 899 900 status_t SampleTable::findThumbnailSample(uint32_t *sample_index) { 901 Mutex::Autolock autoLock(mLock); 902 903 if (mSyncSampleOffset < 0) { 904 // All samples are sync-samples. 905 *sample_index = 0; 906 return OK; 907 } 908 909 uint32_t bestSampleIndex = 0; 910 size_t maxSampleSize = 0; 911 912 static const size_t kMaxNumSyncSamplesToScan = 20; 913 914 // Consider the first kMaxNumSyncSamplesToScan sync samples and 915 // pick the one with the largest (compressed) size as the thumbnail. 916 917 size_t numSamplesToScan = mNumSyncSamples; 918 if (numSamplesToScan > kMaxNumSyncSamplesToScan) { 919 numSamplesToScan = kMaxNumSyncSamplesToScan; 920 } 921 922 for (size_t i = 0; i < numSamplesToScan; ++i) { 923 uint32_t x = mSyncSamples[i]; 924 925 // Now x is a sample index. 926 size_t sampleSize; 927 status_t err = getSampleSize_l(x, &sampleSize); 928 if (err != OK) { 929 return err; 930 } 931 932 if (i == 0 || sampleSize > maxSampleSize) { 933 bestSampleIndex = x; 934 maxSampleSize = sampleSize; 935 } 936 } 937 938 *sample_index = bestSampleIndex; 939 940 return OK; 941 } 942 943 status_t SampleTable::getSampleSize_l( 944 uint32_t sampleIndex, size_t *sampleSize) { 945 return mSampleIterator->getSampleSizeDirect( 946 sampleIndex, sampleSize); 947 } 948 949 uint32_t SampleTable::getLastSampleIndexInChunk() { 950 Mutex::Autolock autoLock(mLock); 951 return mSampleIterator->getLastSampleIndexInChunk(); 952 } 953 954 status_t SampleTable::getMetaDataForSample( 955 uint32_t sampleIndex, 956 off64_t *offset, 957 size_t *size, 958 uint64_t *compositionTime, 959 bool *isSyncSample, 960 uint64_t *sampleDuration) { 961 Mutex::Autolock autoLock(mLock); 962 963 status_t err; 964 if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) { 965 return err; 966 } 967 968 if (offset) { 969 *offset = mSampleIterator->getSampleOffset(); 970 } 971 972 if (size) { 973 *size = mSampleIterator->getSampleSize(); 974 } 975 976 if (compositionTime) { 977 *compositionTime = mSampleIterator->getSampleTime(); 978 } 979 980 if (isSyncSample) { 981 *isSyncSample = false; 982 if (mSyncSampleOffset < 0) { 983 // Every sample is a sync sample. 984 *isSyncSample = true; 985 } else { 986 size_t i = (mLastSyncSampleIndex < mNumSyncSamples) 987 && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex) 988 ? mLastSyncSampleIndex : 0; 989 990 while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) { 991 ++i; 992 } 993 994 if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) { 995 *isSyncSample = true; 996 } 997 998 mLastSyncSampleIndex = i; 999 } 1000 } 1001 1002 if (sampleDuration) { 1003 *sampleDuration = mSampleIterator->getSampleDuration(); 1004 } 1005 1006 return OK; 1007 } 1008 1009 int32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) { 1010 return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex); 1011 } 1012 1013 } // namespace android 1014