SampleTable.cpp revision fdf0437ec1f80af98fc7a7406df8838ace6c58ba
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 mSyncSampleOffset = data_offset; 526 527 uint8_t header[8]; 528 if (mDataSource->readAt( 529 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { 530 return ERROR_IO; 531 } 532 533 if (U32_AT(header) != 0) { 534 // Expected version = 0, flags = 0. 535 return ERROR_MALFORMED; 536 } 537 538 mNumSyncSamples = U32_AT(&header[4]); 539 540 if (mNumSyncSamples < 2) { 541 ALOGV("Table of sync samples is empty or has only a single entry!"); 542 } 543 544 uint64_t allocSize = (uint64_t)mNumSyncSamples * sizeof(uint32_t); 545 if (allocSize > kMaxTotalSize) { 546 ALOGE("Sync sample table size too large."); 547 return ERROR_OUT_OF_RANGE; 548 } 549 550 mTotalSize += allocSize; 551 if (mTotalSize > kMaxTotalSize) { 552 ALOGE("Sync sample table size would make sample table too large.\n" 553 " Requested sync sample table size = %llu\n" 554 " Eventual sample table size >= %llu\n" 555 " Allowed sample table size = %llu\n", 556 (unsigned long long)allocSize, 557 (unsigned long long)mTotalSize, 558 (unsigned long long)kMaxTotalSize); 559 return ERROR_OUT_OF_RANGE; 560 } 561 562 mSyncSamples = new (std::nothrow) uint32_t[mNumSyncSamples]; 563 if (!mSyncSamples) { 564 ALOGE("Cannot allocate sync sample table with %llu entries.", 565 (unsigned long long)mNumSyncSamples); 566 return ERROR_OUT_OF_RANGE; 567 } 568 569 if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, 570 (size_t)allocSize) != (ssize_t)allocSize) { 571 return ERROR_IO; 572 } 573 574 for (size_t i = 0; i < mNumSyncSamples; ++i) { 575 mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1; 576 } 577 578 return OK; 579} 580 581uint32_t SampleTable::countChunkOffsets() const { 582 return mNumChunkOffsets; 583} 584 585uint32_t SampleTable::countSamples() const { 586 return mNumSampleSizes; 587} 588 589status_t SampleTable::getMaxSampleSize(size_t *max_size) { 590 Mutex::Autolock autoLock(mLock); 591 592 *max_size = 0; 593 594 for (uint32_t i = 0; i < mNumSampleSizes; ++i) { 595 size_t sample_size; 596 status_t err = getSampleSize_l(i, &sample_size); 597 598 if (err != OK) { 599 return err; 600 } 601 602 if (sample_size > *max_size) { 603 *max_size = sample_size; 604 } 605 } 606 607 return OK; 608} 609 610uint32_t abs_difference(uint32_t time1, uint32_t time2) { 611 return time1 > time2 ? time1 - time2 : time2 - time1; 612} 613 614// static 615int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) { 616 const SampleTimeEntry *a = (const SampleTimeEntry *)_a; 617 const SampleTimeEntry *b = (const SampleTimeEntry *)_b; 618 619 if (a->mCompositionTime < b->mCompositionTime) { 620 return -1; 621 } else if (a->mCompositionTime > b->mCompositionTime) { 622 return 1; 623 } 624 625 return 0; 626} 627 628void SampleTable::buildSampleEntriesTable() { 629 Mutex::Autolock autoLock(mLock); 630 631 if (mSampleTimeEntries != NULL || mNumSampleSizes == 0) { 632 if (mNumSampleSizes == 0) { 633 ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes); 634 } 635 return; 636 } 637 638 mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry); 639 if (mTotalSize > kMaxTotalSize) { 640 ALOGE("Sample entry table size would make sample table too large.\n" 641 " Requested sample entry table size = %llu\n" 642 " Eventual sample table size >= %llu\n" 643 " Allowed sample table size = %llu\n", 644 (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry), 645 (unsigned long long)mTotalSize, 646 (unsigned long long)kMaxTotalSize); 647 return; 648 } 649 650 mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes]; 651 if (!mSampleTimeEntries) { 652 ALOGE("Cannot allocate sample entry table with %llu entries.", 653 (unsigned long long)mNumSampleSizes); 654 return; 655 } 656 657 uint32_t sampleIndex = 0; 658 uint32_t sampleTime = 0; 659 660 for (uint32_t i = 0; i < mTimeToSampleCount; ++i) { 661 uint32_t n = mTimeToSample[2 * i]; 662 uint32_t delta = mTimeToSample[2 * i + 1]; 663 664 for (uint32_t j = 0; j < n; ++j) { 665 if (sampleIndex < mNumSampleSizes) { 666 // Technically this should always be the case if the file 667 // is well-formed, but you know... there's (gasp) malformed 668 // content out there. 669 670 mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex; 671 672 int32_t compTimeDelta = 673 mCompositionDeltaLookup->getCompositionTimeOffset( 674 sampleIndex); 675 676 if ((compTimeDelta < 0 && sampleTime < 677 (compTimeDelta == INT32_MIN ? 678 INT32_MAX : uint32_t(-compTimeDelta))) 679 || (compTimeDelta > 0 && 680 sampleTime > UINT32_MAX - compTimeDelta)) { 681 ALOGE("%u + %d would overflow, clamping", 682 sampleTime, compTimeDelta); 683 if (compTimeDelta < 0) { 684 sampleTime = 0; 685 } else { 686 sampleTime = UINT32_MAX; 687 } 688 compTimeDelta = 0; 689 } 690 691 mSampleTimeEntries[sampleIndex].mCompositionTime = 692 compTimeDelta > 0 ? sampleTime + compTimeDelta: 693 sampleTime - (-compTimeDelta); 694 } 695 696 ++sampleIndex; 697 sampleTime += delta; 698 } 699 } 700 701 qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry), 702 CompareIncreasingTime); 703} 704 705status_t SampleTable::findSampleAtTime( 706 uint64_t req_time, uint64_t scale_num, uint64_t scale_den, 707 uint32_t *sample_index, uint32_t flags) { 708 buildSampleEntriesTable(); 709 710 if (mSampleTimeEntries == NULL) { 711 return ERROR_OUT_OF_RANGE; 712 } 713 714 uint32_t left = 0; 715 uint32_t right_plus_one = mNumSampleSizes; 716 while (left < right_plus_one) { 717 uint32_t center = left + (right_plus_one - left) / 2; 718 uint64_t centerTime = 719 getSampleTime(center, scale_num, scale_den); 720 721 if (req_time < centerTime) { 722 right_plus_one = center; 723 } else if (req_time > centerTime) { 724 left = center + 1; 725 } else { 726 *sample_index = mSampleTimeEntries[center].mSampleIndex; 727 return OK; 728 } 729 } 730 731 uint32_t closestIndex = left; 732 733 if (closestIndex == mNumSampleSizes) { 734 if (flags == kFlagAfter) { 735 return ERROR_OUT_OF_RANGE; 736 } 737 flags = kFlagBefore; 738 } else if (closestIndex == 0) { 739 if (flags == kFlagBefore) { 740 // normally we should return out of range, but that is 741 // treated as end-of-stream. instead return first sample 742 // 743 // return ERROR_OUT_OF_RANGE; 744 } 745 flags = kFlagAfter; 746 } 747 748 switch (flags) { 749 case kFlagBefore: 750 { 751 --closestIndex; 752 break; 753 } 754 755 case kFlagAfter: 756 { 757 // nothing to do 758 break; 759 } 760 761 default: 762 { 763 CHECK(flags == kFlagClosest); 764 // pick closest based on timestamp. use abs_difference for safety 765 if (abs_difference( 766 getSampleTime(closestIndex, scale_num, scale_den), req_time) > 767 abs_difference( 768 req_time, getSampleTime(closestIndex - 1, scale_num, scale_den))) { 769 --closestIndex; 770 } 771 break; 772 } 773 } 774 775 *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex; 776 return OK; 777} 778 779status_t SampleTable::findSyncSampleNear( 780 uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) { 781 Mutex::Autolock autoLock(mLock); 782 783 *sample_index = 0; 784 785 if (mSyncSampleOffset < 0) { 786 // All samples are sync-samples. 787 *sample_index = start_sample_index; 788 return OK; 789 } 790 791 if (mNumSyncSamples == 0) { 792 *sample_index = 0; 793 return OK; 794 } 795 796 uint32_t left = 0; 797 uint32_t right_plus_one = mNumSyncSamples; 798 while (left < right_plus_one) { 799 uint32_t center = left + (right_plus_one - left) / 2; 800 uint32_t x = mSyncSamples[center]; 801 802 if (start_sample_index < x) { 803 right_plus_one = center; 804 } else if (start_sample_index > x) { 805 left = center + 1; 806 } else { 807 *sample_index = x; 808 return OK; 809 } 810 } 811 812 if (left == mNumSyncSamples) { 813 if (flags == kFlagAfter) { 814 ALOGE("tried to find a sync frame after the last one: %d", left); 815 return ERROR_OUT_OF_RANGE; 816 } 817 flags = kFlagBefore; 818 } 819 else if (left == 0) { 820 if (flags == kFlagBefore) { 821 ALOGE("tried to find a sync frame before the first one: %d", left); 822 823 // normally we should return out of range, but that is 824 // treated as end-of-stream. instead seek to first sync 825 // 826 // return ERROR_OUT_OF_RANGE; 827 } 828 flags = kFlagAfter; 829 } 830 831 // Now ssi[left - 1] <(=) start_sample_index <= ssi[left] 832 switch (flags) { 833 case kFlagBefore: 834 { 835 --left; 836 break; 837 } 838 case kFlagAfter: 839 { 840 // nothing to do 841 break; 842 } 843 default: 844 { 845 // this route is not used, but implement it nonetheless 846 CHECK(flags == kFlagClosest); 847 848 status_t err = mSampleIterator->seekTo(start_sample_index); 849 if (err != OK) { 850 return err; 851 } 852 uint32_t sample_time = mSampleIterator->getSampleTime(); 853 854 err = mSampleIterator->seekTo(mSyncSamples[left]); 855 if (err != OK) { 856 return err; 857 } 858 uint32_t upper_time = mSampleIterator->getSampleTime(); 859 860 err = mSampleIterator->seekTo(mSyncSamples[left - 1]); 861 if (err != OK) { 862 return err; 863 } 864 uint32_t lower_time = mSampleIterator->getSampleTime(); 865 866 // use abs_difference for safety 867 if (abs_difference(upper_time, sample_time) > 868 abs_difference(sample_time, lower_time)) { 869 --left; 870 } 871 break; 872 } 873 } 874 875 *sample_index = mSyncSamples[left]; 876 return OK; 877} 878 879status_t SampleTable::findThumbnailSample(uint32_t *sample_index) { 880 Mutex::Autolock autoLock(mLock); 881 882 if (mSyncSampleOffset < 0) { 883 // All samples are sync-samples. 884 *sample_index = 0; 885 return OK; 886 } 887 888 uint32_t bestSampleIndex = 0; 889 size_t maxSampleSize = 0; 890 891 static const size_t kMaxNumSyncSamplesToScan = 20; 892 893 // Consider the first kMaxNumSyncSamplesToScan sync samples and 894 // pick the one with the largest (compressed) size as the thumbnail. 895 896 size_t numSamplesToScan = mNumSyncSamples; 897 if (numSamplesToScan > kMaxNumSyncSamplesToScan) { 898 numSamplesToScan = kMaxNumSyncSamplesToScan; 899 } 900 901 for (size_t i = 0; i < numSamplesToScan; ++i) { 902 uint32_t x = mSyncSamples[i]; 903 904 // Now x is a sample index. 905 size_t sampleSize; 906 status_t err = getSampleSize_l(x, &sampleSize); 907 if (err != OK) { 908 return err; 909 } 910 911 if (i == 0 || sampleSize > maxSampleSize) { 912 bestSampleIndex = x; 913 maxSampleSize = sampleSize; 914 } 915 } 916 917 *sample_index = bestSampleIndex; 918 919 return OK; 920} 921 922status_t SampleTable::getSampleSize_l( 923 uint32_t sampleIndex, size_t *sampleSize) { 924 return mSampleIterator->getSampleSizeDirect( 925 sampleIndex, sampleSize); 926} 927 928status_t SampleTable::getMetaDataForSample( 929 uint32_t sampleIndex, 930 off64_t *offset, 931 size_t *size, 932 uint32_t *compositionTime, 933 bool *isSyncSample, 934 uint32_t *sampleDuration) { 935 Mutex::Autolock autoLock(mLock); 936 937 status_t err; 938 if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) { 939 return err; 940 } 941 942 if (offset) { 943 *offset = mSampleIterator->getSampleOffset(); 944 } 945 946 if (size) { 947 *size = mSampleIterator->getSampleSize(); 948 } 949 950 if (compositionTime) { 951 *compositionTime = mSampleIterator->getSampleTime(); 952 } 953 954 if (isSyncSample) { 955 *isSyncSample = false; 956 if (mSyncSampleOffset < 0) { 957 // Every sample is a sync sample. 958 *isSyncSample = true; 959 } else { 960 size_t i = (mLastSyncSampleIndex < mNumSyncSamples) 961 && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex) 962 ? mLastSyncSampleIndex : 0; 963 964 while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) { 965 ++i; 966 } 967 968 if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) { 969 *isSyncSample = true; 970 } 971 972 mLastSyncSampleIndex = i; 973 } 974 } 975 976 if (sampleDuration) { 977 *sampleDuration = mSampleIterator->getSampleDuration(); 978 } 979 980 return OK; 981} 982 983int32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) { 984 return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex); 985} 986 987} // namespace android 988 989