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