SampleTable.cpp revision 3cc11bfc00cbb3ed87a4464777a75606b4973b51
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 mSampleToChunkEntries = 234 new SampleToChunkEntry[mNumSampleToChunkOffsets]; 235 236 for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) { 237 uint8_t buffer[12]; 238 if (mDataSource->readAt( 239 mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer)) 240 != (ssize_t)sizeof(buffer)) { 241 return ERROR_IO; 242 } 243 244 CHECK(U32_AT(buffer) >= 1); // chunk index is 1 based in the spec. 245 246 // We want the chunk index to be 0-based. 247 mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1; 248 mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]); 249 mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]); 250 } 251 252 return OK; 253} 254 255status_t SampleTable::setSampleSizeParams( 256 uint32_t type, off64_t data_offset, size_t data_size) { 257 if (mSampleSizeOffset >= 0) { 258 return ERROR_MALFORMED; 259 } 260 261 CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact); 262 263 mSampleSizeOffset = data_offset; 264 265 if (data_size < 12) { 266 return ERROR_MALFORMED; 267 } 268 269 uint8_t header[12]; 270 if (mDataSource->readAt( 271 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { 272 return ERROR_IO; 273 } 274 275 if (U32_AT(header) != 0) { 276 // Expected version = 0, flags = 0. 277 return ERROR_MALFORMED; 278 } 279 280 mDefaultSampleSize = U32_AT(&header[4]); 281 mNumSampleSizes = U32_AT(&header[8]); 282 283 if (type == kSampleSizeType32) { 284 mSampleSizeFieldSize = 32; 285 286 if (mDefaultSampleSize != 0) { 287 return OK; 288 } 289 290 if (data_size < 12 + mNumSampleSizes * 4) { 291 return ERROR_MALFORMED; 292 } 293 } else { 294 if ((mDefaultSampleSize & 0xffffff00) != 0) { 295 // The high 24 bits are reserved and must be 0. 296 return ERROR_MALFORMED; 297 } 298 299 mSampleSizeFieldSize = mDefaultSampleSize & 0xff; 300 mDefaultSampleSize = 0; 301 302 if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8 303 && mSampleSizeFieldSize != 16) { 304 return ERROR_MALFORMED; 305 } 306 307 if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) { 308 return ERROR_MALFORMED; 309 } 310 } 311 312 return OK; 313} 314 315status_t SampleTable::setTimeToSampleParams( 316 off64_t data_offset, size_t data_size) { 317 if (mTimeToSample != NULL || data_size < 8) { 318 return ERROR_MALFORMED; 319 } 320 321 uint8_t header[8]; 322 if (mDataSource->readAt( 323 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { 324 return ERROR_IO; 325 } 326 327 if (U32_AT(header) != 0) { 328 // Expected version = 0, flags = 0. 329 return ERROR_MALFORMED; 330 } 331 332 mTimeToSampleCount = U32_AT(&header[4]); 333 uint64_t allocSize = mTimeToSampleCount * 2 * (uint64_t)sizeof(uint32_t); 334 if (allocSize > SIZE_MAX) { 335 return ERROR_OUT_OF_RANGE; 336 } 337 mTimeToSample = new uint32_t[mTimeToSampleCount * 2]; 338 339 size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2; 340 if (mDataSource->readAt( 341 data_offset + 8, mTimeToSample, size) < (ssize_t)size) { 342 return ERROR_IO; 343 } 344 345 for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) { 346 mTimeToSample[i] = ntohl(mTimeToSample[i]); 347 } 348 349 return OK; 350} 351 352status_t SampleTable::setCompositionTimeToSampleParams( 353 off64_t data_offset, size_t data_size) { 354 ALOGI("There are reordered frames present."); 355 356 if (mCompositionTimeDeltaEntries != NULL || data_size < 8) { 357 return ERROR_MALFORMED; 358 } 359 360 uint8_t header[8]; 361 if (mDataSource->readAt( 362 data_offset, header, sizeof(header)) 363 < (ssize_t)sizeof(header)) { 364 return ERROR_IO; 365 } 366 367 if (U32_AT(header) != 0) { 368 // Expected version = 0, flags = 0. 369 return ERROR_MALFORMED; 370 } 371 372 size_t numEntries = U32_AT(&header[4]); 373 374 if (data_size != (numEntries + 1) * 8) { 375 return ERROR_MALFORMED; 376 } 377 378 mNumCompositionTimeDeltaEntries = numEntries; 379 uint64_t allocSize = numEntries * 2 * (uint64_t)sizeof(uint32_t); 380 if (allocSize > SIZE_MAX) { 381 return ERROR_OUT_OF_RANGE; 382 } 383 384 mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries]; 385 386 if (mDataSource->readAt( 387 data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8) 388 < (ssize_t)numEntries * 8) { 389 delete[] mCompositionTimeDeltaEntries; 390 mCompositionTimeDeltaEntries = NULL; 391 392 return ERROR_IO; 393 } 394 395 for (size_t i = 0; i < 2 * numEntries; ++i) { 396 mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]); 397 } 398 399 mCompositionDeltaLookup->setEntries( 400 mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries); 401 402 return OK; 403} 404 405status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) { 406 if (mSyncSampleOffset >= 0 || data_size < 8) { 407 return ERROR_MALFORMED; 408 } 409 410 mSyncSampleOffset = data_offset; 411 412 uint8_t header[8]; 413 if (mDataSource->readAt( 414 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) { 415 return ERROR_IO; 416 } 417 418 if (U32_AT(header) != 0) { 419 // Expected version = 0, flags = 0. 420 return ERROR_MALFORMED; 421 } 422 423 mNumSyncSamples = U32_AT(&header[4]); 424 425 if (mNumSyncSamples < 2) { 426 ALOGV("Table of sync samples is empty or has only a single entry!"); 427 } 428 429 uint64_t allocSize = mNumSyncSamples * (uint64_t)sizeof(uint32_t); 430 if (allocSize > SIZE_MAX) { 431 return ERROR_OUT_OF_RANGE; 432 } 433 434 mSyncSamples = new uint32_t[mNumSyncSamples]; 435 size_t size = mNumSyncSamples * sizeof(uint32_t); 436 if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size) 437 != (ssize_t)size) { 438 return ERROR_IO; 439 } 440 441 for (size_t i = 0; i < mNumSyncSamples; ++i) { 442 mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1; 443 } 444 445 return OK; 446} 447 448uint32_t SampleTable::countChunkOffsets() const { 449 return mNumChunkOffsets; 450} 451 452uint32_t SampleTable::countSamples() const { 453 return mNumSampleSizes; 454} 455 456status_t SampleTable::getMaxSampleSize(size_t *max_size) { 457 Mutex::Autolock autoLock(mLock); 458 459 *max_size = 0; 460 461 for (uint32_t i = 0; i < mNumSampleSizes; ++i) { 462 size_t sample_size; 463 status_t err = getSampleSize_l(i, &sample_size); 464 465 if (err != OK) { 466 return err; 467 } 468 469 if (sample_size > *max_size) { 470 *max_size = sample_size; 471 } 472 } 473 474 return OK; 475} 476 477uint32_t abs_difference(uint32_t time1, uint32_t time2) { 478 return time1 > time2 ? time1 - time2 : time2 - time1; 479} 480 481// static 482int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) { 483 const SampleTimeEntry *a = (const SampleTimeEntry *)_a; 484 const SampleTimeEntry *b = (const SampleTimeEntry *)_b; 485 486 if (a->mCompositionTime < b->mCompositionTime) { 487 return -1; 488 } else if (a->mCompositionTime > b->mCompositionTime) { 489 return 1; 490 } 491 492 return 0; 493} 494 495void SampleTable::buildSampleEntriesTable() { 496 Mutex::Autolock autoLock(mLock); 497 498 if (mSampleTimeEntries != NULL) { 499 return; 500 } 501 502 mSampleTimeEntries = new SampleTimeEntry[mNumSampleSizes]; 503 504 uint32_t sampleIndex = 0; 505 uint32_t sampleTime = 0; 506 507 for (uint32_t i = 0; i < mTimeToSampleCount; ++i) { 508 uint32_t n = mTimeToSample[2 * i]; 509 uint32_t delta = mTimeToSample[2 * i + 1]; 510 511 for (uint32_t j = 0; j < n; ++j) { 512 if (sampleIndex < mNumSampleSizes) { 513 // Technically this should always be the case if the file 514 // is well-formed, but you know... there's (gasp) malformed 515 // content out there. 516 517 mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex; 518 519 uint32_t compTimeDelta = 520 mCompositionDeltaLookup->getCompositionTimeOffset( 521 sampleIndex); 522 523 mSampleTimeEntries[sampleIndex].mCompositionTime = 524 sampleTime + compTimeDelta; 525 } 526 527 ++sampleIndex; 528 sampleTime += delta; 529 } 530 } 531 532 qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry), 533 CompareIncreasingTime); 534} 535 536status_t SampleTable::findSampleAtTime( 537 uint32_t req_time, uint32_t *sample_index, uint32_t flags) { 538 buildSampleEntriesTable(); 539 540 uint32_t left = 0; 541 uint32_t right = mNumSampleSizes; 542 while (left < right) { 543 uint32_t center = (left + right) / 2; 544 uint32_t centerTime = mSampleTimeEntries[center].mCompositionTime; 545 546 if (req_time < centerTime) { 547 right = center; 548 } else if (req_time > centerTime) { 549 left = center + 1; 550 } else { 551 left = center; 552 break; 553 } 554 } 555 556 if (left == mNumSampleSizes) { 557 if (flags == kFlagAfter) { 558 return ERROR_OUT_OF_RANGE; 559 } 560 561 --left; 562 } 563 564 uint32_t closestIndex = left; 565 566 switch (flags) { 567 case kFlagBefore: 568 { 569 while (closestIndex > 0 570 && mSampleTimeEntries[closestIndex].mCompositionTime 571 > req_time) { 572 --closestIndex; 573 } 574 break; 575 } 576 577 case kFlagAfter: 578 { 579 while (closestIndex + 1 < mNumSampleSizes 580 && mSampleTimeEntries[closestIndex].mCompositionTime 581 < req_time) { 582 ++closestIndex; 583 } 584 break; 585 } 586 587 default: 588 { 589 CHECK(flags == kFlagClosest); 590 591 if (closestIndex > 0) { 592 // Check left neighbour and pick closest. 593 uint32_t absdiff1 = 594 abs_difference( 595 mSampleTimeEntries[closestIndex].mCompositionTime, 596 req_time); 597 598 uint32_t absdiff2 = 599 abs_difference( 600 mSampleTimeEntries[closestIndex - 1].mCompositionTime, 601 req_time); 602 603 if (absdiff1 > absdiff2) { 604 closestIndex = closestIndex - 1; 605 } 606 } 607 608 break; 609 } 610 } 611 612 *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex; 613 614 return OK; 615} 616 617status_t SampleTable::findSyncSampleNear( 618 uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) { 619 Mutex::Autolock autoLock(mLock); 620 621 *sample_index = 0; 622 623 if (mSyncSampleOffset < 0) { 624 // All samples are sync-samples. 625 *sample_index = start_sample_index; 626 return OK; 627 } 628 629 if (mNumSyncSamples == 0) { 630 *sample_index = 0; 631 return OK; 632 } 633 634 uint32_t left = 0; 635 uint32_t right = mNumSyncSamples; 636 while (left < right) { 637 uint32_t center = left + (right - left) / 2; 638 uint32_t x = mSyncSamples[center]; 639 640 if (start_sample_index < x) { 641 right = center; 642 } else if (start_sample_index > x) { 643 left = center + 1; 644 } else { 645 left = center; 646 break; 647 } 648 } 649 if (left == mNumSyncSamples) { 650 if (flags == kFlagAfter) { 651 ALOGE("tried to find a sync frame after the last one: %d", left); 652 return ERROR_OUT_OF_RANGE; 653 } 654 left = left - 1; 655 } 656 657 // Now ssi[left] is the sync sample index just before (or at) 658 // start_sample_index. 659 // Also start_sample_index < ssi[left + 1], if left + 1 < mNumSyncSamples. 660 661 uint32_t x = mSyncSamples[left]; 662 663 if (left + 1 < mNumSyncSamples) { 664 uint32_t y = mSyncSamples[left + 1]; 665 666 // our sample lies between sync samples x and y. 667 668 status_t err = mSampleIterator->seekTo(start_sample_index); 669 if (err != OK) { 670 return err; 671 } 672 673 uint32_t sample_time = mSampleIterator->getSampleTime(); 674 675 err = mSampleIterator->seekTo(x); 676 if (err != OK) { 677 return err; 678 } 679 uint32_t x_time = mSampleIterator->getSampleTime(); 680 681 err = mSampleIterator->seekTo(y); 682 if (err != OK) { 683 return err; 684 } 685 686 uint32_t y_time = mSampleIterator->getSampleTime(); 687 688 if (abs_difference(x_time, sample_time) 689 > abs_difference(y_time, sample_time)) { 690 // Pick the sync sample closest (timewise) to the start-sample. 691 x = y; 692 ++left; 693 } 694 } 695 696 switch (flags) { 697 case kFlagBefore: 698 { 699 if (x > start_sample_index) { 700 CHECK(left > 0); 701 702 x = mSyncSamples[left - 1]; 703 704 if (x > start_sample_index) { 705 // The table of sync sample indices was not sorted 706 // properly. 707 return ERROR_MALFORMED; 708 } 709 } 710 break; 711 } 712 713 case kFlagAfter: 714 { 715 if (x < start_sample_index) { 716 if (left + 1 >= mNumSyncSamples) { 717 return ERROR_OUT_OF_RANGE; 718 } 719 720 x = mSyncSamples[left + 1]; 721 722 if (x < start_sample_index) { 723 // The table of sync sample indices was not sorted 724 // properly. 725 return ERROR_MALFORMED; 726 } 727 } 728 729 break; 730 } 731 732 default: 733 break; 734 } 735 736 *sample_index = x; 737 738 return OK; 739} 740 741status_t SampleTable::findThumbnailSample(uint32_t *sample_index) { 742 Mutex::Autolock autoLock(mLock); 743 744 if (mSyncSampleOffset < 0) { 745 // All samples are sync-samples. 746 *sample_index = 0; 747 return OK; 748 } 749 750 uint32_t bestSampleIndex = 0; 751 size_t maxSampleSize = 0; 752 753 static const size_t kMaxNumSyncSamplesToScan = 20; 754 755 // Consider the first kMaxNumSyncSamplesToScan sync samples and 756 // pick the one with the largest (compressed) size as the thumbnail. 757 758 size_t numSamplesToScan = mNumSyncSamples; 759 if (numSamplesToScan > kMaxNumSyncSamplesToScan) { 760 numSamplesToScan = kMaxNumSyncSamplesToScan; 761 } 762 763 for (size_t i = 0; i < numSamplesToScan; ++i) { 764 uint32_t x = mSyncSamples[i]; 765 766 // Now x is a sample index. 767 size_t sampleSize; 768 status_t err = getSampleSize_l(x, &sampleSize); 769 if (err != OK) { 770 return err; 771 } 772 773 if (i == 0 || sampleSize > maxSampleSize) { 774 bestSampleIndex = x; 775 maxSampleSize = sampleSize; 776 } 777 } 778 779 *sample_index = bestSampleIndex; 780 781 return OK; 782} 783 784status_t SampleTable::getSampleSize_l( 785 uint32_t sampleIndex, size_t *sampleSize) { 786 return mSampleIterator->getSampleSizeDirect( 787 sampleIndex, sampleSize); 788} 789 790status_t SampleTable::getMetaDataForSample( 791 uint32_t sampleIndex, 792 off64_t *offset, 793 size_t *size, 794 uint32_t *compositionTime, 795 bool *isSyncSample) { 796 Mutex::Autolock autoLock(mLock); 797 798 status_t err; 799 if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) { 800 return err; 801 } 802 803 if (offset) { 804 *offset = mSampleIterator->getSampleOffset(); 805 } 806 807 if (size) { 808 *size = mSampleIterator->getSampleSize(); 809 } 810 811 if (compositionTime) { 812 *compositionTime = mSampleIterator->getSampleTime(); 813 } 814 815 if (isSyncSample) { 816 *isSyncSample = false; 817 if (mSyncSampleOffset < 0) { 818 // Every sample is a sync sample. 819 *isSyncSample = true; 820 } else { 821 size_t i = (mLastSyncSampleIndex < mNumSyncSamples) 822 && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex) 823 ? mLastSyncSampleIndex : 0; 824 825 while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) { 826 ++i; 827 } 828 829 if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) { 830 *isSyncSample = true; 831 } 832 833 mLastSyncSampleIndex = i; 834 } 835 } 836 837 return OK; 838} 839 840uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) { 841 return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex); 842} 843 844} // namespace android 845 846