SampleTable.cpp revision 17b625b7f51b75fde6640c737474b8b2c51412bf
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 30namespace android { 31 32// static 33const uint32_t SampleTable::kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o'); 34// static 35const uint32_t SampleTable::kChunkOffsetType64 = FOURCC('c', 'o', '6', '4'); 36// static 37const uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z'); 38// static 39const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2'); 40 41//////////////////////////////////////////////////////////////////////////////// 42 43struct SampleTable::CompositionDeltaLookup { 44 CompositionDeltaLookup(); 45 46 void setEntries( 47 const uint32_t *deltaEntries, size_t numDeltaEntries); 48 49 uint32_t getCompositionTimeOffset(uint32_t sampleIndex); 50 51private: 52 Mutex mLock; 53 54 const uint32_t *mDeltaEntries; 55 size_t mNumDeltaEntries; 56 57 size_t mCurrentDeltaEntry; 58 size_t mCurrentEntrySampleIndex; 59 60 DISALLOW_EVIL_CONSTRUCTORS(CompositionDeltaLookup); 61}; 62 63SampleTable::CompositionDeltaLookup::CompositionDeltaLookup() 64 : mDeltaEntries(NULL), 65 mNumDeltaEntries(0), 66 mCurrentDeltaEntry(0), 67 mCurrentEntrySampleIndex(0) { 68} 69 70void SampleTable::CompositionDeltaLookup::setEntries( 71 const uint32_t *deltaEntries, size_t numDeltaEntries) { 72 Mutex::Autolock autolock(mLock); 73 74 mDeltaEntries = deltaEntries; 75 mNumDeltaEntries = numDeltaEntries; 76 mCurrentDeltaEntry = 0; 77 mCurrentEntrySampleIndex = 0; 78} 79 80uint32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset( 81 uint32_t sampleIndex) { 82 Mutex::Autolock autolock(mLock); 83 84 if (mDeltaEntries == NULL) { 85 return 0; 86 } 87 88 if (sampleIndex < mCurrentEntrySampleIndex) { 89 mCurrentDeltaEntry = 0; 90 mCurrentEntrySampleIndex = 0; 91 } 92 93 while (mCurrentDeltaEntry < mNumDeltaEntries) { 94 uint32_t sampleCount = mDeltaEntries[2 * mCurrentDeltaEntry]; 95 if (sampleIndex < mCurrentEntrySampleIndex + sampleCount) { 96 return mDeltaEntries[2 * mCurrentDeltaEntry + 1]; 97 } 98 99 mCurrentEntrySampleIndex += sampleCount; 100 ++mCurrentDeltaEntry; 101 } 102 103 return 0; 104} 105 106//////////////////////////////////////////////////////////////////////////////// 107 108SampleTable::SampleTable(const sp<DataSource> &source) 109 : mDataSource(source), 110 mChunkOffsetOffset(-1), 111 mChunkOffsetType(0), 112 mNumChunkOffsets(0), 113 mSampleToChunkOffset(-1), 114 mNumSampleToChunkOffsets(0), 115 mSampleSizeOffset(-1), 116 mSampleSizeFieldSize(0), 117 mDefaultSampleSize(0), 118 mNumSampleSizes(0), 119 mTimeToSampleCount(0), 120 mTimeToSample(NULL), 121 mSampleTimeEntries(NULL), 122 mCompositionTimeDeltaEntries(NULL), 123 mNumCompositionTimeDeltaEntries(0), 124 mCompositionDeltaLookup(new CompositionDeltaLookup), 125 mSyncSampleOffset(-1), 126 mNumSyncSamples(0), 127 mSyncSamples(NULL), 128 mLastSyncSampleIndex(0), 129 mSampleToChunkEntries(NULL) { 130 mSampleIterator = new SampleIterator(this); 131} 132 133SampleTable::~SampleTable() { 134 delete[] mSampleToChunkEntries; 135 mSampleToChunkEntries = NULL; 136 137 delete[] mSyncSamples; 138 mSyncSamples = NULL; 139 140 delete mCompositionDeltaLookup; 141 mCompositionDeltaLookup = NULL; 142 143 delete[] mCompositionTimeDeltaEntries; 144 mCompositionTimeDeltaEntries = NULL; 145 146 delete[] mSampleTimeEntries; 147 mSampleTimeEntries = NULL; 148 149 delete[] mTimeToSample; 150 mTimeToSample = NULL; 151 152 delete mSampleIterator; 153 mSampleIterator = NULL; 154} 155 156bool SampleTable::isValid() const { 157 return mChunkOffsetOffset >= 0 158 && mSampleToChunkOffset >= 0 159 && mSampleSizeOffset >= 0 160 && mTimeToSample != NULL; 161} 162 163status_t SampleTable::setChunkOffsetParams( 164 uint32_t type, off64_t data_offset, size_t data_size) { 165 if (mChunkOffsetOffset >= 0) { 166 return ERROR_MALFORMED; 167 } 168 169 CHECK(type == kChunkOffsetType32 || type == kChunkOffsetType64); 170 171 mChunkOffsetOffset = data_offset; 172 mChunkOffsetType = type; 173 174 if (data_size < 8) { 175 return ERROR_MALFORMED; 176 } 177 178 uint8_t header[8]; 179 if (mDataSource->readAt( 180 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { 181 return ERROR_IO; 182 } 183 184 if (U32_AT(header) != 0) { 185 // Expected version = 0, flags = 0. 186 return ERROR_MALFORMED; 187 } 188 189 mNumChunkOffsets = U32_AT(&header[4]); 190 191 if (mChunkOffsetType == kChunkOffsetType32) { 192 if (data_size < 8 + mNumChunkOffsets * 4) { 193 return ERROR_MALFORMED; 194 } 195 } else { 196 if (data_size < 8 + mNumChunkOffsets * 8) { 197 return ERROR_MALFORMED; 198 } 199 } 200 201 return OK; 202} 203 204status_t SampleTable::setSampleToChunkParams( 205 off64_t data_offset, size_t data_size) { 206 if (mSampleToChunkOffset >= 0) { 207 return ERROR_MALFORMED; 208 } 209 210 mSampleToChunkOffset = data_offset; 211 212 if (data_size < 8) { 213 return ERROR_MALFORMED; 214 } 215 216 uint8_t header[8]; 217 if (mDataSource->readAt( 218 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { 219 return ERROR_IO; 220 } 221 222 if (U32_AT(header) != 0) { 223 // Expected version = 0, flags = 0. 224 return ERROR_MALFORMED; 225 } 226 227 mNumSampleToChunkOffsets = U32_AT(&header[4]); 228 229 if (data_size < 8 + mNumSampleToChunkOffsets * 12) { 230 return ERROR_MALFORMED; 231 } 232 233 if (SIZE_MAX / sizeof(SampleToChunkEntry) <= mNumSampleToChunkOffsets) 234 return ERROR_OUT_OF_RANGE; 235 236 mSampleToChunkEntries = 237 new SampleToChunkEntry[mNumSampleToChunkOffsets]; 238 239 for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) { 240 uint8_t buffer[12]; 241 if (mDataSource->readAt( 242 mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer)) 243 != (ssize_t)sizeof(buffer)) { 244 return ERROR_IO; 245 } 246 247 CHECK(U32_AT(buffer) >= 1); // chunk index is 1 based in the spec. 248 249 // We want the chunk index to be 0-based. 250 mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1; 251 mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]); 252 mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]); 253 } 254 255 return OK; 256} 257 258status_t SampleTable::setSampleSizeParams( 259 uint32_t type, off64_t data_offset, size_t data_size) { 260 if (mSampleSizeOffset >= 0) { 261 return ERROR_MALFORMED; 262 } 263 264 CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact); 265 266 mSampleSizeOffset = data_offset; 267 268 if (data_size < 12) { 269 return ERROR_MALFORMED; 270 } 271 272 uint8_t header[12]; 273 if (mDataSource->readAt( 274 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { 275 return ERROR_IO; 276 } 277 278 if (U32_AT(header) != 0) { 279 // Expected version = 0, flags = 0. 280 return ERROR_MALFORMED; 281 } 282 283 mDefaultSampleSize = U32_AT(&header[4]); 284 mNumSampleSizes = U32_AT(&header[8]); 285 286 if (type == kSampleSizeType32) { 287 mSampleSizeFieldSize = 32; 288 289 if (mDefaultSampleSize != 0) { 290 return OK; 291 } 292 293 if (data_size < 12 + mNumSampleSizes * 4) { 294 return ERROR_MALFORMED; 295 } 296 } else { 297 if ((mDefaultSampleSize & 0xffffff00) != 0) { 298 // The high 24 bits are reserved and must be 0. 299 return ERROR_MALFORMED; 300 } 301 302 mSampleSizeFieldSize = mDefaultSampleSize & 0xff; 303 mDefaultSampleSize = 0; 304 305 if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8 306 && mSampleSizeFieldSize != 16) { 307 return ERROR_MALFORMED; 308 } 309 310 if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) { 311 return ERROR_MALFORMED; 312 } 313 } 314 315 return OK; 316} 317 318status_t SampleTable::setTimeToSampleParams( 319 off64_t data_offset, size_t data_size) { 320 if (mTimeToSample != NULL || data_size < 8) { 321 return ERROR_MALFORMED; 322 } 323 324 uint8_t header[8]; 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 mTimeToSampleCount = U32_AT(&header[4]); 336 uint64_t allocSize = mTimeToSampleCount * 2 * (uint64_t)sizeof(uint32_t); 337 if (allocSize > SIZE_MAX) { 338 return ERROR_OUT_OF_RANGE; 339 } 340 mTimeToSample = new uint32_t[mTimeToSampleCount * 2]; 341 342 size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2; 343 if (mDataSource->readAt( 344 data_offset + 8, mTimeToSample, size) < (ssize_t)size) { 345 return ERROR_IO; 346 } 347 348 for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) { 349 mTimeToSample[i] = ntohl(mTimeToSample[i]); 350 } 351 352 return OK; 353} 354 355status_t SampleTable::setCompositionTimeToSampleParams( 356 off64_t data_offset, size_t data_size) { 357 ALOGI("There are reordered frames present."); 358 359 if (mCompositionTimeDeltaEntries != NULL || data_size < 8) { 360 return ERROR_MALFORMED; 361 } 362 363 uint8_t header[8]; 364 if (mDataSource->readAt( 365 data_offset, header, sizeof(header)) 366 < (ssize_t)sizeof(header)) { 367 return ERROR_IO; 368 } 369 370 if (U32_AT(header) != 0) { 371 // Expected version = 0, flags = 0. 372 return ERROR_MALFORMED; 373 } 374 375 size_t numEntries = U32_AT(&header[4]); 376 377 if (data_size != (numEntries + 1) * 8) { 378 return ERROR_MALFORMED; 379 } 380 381 mNumCompositionTimeDeltaEntries = numEntries; 382 uint64_t allocSize = numEntries * 2 * (uint64_t)sizeof(uint32_t); 383 if (allocSize > SIZE_MAX) { 384 return ERROR_OUT_OF_RANGE; 385 } 386 387 mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries]; 388 389 if (mDataSource->readAt( 390 data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8) 391 < (ssize_t)numEntries * 8) { 392 delete[] mCompositionTimeDeltaEntries; 393 mCompositionTimeDeltaEntries = NULL; 394 395 return ERROR_IO; 396 } 397 398 for (size_t i = 0; i < 2 * numEntries; ++i) { 399 mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]); 400 } 401 402 mCompositionDeltaLookup->setEntries( 403 mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries); 404 405 return OK; 406} 407 408status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) { 409 if (mSyncSampleOffset >= 0 || data_size < 8) { 410 return ERROR_MALFORMED; 411 } 412 413 mSyncSampleOffset = data_offset; 414 415 uint8_t header[8]; 416 if (mDataSource->readAt( 417 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { 418 return ERROR_IO; 419 } 420 421 if (U32_AT(header) != 0) { 422 // Expected version = 0, flags = 0. 423 return ERROR_MALFORMED; 424 } 425 426 mNumSyncSamples = U32_AT(&header[4]); 427 428 if (mNumSyncSamples < 2) { 429 ALOGV("Table of sync samples is empty or has only a single entry!"); 430 } 431 432 uint64_t allocSize = mNumSyncSamples * (uint64_t)sizeof(uint32_t); 433 if (allocSize > SIZE_MAX) { 434 return ERROR_OUT_OF_RANGE; 435 } 436 437 mSyncSamples = new uint32_t[mNumSyncSamples]; 438 size_t size = mNumSyncSamples * sizeof(uint32_t); 439 if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size) 440 != (ssize_t)size) { 441 return ERROR_IO; 442 } 443 444 for (size_t i = 0; i < mNumSyncSamples; ++i) { 445 mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1; 446 } 447 448 return OK; 449} 450 451uint32_t SampleTable::countChunkOffsets() const { 452 return mNumChunkOffsets; 453} 454 455uint32_t SampleTable::countSamples() const { 456 return mNumSampleSizes; 457} 458 459status_t SampleTable::getMaxSampleSize(size_t *max_size) { 460 Mutex::Autolock autoLock(mLock); 461 462 *max_size = 0; 463 464 for (uint32_t i = 0; i < mNumSampleSizes; ++i) { 465 size_t sample_size; 466 status_t err = getSampleSize_l(i, &sample_size); 467 468 if (err != OK) { 469 return err; 470 } 471 472 if (sample_size > *max_size) { 473 *max_size = sample_size; 474 } 475 } 476 477 return OK; 478} 479 480uint32_t abs_difference(uint32_t time1, uint32_t time2) { 481 return time1 > time2 ? time1 - time2 : time2 - time1; 482} 483 484// static 485int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) { 486 const SampleTimeEntry *a = (const SampleTimeEntry *)_a; 487 const SampleTimeEntry *b = (const SampleTimeEntry *)_b; 488 489 if (a->mCompositionTime < b->mCompositionTime) { 490 return -1; 491 } else if (a->mCompositionTime > b->mCompositionTime) { 492 return 1; 493 } 494 495 return 0; 496} 497 498void SampleTable::buildSampleEntriesTable() { 499 Mutex::Autolock autoLock(mLock); 500 501 if (mSampleTimeEntries != NULL) { 502 return; 503 } 504 505 mSampleTimeEntries = new SampleTimeEntry[mNumSampleSizes]; 506 507 uint32_t sampleIndex = 0; 508 uint32_t sampleTime = 0; 509 510 for (uint32_t i = 0; i < mTimeToSampleCount; ++i) { 511 uint32_t n = mTimeToSample[2 * i]; 512 uint32_t delta = mTimeToSample[2 * i + 1]; 513 514 for (uint32_t j = 0; j < n; ++j) { 515 if (sampleIndex < mNumSampleSizes) { 516 // Technically this should always be the case if the file 517 // is well-formed, but you know... there's (gasp) malformed 518 // content out there. 519 520 mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex; 521 522 uint32_t compTimeDelta = 523 mCompositionDeltaLookup->getCompositionTimeOffset( 524 sampleIndex); 525 526 mSampleTimeEntries[sampleIndex].mCompositionTime = 527 sampleTime + compTimeDelta; 528 } 529 530 ++sampleIndex; 531 sampleTime += delta; 532 } 533 } 534 535 qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry), 536 CompareIncreasingTime); 537} 538 539status_t SampleTable::findSampleAtTime( 540 uint32_t req_time, uint32_t *sample_index, uint32_t flags) { 541 buildSampleEntriesTable(); 542 543 uint32_t left = 0; 544 uint32_t right = mNumSampleSizes; 545 while (left < right) { 546 uint32_t center = (left + right) / 2; 547 uint32_t centerTime = mSampleTimeEntries[center].mCompositionTime; 548 549 if (req_time < centerTime) { 550 right = center; 551 } else if (req_time > centerTime) { 552 left = center + 1; 553 } else { 554 left = center; 555 break; 556 } 557 } 558 559 if (left == mNumSampleSizes) { 560 if (flags == kFlagAfter) { 561 return ERROR_OUT_OF_RANGE; 562 } 563 564 --left; 565 } 566 567 uint32_t closestIndex = left; 568 569 switch (flags) { 570 case kFlagBefore: 571 { 572 while (closestIndex > 0 573 && mSampleTimeEntries[closestIndex].mCompositionTime 574 > req_time) { 575 --closestIndex; 576 } 577 break; 578 } 579 580 case kFlagAfter: 581 { 582 while (closestIndex + 1 < mNumSampleSizes 583 && mSampleTimeEntries[closestIndex].mCompositionTime 584 < req_time) { 585 ++closestIndex; 586 } 587 break; 588 } 589 590 default: 591 { 592 CHECK(flags == kFlagClosest); 593 594 if (closestIndex > 0) { 595 // Check left neighbour and pick closest. 596 uint32_t absdiff1 = 597 abs_difference( 598 mSampleTimeEntries[closestIndex].mCompositionTime, 599 req_time); 600 601 uint32_t absdiff2 = 602 abs_difference( 603 mSampleTimeEntries[closestIndex - 1].mCompositionTime, 604 req_time); 605 606 if (absdiff1 > absdiff2) { 607 closestIndex = closestIndex - 1; 608 } 609 } 610 611 break; 612 } 613 } 614 615 *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex; 616 617 return OK; 618} 619 620status_t SampleTable::findSyncSampleNear( 621 uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) { 622 Mutex::Autolock autoLock(mLock); 623 624 *sample_index = 0; 625 626 if (mSyncSampleOffset < 0) { 627 // All samples are sync-samples. 628 *sample_index = start_sample_index; 629 return OK; 630 } 631 632 if (mNumSyncSamples == 0) { 633 *sample_index = 0; 634 return OK; 635 } 636 637 uint32_t left = 0; 638 uint32_t right = mNumSyncSamples; 639 while (left < right) { 640 uint32_t center = left + (right - left) / 2; 641 uint32_t x = mSyncSamples[center]; 642 643 if (start_sample_index < x) { 644 right = center; 645 } else if (start_sample_index > x) { 646 left = center + 1; 647 } else { 648 left = center; 649 break; 650 } 651 } 652 if (left == mNumSyncSamples) { 653 if (flags == kFlagAfter) { 654 ALOGE("tried to find a sync frame after the last one: %d", left); 655 return ERROR_OUT_OF_RANGE; 656 } 657 left = left - 1; 658 } 659 660 // Now ssi[left] is the sync sample index just before (or at) 661 // start_sample_index. 662 // Also start_sample_index < ssi[left + 1], if left + 1 < mNumSyncSamples. 663 664 uint32_t x = mSyncSamples[left]; 665 666 if (left + 1 < mNumSyncSamples) { 667 uint32_t y = mSyncSamples[left + 1]; 668 669 // our sample lies between sync samples x and y. 670 671 status_t err = mSampleIterator->seekTo(start_sample_index); 672 if (err != OK) { 673 return err; 674 } 675 676 uint32_t sample_time = mSampleIterator->getSampleTime(); 677 678 err = mSampleIterator->seekTo(x); 679 if (err != OK) { 680 return err; 681 } 682 uint32_t x_time = mSampleIterator->getSampleTime(); 683 684 err = mSampleIterator->seekTo(y); 685 if (err != OK) { 686 return err; 687 } 688 689 uint32_t y_time = mSampleIterator->getSampleTime(); 690 691 if (abs_difference(x_time, sample_time) 692 > abs_difference(y_time, sample_time)) { 693 // Pick the sync sample closest (timewise) to the start-sample. 694 x = y; 695 ++left; 696 } 697 } 698 699 switch (flags) { 700 case kFlagBefore: 701 { 702 if (x > start_sample_index) { 703 CHECK(left > 0); 704 705 x = mSyncSamples[left - 1]; 706 707 if (x > start_sample_index) { 708 // The table of sync sample indices was not sorted 709 // properly. 710 return ERROR_MALFORMED; 711 } 712 } 713 break; 714 } 715 716 case kFlagAfter: 717 { 718 if (x < start_sample_index) { 719 if (left + 1 >= mNumSyncSamples) { 720 return ERROR_OUT_OF_RANGE; 721 } 722 723 x = mSyncSamples[left + 1]; 724 725 if (x < start_sample_index) { 726 // The table of sync sample indices was not sorted 727 // properly. 728 return ERROR_MALFORMED; 729 } 730 } 731 732 break; 733 } 734 735 default: 736 break; 737 } 738 739 *sample_index = x; 740 741 return OK; 742} 743 744status_t SampleTable::findThumbnailSample(uint32_t *sample_index) { 745 Mutex::Autolock autoLock(mLock); 746 747 if (mSyncSampleOffset < 0) { 748 // All samples are sync-samples. 749 *sample_index = 0; 750 return OK; 751 } 752 753 uint32_t bestSampleIndex = 0; 754 size_t maxSampleSize = 0; 755 756 static const size_t kMaxNumSyncSamplesToScan = 20; 757 758 // Consider the first kMaxNumSyncSamplesToScan sync samples and 759 // pick the one with the largest (compressed) size as the thumbnail. 760 761 size_t numSamplesToScan = mNumSyncSamples; 762 if (numSamplesToScan > kMaxNumSyncSamplesToScan) { 763 numSamplesToScan = kMaxNumSyncSamplesToScan; 764 } 765 766 for (size_t i = 0; i < numSamplesToScan; ++i) { 767 uint32_t x = mSyncSamples[i]; 768 769 // Now x is a sample index. 770 size_t sampleSize; 771 status_t err = getSampleSize_l(x, &sampleSize); 772 if (err != OK) { 773 return err; 774 } 775 776 if (i == 0 || sampleSize > maxSampleSize) { 777 bestSampleIndex = x; 778 maxSampleSize = sampleSize; 779 } 780 } 781 782 *sample_index = bestSampleIndex; 783 784 return OK; 785} 786 787status_t SampleTable::getSampleSize_l( 788 uint32_t sampleIndex, size_t *sampleSize) { 789 return mSampleIterator->getSampleSizeDirect( 790 sampleIndex, sampleSize); 791} 792 793status_t SampleTable::getMetaDataForSample( 794 uint32_t sampleIndex, 795 off64_t *offset, 796 size_t *size, 797 uint32_t *compositionTime, 798 bool *isSyncSample) { 799 Mutex::Autolock autoLock(mLock); 800 801 status_t err; 802 if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) { 803 return err; 804 } 805 806 if (offset) { 807 *offset = mSampleIterator->getSampleOffset(); 808 } 809 810 if (size) { 811 *size = mSampleIterator->getSampleSize(); 812 } 813 814 if (compositionTime) { 815 *compositionTime = mSampleIterator->getSampleTime(); 816 } 817 818 if (isSyncSample) { 819 *isSyncSample = false; 820 if (mSyncSampleOffset < 0) { 821 // Every sample is a sync sample. 822 *isSyncSample = true; 823 } else { 824 size_t i = (mLastSyncSampleIndex < mNumSyncSamples) 825 && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex) 826 ? mLastSyncSampleIndex : 0; 827 828 while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) { 829 ++i; 830 } 831 832 if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) { 833 *isSyncSample = true; 834 } 835 836 mLastSyncSampleIndex = i; 837 } 838 } 839 840 return OK; 841} 842 843uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) { 844 return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex); 845} 846 847} // namespace android 848 849