SampleTable.cpp revision 6bf40ddf1c484404a70c3217ebfb47ce504d9f93
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 "include/SampleTable.h" 24#include "include/SampleIterator.h" 25 26#include <arpa/inet.h> 27 28#include <media/stagefright/foundation/ADebug.h> 29#include <media/stagefright/DataSource.h> 30#include <media/stagefright/Utils.h> 31 32/* TODO: remove after being merged into other branches */ 33#ifndef UINT32_MAX 34#define UINT32_MAX (4294967295U) 35#endif 36 37namespace android { 38 39// static 40const uint32_t SampleTable::kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o'); 41// static 42const uint32_t SampleTable::kChunkOffsetType64 = FOURCC('c', 'o', '6', '4'); 43// static 44const uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z'); 45// static 46const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2'); 47 48//////////////////////////////////////////////////////////////////////////////// 49 50const off64_t kMaxOffset = std::numeric_limits<off64_t>::max(); 51 52struct 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 60private: 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 72SampleTable::CompositionDeltaLookup::CompositionDeltaLookup() 73 : mDeltaEntries(NULL), 74 mNumDeltaEntries(0), 75 mCurrentDeltaEntry(0), 76 mCurrentEntrySampleIndex(0) { 77} 78 79void 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 89int32_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 117SampleTable::SampleTable(const sp<DataSource> &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 144SampleTable::~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 167bool SampleTable::isValid() const { 168 return mChunkOffsetOffset >= 0 169 && mSampleToChunkOffset >= 0 170 && mSampleSizeOffset >= 0 171 && mHasTimeToSample; 172} 173 174status_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 215status_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 312status_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 376status_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. 446status_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 520status_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 588uint32_t SampleTable::countChunkOffsets() const { 589 return mNumChunkOffsets; 590} 591 592uint32_t SampleTable::countSamples() const { 593 return mNumSampleSizes; 594} 595 596status_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 617uint32_t abs_difference(uint32_t time1, uint32_t time2) { 618 return time1 > time2 ? time1 - time2 : time2 - time1; 619} 620 621// static 622int 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 635void 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 uint32_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 > UINT32_MAX - compTimeDelta)) { 688 ALOGE("%u + %d would overflow, clamping", 689 sampleTime, compTimeDelta); 690 if (compTimeDelta < 0) { 691 sampleTime = 0; 692 } else { 693 sampleTime = UINT32_MAX; 694 } 695 compTimeDelta = 0; 696 } 697 698 mSampleTimeEntries[sampleIndex].mCompositionTime = 699 compTimeDelta > 0 ? sampleTime + compTimeDelta: 700 sampleTime - (-compTimeDelta); 701 } 702 703 ++sampleIndex; 704 sampleTime += delta; 705 } 706 } 707 708 qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry), 709 CompareIncreasingTime); 710} 711 712status_t SampleTable::findSampleAtTime( 713 uint64_t req_time, uint64_t scale_num, uint64_t scale_den, 714 uint32_t *sample_index, uint32_t flags) { 715 buildSampleEntriesTable(); 716 717 if (mSampleTimeEntries == NULL) { 718 return ERROR_OUT_OF_RANGE; 719 } 720 721 uint32_t left = 0; 722 uint32_t right_plus_one = mNumSampleSizes; 723 while (left < right_plus_one) { 724 uint32_t center = left + (right_plus_one - left) / 2; 725 uint64_t centerTime = 726 getSampleTime(center, scale_num, scale_den); 727 728 if (req_time < centerTime) { 729 right_plus_one = center; 730 } else if (req_time > centerTime) { 731 left = center + 1; 732 } else { 733 *sample_index = mSampleTimeEntries[center].mSampleIndex; 734 return OK; 735 } 736 } 737 738 uint32_t closestIndex = left; 739 740 if (closestIndex == mNumSampleSizes) { 741 if (flags == kFlagAfter) { 742 return ERROR_OUT_OF_RANGE; 743 } 744 flags = kFlagBefore; 745 } else if (closestIndex == 0) { 746 if (flags == kFlagBefore) { 747 // normally we should return out of range, but that is 748 // treated as end-of-stream. instead return first sample 749 // 750 // return ERROR_OUT_OF_RANGE; 751 } 752 flags = kFlagAfter; 753 } 754 755 switch (flags) { 756 case kFlagBefore: 757 { 758 --closestIndex; 759 break; 760 } 761 762 case kFlagAfter: 763 { 764 // nothing to do 765 break; 766 } 767 768 default: 769 { 770 CHECK(flags == kFlagClosest); 771 // pick closest based on timestamp. use abs_difference for safety 772 if (abs_difference( 773 getSampleTime(closestIndex, scale_num, scale_den), req_time) > 774 abs_difference( 775 req_time, getSampleTime(closestIndex - 1, scale_num, scale_den))) { 776 --closestIndex; 777 } 778 break; 779 } 780 } 781 782 *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex; 783 return OK; 784} 785 786status_t SampleTable::findSyncSampleNear( 787 uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) { 788 Mutex::Autolock autoLock(mLock); 789 790 *sample_index = 0; 791 792 if (mSyncSampleOffset < 0) { 793 // All samples are sync-samples. 794 *sample_index = start_sample_index; 795 return OK; 796 } 797 798 if (mNumSyncSamples == 0) { 799 *sample_index = 0; 800 return OK; 801 } 802 803 uint32_t left = 0; 804 uint32_t right_plus_one = mNumSyncSamples; 805 while (left < right_plus_one) { 806 uint32_t center = left + (right_plus_one - left) / 2; 807 uint32_t x = mSyncSamples[center]; 808 809 if (start_sample_index < x) { 810 right_plus_one = center; 811 } else if (start_sample_index > x) { 812 left = center + 1; 813 } else { 814 *sample_index = x; 815 return OK; 816 } 817 } 818 819 if (left == mNumSyncSamples) { 820 if (flags == kFlagAfter) { 821 ALOGE("tried to find a sync frame after the last one: %d", left); 822 return ERROR_OUT_OF_RANGE; 823 } 824 flags = kFlagBefore; 825 } 826 else if (left == 0) { 827 if (flags == kFlagBefore) { 828 ALOGE("tried to find a sync frame before the first one: %d", left); 829 830 // normally we should return out of range, but that is 831 // treated as end-of-stream. instead seek to first sync 832 // 833 // return ERROR_OUT_OF_RANGE; 834 } 835 flags = kFlagAfter; 836 } 837 838 // Now ssi[left - 1] <(=) start_sample_index <= ssi[left] 839 switch (flags) { 840 case kFlagBefore: 841 { 842 --left; 843 break; 844 } 845 case kFlagAfter: 846 { 847 // nothing to do 848 break; 849 } 850 default: 851 { 852 // this route is not used, but implement it nonetheless 853 CHECK(flags == kFlagClosest); 854 855 status_t err = mSampleIterator->seekTo(start_sample_index); 856 if (err != OK) { 857 return err; 858 } 859 uint32_t sample_time = mSampleIterator->getSampleTime(); 860 861 err = mSampleIterator->seekTo(mSyncSamples[left]); 862 if (err != OK) { 863 return err; 864 } 865 uint32_t upper_time = mSampleIterator->getSampleTime(); 866 867 err = mSampleIterator->seekTo(mSyncSamples[left - 1]); 868 if (err != OK) { 869 return err; 870 } 871 uint32_t lower_time = mSampleIterator->getSampleTime(); 872 873 // use abs_difference for safety 874 if (abs_difference(upper_time, sample_time) > 875 abs_difference(sample_time, lower_time)) { 876 --left; 877 } 878 break; 879 } 880 } 881 882 *sample_index = mSyncSamples[left]; 883 return OK; 884} 885 886status_t SampleTable::findThumbnailSample(uint32_t *sample_index) { 887 Mutex::Autolock autoLock(mLock); 888 889 if (mSyncSampleOffset < 0) { 890 // All samples are sync-samples. 891 *sample_index = 0; 892 return OK; 893 } 894 895 uint32_t bestSampleIndex = 0; 896 size_t maxSampleSize = 0; 897 898 static const size_t kMaxNumSyncSamplesToScan = 20; 899 900 // Consider the first kMaxNumSyncSamplesToScan sync samples and 901 // pick the one with the largest (compressed) size as the thumbnail. 902 903 size_t numSamplesToScan = mNumSyncSamples; 904 if (numSamplesToScan > kMaxNumSyncSamplesToScan) { 905 numSamplesToScan = kMaxNumSyncSamplesToScan; 906 } 907 908 for (size_t i = 0; i < numSamplesToScan; ++i) { 909 uint32_t x = mSyncSamples[i]; 910 911 // Now x is a sample index. 912 size_t sampleSize; 913 status_t err = getSampleSize_l(x, &sampleSize); 914 if (err != OK) { 915 return err; 916 } 917 918 if (i == 0 || sampleSize > maxSampleSize) { 919 bestSampleIndex = x; 920 maxSampleSize = sampleSize; 921 } 922 } 923 924 *sample_index = bestSampleIndex; 925 926 return OK; 927} 928 929status_t SampleTable::getSampleSize_l( 930 uint32_t sampleIndex, size_t *sampleSize) { 931 return mSampleIterator->getSampleSizeDirect( 932 sampleIndex, sampleSize); 933} 934 935status_t SampleTable::getMetaDataForSample( 936 uint32_t sampleIndex, 937 off64_t *offset, 938 size_t *size, 939 uint32_t *compositionTime, 940 bool *isSyncSample, 941 uint32_t *sampleDuration) { 942 Mutex::Autolock autoLock(mLock); 943 944 status_t err; 945 if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) { 946 return err; 947 } 948 949 if (offset) { 950 *offset = mSampleIterator->getSampleOffset(); 951 } 952 953 if (size) { 954 *size = mSampleIterator->getSampleSize(); 955 } 956 957 if (compositionTime) { 958 *compositionTime = mSampleIterator->getSampleTime(); 959 } 960 961 if (isSyncSample) { 962 *isSyncSample = false; 963 if (mSyncSampleOffset < 0) { 964 // Every sample is a sync sample. 965 *isSyncSample = true; 966 } else { 967 size_t i = (mLastSyncSampleIndex < mNumSyncSamples) 968 && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex) 969 ? mLastSyncSampleIndex : 0; 970 971 while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) { 972 ++i; 973 } 974 975 if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) { 976 *isSyncSample = true; 977 } 978 979 mLastSyncSampleIndex = i; 980 } 981 } 982 983 if (sampleDuration) { 984 *sampleDuration = mSampleIterator->getSampleDuration(); 985 } 986 987 return OK; 988} 989 990int32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) { 991 return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex); 992} 993 994} // namespace android 995 996