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