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