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