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