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