Home | History | Annotate | Download | only in libstagefright
      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 <limits>
     22 
     23 #include "include/SampleTable.h"
     24 #include "include/SampleIterator.h"
     25 
     26 #include <arpa/inet.h>
     27 
     28 #include <media/stagefright/foundation/ADebug.h>
     29 #include <media/stagefright/DataSource.h>
     30 #include <media/stagefright/Utils.h>
     31 
     32 /* TODO: remove after being merged into other branches */
     33 #ifndef UINT32_MAX
     34 #define UINT32_MAX       (4294967295U)
     35 #endif
     36 
     37 namespace android {
     38 
     39 // static
     40 const uint32_t SampleTable::kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o');
     41 // static
     42 const uint32_t SampleTable::kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
     43 // static
     44 const uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
     45 // static
     46 const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
     47 
     48 ////////////////////////////////////////////////////////////////////////////////
     49 
     50 const off64_t kMaxOffset = std::numeric_limits<off64_t>::max();
     51 
     52 struct SampleTable::CompositionDeltaLookup {
     53     CompositionDeltaLookup();
     54 
     55     void setEntries(
     56             const int32_t *deltaEntries, size_t numDeltaEntries);
     57 
     58     int32_t getCompositionTimeOffset(uint32_t sampleIndex);
     59 
     60 private:
     61     Mutex mLock;
     62 
     63     const int32_t *mDeltaEntries;
     64     size_t mNumDeltaEntries;
     65 
     66     size_t mCurrentDeltaEntry;
     67     size_t mCurrentEntrySampleIndex;
     68 
     69     DISALLOW_EVIL_CONSTRUCTORS(CompositionDeltaLookup);
     70 };
     71 
     72 SampleTable::CompositionDeltaLookup::CompositionDeltaLookup()
     73     : mDeltaEntries(NULL),
     74       mNumDeltaEntries(0),
     75       mCurrentDeltaEntry(0),
     76       mCurrentEntrySampleIndex(0) {
     77 }
     78 
     79 void SampleTable::CompositionDeltaLookup::setEntries(
     80         const int32_t *deltaEntries, size_t numDeltaEntries) {
     81     Mutex::Autolock autolock(mLock);
     82 
     83     mDeltaEntries = deltaEntries;
     84     mNumDeltaEntries = numDeltaEntries;
     85     mCurrentDeltaEntry = 0;
     86     mCurrentEntrySampleIndex = 0;
     87 }
     88 
     89 int32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
     90         uint32_t sampleIndex) {
     91     Mutex::Autolock autolock(mLock);
     92 
     93     if (mDeltaEntries == NULL) {
     94         return 0;
     95     }
     96 
     97     if (sampleIndex < mCurrentEntrySampleIndex) {
     98         mCurrentDeltaEntry = 0;
     99         mCurrentEntrySampleIndex = 0;
    100     }
    101 
    102     while (mCurrentDeltaEntry < mNumDeltaEntries) {
    103         uint32_t sampleCount = mDeltaEntries[2 * mCurrentDeltaEntry];
    104         if (sampleIndex < mCurrentEntrySampleIndex + sampleCount) {
    105             return mDeltaEntries[2 * mCurrentDeltaEntry + 1];
    106         }
    107 
    108         mCurrentEntrySampleIndex += sampleCount;
    109         ++mCurrentDeltaEntry;
    110     }
    111 
    112     return 0;
    113 }
    114 
    115 ////////////////////////////////////////////////////////////////////////////////
    116 
    117 SampleTable::SampleTable(const sp<DataSource> &source)
    118     : mDataSource(source),
    119       mChunkOffsetOffset(-1),
    120       mChunkOffsetType(0),
    121       mNumChunkOffsets(0),
    122       mSampleToChunkOffset(-1),
    123       mNumSampleToChunkOffsets(0),
    124       mSampleSizeOffset(-1),
    125       mSampleSizeFieldSize(0),
    126       mDefaultSampleSize(0),
    127       mNumSampleSizes(0),
    128       mHasTimeToSample(false),
    129       mTimeToSampleCount(0),
    130       mTimeToSample(NULL),
    131       mSampleTimeEntries(NULL),
    132       mCompositionTimeDeltaEntries(NULL),
    133       mNumCompositionTimeDeltaEntries(0),
    134       mCompositionDeltaLookup(new CompositionDeltaLookup),
    135       mSyncSampleOffset(-1),
    136       mNumSyncSamples(0),
    137       mSyncSamples(NULL),
    138       mLastSyncSampleIndex(0),
    139       mSampleToChunkEntries(NULL),
    140       mTotalSize(0) {
    141     mSampleIterator = new SampleIterator(this);
    142 }
    143 
    144 SampleTable::~SampleTable() {
    145     delete[] mSampleToChunkEntries;
    146     mSampleToChunkEntries = NULL;
    147 
    148     delete[] mSyncSamples;
    149     mSyncSamples = NULL;
    150 
    151     delete[] mTimeToSample;
    152     mTimeToSample = NULL;
    153 
    154     delete mCompositionDeltaLookup;
    155     mCompositionDeltaLookup = NULL;
    156 
    157     delete[] mCompositionTimeDeltaEntries;
    158     mCompositionTimeDeltaEntries = NULL;
    159 
    160     delete[] mSampleTimeEntries;
    161     mSampleTimeEntries = NULL;
    162 
    163     delete mSampleIterator;
    164     mSampleIterator = NULL;
    165 }
    166 
    167 bool SampleTable::isValid() const {
    168     return mChunkOffsetOffset >= 0
    169         && mSampleToChunkOffset >= 0
    170         && mSampleSizeOffset >= 0
    171         && mHasTimeToSample;
    172 }
    173 
    174 status_t SampleTable::setChunkOffsetParams(
    175         uint32_t type, off64_t data_offset, size_t data_size) {
    176     if (mChunkOffsetOffset >= 0) {
    177         return ERROR_MALFORMED;
    178     }
    179 
    180     CHECK(type == kChunkOffsetType32 || type == kChunkOffsetType64);
    181 
    182     mChunkOffsetOffset = data_offset;
    183     mChunkOffsetType = type;
    184 
    185     if (data_size < 8) {
    186         return ERROR_MALFORMED;
    187     }
    188 
    189     uint8_t header[8];
    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     mNumChunkOffsets = U32_AT(&header[4]);
    201 
    202     if (mChunkOffsetType == kChunkOffsetType32) {
    203       if ((data_size - 8) / 4 < mNumChunkOffsets) {
    204             return ERROR_MALFORMED;
    205         }
    206     } else {
    207       if ((data_size - 8) / 8 < mNumChunkOffsets) {
    208             return ERROR_MALFORMED;
    209         }
    210     }
    211 
    212     return OK;
    213 }
    214 
    215 status_t SampleTable::setSampleToChunkParams(
    216         off64_t data_offset, size_t data_size) {
    217     if (mSampleToChunkOffset >= 0) {
    218         return ERROR_MALFORMED;
    219     }
    220 
    221     mSampleToChunkOffset = data_offset;
    222 
    223     if (data_size < 8) {
    224         return ERROR_MALFORMED;
    225     }
    226 
    227     uint8_t header[8];
    228     if (mDataSource->readAt(
    229                 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
    230         return ERROR_IO;
    231     }
    232 
    233     if (U32_AT(header) != 0) {
    234         // Expected version = 0, flags = 0.
    235         return ERROR_MALFORMED;
    236     }
    237 
    238     mNumSampleToChunkOffsets = U32_AT(&header[4]);
    239 
    240     if ((data_size - 8) / sizeof(SampleToChunkEntry) < mNumSampleToChunkOffsets) {
    241         return ERROR_MALFORMED;
    242     }
    243 
    244     if ((uint64_t)kMaxTotalSize / sizeof(SampleToChunkEntry) <=
    245             (uint64_t)mNumSampleToChunkOffsets) {
    246         ALOGE("Sample-to-chunk table size too large.");
    247         return ERROR_OUT_OF_RANGE;
    248     }
    249 
    250     mTotalSize += (uint64_t)mNumSampleToChunkOffsets *
    251             sizeof(SampleToChunkEntry);
    252     if (mTotalSize > kMaxTotalSize) {
    253         ALOGE("Sample-to-chunk table size would make sample table too large.\n"
    254               "    Requested sample-to-chunk table size = %llu\n"
    255               "    Eventual sample table size >= %llu\n"
    256               "    Allowed sample table size = %llu\n",
    257               (unsigned long long)mNumSampleToChunkOffsets *
    258                       sizeof(SampleToChunkEntry),
    259               (unsigned long long)mTotalSize,
    260               (unsigned long long)kMaxTotalSize);
    261         return ERROR_OUT_OF_RANGE;
    262     }
    263 
    264     mSampleToChunkEntries =
    265         new (std::nothrow) SampleToChunkEntry[mNumSampleToChunkOffsets];
    266     if (!mSampleToChunkEntries) {
    267         ALOGE("Cannot allocate sample-to-chunk table with %llu entries.",
    268                 (unsigned long long)mNumSampleToChunkOffsets);
    269         return ERROR_OUT_OF_RANGE;
    270     }
    271 
    272     if (mNumSampleToChunkOffsets == 0) {
    273         return OK;
    274     }
    275 
    276     if ((off64_t)(kMaxOffset - 8 -
    277             ((mNumSampleToChunkOffsets - 1) * sizeof(SampleToChunkEntry)))
    278             < mSampleToChunkOffset) {
    279         return ERROR_MALFORMED;
    280     }
    281 
    282     for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
    283         uint8_t buffer[sizeof(SampleToChunkEntry)];
    284 
    285         if (mDataSource->readAt(
    286                     mSampleToChunkOffset + 8 + i * sizeof(SampleToChunkEntry),
    287                     buffer,
    288                     sizeof(buffer))
    289                 != (ssize_t)sizeof(buffer)) {
    290             return ERROR_IO;
    291         }
    292         // chunk index is 1 based in the spec.
    293         if (U32_AT(buffer) < 1) {
    294             ALOGE("b/23534160");
    295             return ERROR_OUT_OF_RANGE;
    296         }
    297 
    298         // We want the chunk index to be 0-based.
    299         mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
    300         mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]);
    301         mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]);
    302     }
    303 
    304     return OK;
    305 }
    306 
    307 status_t SampleTable::setSampleSizeParams(
    308         uint32_t type, off64_t data_offset, size_t data_size) {
    309     if (mSampleSizeOffset >= 0) {
    310         return ERROR_MALFORMED;
    311     }
    312 
    313     CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact);
    314 
    315     mSampleSizeOffset = data_offset;
    316 
    317     if (data_size < 12) {
    318         return ERROR_MALFORMED;
    319     }
    320 
    321     uint8_t header[12];
    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     mDefaultSampleSize = U32_AT(&header[4]);
    333     mNumSampleSizes = U32_AT(&header[8]);
    334     if (mNumSampleSizes > (UINT32_MAX - 12) / 16) {
    335         ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes);
    336         return ERROR_MALFORMED;
    337     }
    338 
    339     if (type == kSampleSizeType32) {
    340         mSampleSizeFieldSize = 32;
    341 
    342         if (mDefaultSampleSize != 0) {
    343             return OK;
    344         }
    345 
    346         if (data_size < 12 + mNumSampleSizes * 4) {
    347             return ERROR_MALFORMED;
    348         }
    349     } else {
    350         if ((mDefaultSampleSize & 0xffffff00) != 0) {
    351             // The high 24 bits are reserved and must be 0.
    352             return ERROR_MALFORMED;
    353         }
    354 
    355         mSampleSizeFieldSize = mDefaultSampleSize & 0xff;
    356         mDefaultSampleSize = 0;
    357 
    358         if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8
    359             && mSampleSizeFieldSize != 16) {
    360             return ERROR_MALFORMED;
    361         }
    362 
    363         if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
    364             return ERROR_MALFORMED;
    365         }
    366     }
    367 
    368     return OK;
    369 }
    370 
    371 status_t SampleTable::setTimeToSampleParams(
    372         off64_t data_offset, size_t data_size) {
    373     if (mHasTimeToSample || data_size < 8) {
    374         return ERROR_MALFORMED;
    375     }
    376 
    377     uint8_t header[8];
    378     if (mDataSource->readAt(
    379                 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
    380         return ERROR_IO;
    381     }
    382 
    383     if (U32_AT(header) != 0) {
    384         // Expected version = 0, flags = 0.
    385         return ERROR_MALFORMED;
    386     }
    387 
    388     mTimeToSampleCount = U32_AT(&header[4]);
    389     if (mTimeToSampleCount > UINT32_MAX / (2 * sizeof(uint32_t))) {
    390         // Choose this bound because
    391         // 1) 2 * sizeof(uint32_t) is the amount of memory needed for one
    392         //    time-to-sample entry in the time-to-sample table.
    393         // 2) mTimeToSampleCount is the number of entries of the time-to-sample
    394         //    table.
    395         // 3) We hope that the table size does not exceed UINT32_MAX.
    396         ALOGE("Time-to-sample table size too large.");
    397         return ERROR_OUT_OF_RANGE;
    398     }
    399 
    400     // Note: At this point, we know that mTimeToSampleCount * 2 will not
    401     // overflow because of the above condition.
    402 
    403     uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
    404     mTotalSize += allocSize;
    405     if (mTotalSize > kMaxTotalSize) {
    406         ALOGE("Time-to-sample table size would make sample table too large.\n"
    407               "    Requested time-to-sample table size = %llu\n"
    408               "    Eventual sample table size >= %llu\n"
    409               "    Allowed sample table size = %llu\n",
    410               (unsigned long long)allocSize,
    411               (unsigned long long)mTotalSize,
    412               (unsigned long long)kMaxTotalSize);
    413         return ERROR_OUT_OF_RANGE;
    414     }
    415 
    416     mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2];
    417     if (!mTimeToSample) {
    418         ALOGE("Cannot allocate time-to-sample table with %llu entries.",
    419                 (unsigned long long)mTimeToSampleCount);
    420         return ERROR_OUT_OF_RANGE;
    421     }
    422 
    423     if (mDataSource->readAt(data_offset + 8, mTimeToSample,
    424             (size_t)allocSize) < (ssize_t)allocSize) {
    425         ALOGE("Incomplete data read for time-to-sample table.");
    426         return ERROR_IO;
    427     }
    428 
    429     for (size_t i = 0; i < mTimeToSampleCount * 2; ++i) {
    430         mTimeToSample[i] = ntohl(mTimeToSample[i]);
    431     }
    432 
    433     mHasTimeToSample = true;
    434     return OK;
    435 }
    436 
    437 // NOTE: per 14996-12, version 0 ctts contains unsigned values, while version 1
    438 // contains signed values, however some software creates version 0 files that
    439 // contain signed values, so we're always treating the values as signed,
    440 // regardless of version.
    441 status_t SampleTable::setCompositionTimeToSampleParams(
    442         off64_t data_offset, size_t data_size) {
    443     ALOGI("There are reordered frames present.");
    444 
    445     if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
    446         return ERROR_MALFORMED;
    447     }
    448 
    449     uint8_t header[8];
    450     if (mDataSource->readAt(
    451                 data_offset, header, sizeof(header))
    452             < (ssize_t)sizeof(header)) {
    453         return ERROR_IO;
    454     }
    455 
    456     uint32_t flags = U32_AT(header);
    457     uint32_t version = flags >> 24;
    458     flags &= 0xffffff;
    459 
    460     if ((version != 0 && version != 1) || flags != 0) {
    461         // Expected version = 0 or 1, flags = 0.
    462         return ERROR_MALFORMED;
    463     }
    464 
    465     size_t numEntries = U32_AT(&header[4]);
    466 
    467     if (((SIZE_MAX / 8) - 1 < numEntries) || (data_size != (numEntries + 1) * 8)) {
    468         return ERROR_MALFORMED;
    469     }
    470 
    471     mNumCompositionTimeDeltaEntries = numEntries;
    472     uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(int32_t);
    473     if (allocSize > kMaxTotalSize) {
    474         ALOGE("Composition-time-to-sample table size too large.");
    475         return ERROR_OUT_OF_RANGE;
    476     }
    477 
    478     mTotalSize += allocSize;
    479     if (mTotalSize > kMaxTotalSize) {
    480         ALOGE("Composition-time-to-sample table would make sample table too large.\n"
    481               "    Requested composition-time-to-sample table size = %llu\n"
    482               "    Eventual sample table size >= %llu\n"
    483               "    Allowed sample table size = %llu\n",
    484               (unsigned long long)allocSize,
    485               (unsigned long long)mTotalSize,
    486               (unsigned long long)kMaxTotalSize);
    487         return ERROR_OUT_OF_RANGE;
    488     }
    489 
    490     mCompositionTimeDeltaEntries = new (std::nothrow) int32_t[2 * numEntries];
    491     if (!mCompositionTimeDeltaEntries) {
    492         ALOGE("Cannot allocate composition-time-to-sample table with %llu "
    493                 "entries.", (unsigned long long)numEntries);
    494         return ERROR_OUT_OF_RANGE;
    495     }
    496 
    497     if (mDataSource->readAt(data_offset + 8, mCompositionTimeDeltaEntries,
    498             (size_t)allocSize) < (ssize_t)allocSize) {
    499         delete[] mCompositionTimeDeltaEntries;
    500         mCompositionTimeDeltaEntries = NULL;
    501 
    502         return ERROR_IO;
    503     }
    504 
    505     for (size_t i = 0; i < 2 * numEntries; ++i) {
    506         mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
    507     }
    508 
    509     mCompositionDeltaLookup->setEntries(
    510             mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries);
    511 
    512     return OK;
    513 }
    514 
    515 status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
    516     if (mSyncSampleOffset >= 0 || data_size < 8) {
    517         return ERROR_MALFORMED;
    518     }
    519 
    520     mSyncSampleOffset = data_offset;
    521 
    522     uint8_t header[8];
    523     if (mDataSource->readAt(
    524                 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
    525         return ERROR_IO;
    526     }
    527 
    528     if (U32_AT(header) != 0) {
    529         // Expected version = 0, flags = 0.
    530         return ERROR_MALFORMED;
    531     }
    532 
    533     mNumSyncSamples = U32_AT(&header[4]);
    534 
    535     if (mNumSyncSamples < 2) {
    536         ALOGV("Table of sync samples is empty or has only a single entry!");
    537     }
    538 
    539     uint64_t allocSize = (uint64_t)mNumSyncSamples * sizeof(uint32_t);
    540     if (allocSize > kMaxTotalSize) {
    541         ALOGE("Sync sample table size too large.");
    542         return ERROR_OUT_OF_RANGE;
    543     }
    544 
    545     mTotalSize += allocSize;
    546     if (mTotalSize > kMaxTotalSize) {
    547         ALOGE("Sync sample table size would make sample table too large.\n"
    548               "    Requested sync sample table size = %llu\n"
    549               "    Eventual sample table size >= %llu\n"
    550               "    Allowed sample table size = %llu\n",
    551               (unsigned long long)allocSize,
    552               (unsigned long long)mTotalSize,
    553               (unsigned long long)kMaxTotalSize);
    554         return ERROR_OUT_OF_RANGE;
    555     }
    556 
    557     mSyncSamples = new (std::nothrow) uint32_t[mNumSyncSamples];
    558     if (!mSyncSamples) {
    559         ALOGE("Cannot allocate sync sample table with %llu entries.",
    560                 (unsigned long long)mNumSyncSamples);
    561         return ERROR_OUT_OF_RANGE;
    562     }
    563 
    564     if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples,
    565             (size_t)allocSize) != (ssize_t)allocSize) {
    566         return ERROR_IO;
    567     }
    568 
    569     for (size_t i = 0; i < mNumSyncSamples; ++i) {
    570         mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
    571     }
    572 
    573     return OK;
    574 }
    575 
    576 uint32_t SampleTable::countChunkOffsets() const {
    577     return mNumChunkOffsets;
    578 }
    579 
    580 uint32_t SampleTable::countSamples() const {
    581     return mNumSampleSizes;
    582 }
    583 
    584 status_t SampleTable::getMaxSampleSize(size_t *max_size) {
    585     Mutex::Autolock autoLock(mLock);
    586 
    587     *max_size = 0;
    588 
    589     for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
    590         size_t sample_size;
    591         status_t err = getSampleSize_l(i, &sample_size);
    592 
    593         if (err != OK) {
    594             return err;
    595         }
    596 
    597         if (sample_size > *max_size) {
    598             *max_size = sample_size;
    599         }
    600     }
    601 
    602     return OK;
    603 }
    604 
    605 uint32_t abs_difference(uint32_t time1, uint32_t time2) {
    606     return time1 > time2 ? time1 - time2 : time2 - time1;
    607 }
    608 
    609 // static
    610 int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
    611     const SampleTimeEntry *a = (const SampleTimeEntry *)_a;
    612     const SampleTimeEntry *b = (const SampleTimeEntry *)_b;
    613 
    614     if (a->mCompositionTime < b->mCompositionTime) {
    615         return -1;
    616     } else if (a->mCompositionTime > b->mCompositionTime) {
    617         return 1;
    618     }
    619 
    620     return 0;
    621 }
    622 
    623 void SampleTable::buildSampleEntriesTable() {
    624     Mutex::Autolock autoLock(mLock);
    625 
    626     if (mSampleTimeEntries != NULL || mNumSampleSizes == 0) {
    627         if (mNumSampleSizes == 0) {
    628             ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes);
    629         }
    630         return;
    631     }
    632 
    633     mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry);
    634     if (mTotalSize > kMaxTotalSize) {
    635         ALOGE("Sample entry table size would make sample table too large.\n"
    636               "    Requested sample entry table size = %llu\n"
    637               "    Eventual sample table size >= %llu\n"
    638               "    Allowed sample table size = %llu\n",
    639               (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry),
    640               (unsigned long long)mTotalSize,
    641               (unsigned long long)kMaxTotalSize);
    642         return;
    643     }
    644 
    645     mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
    646     if (!mSampleTimeEntries) {
    647         ALOGE("Cannot allocate sample entry table with %llu entries.",
    648                 (unsigned long long)mNumSampleSizes);
    649         return;
    650     }
    651 
    652     uint32_t sampleIndex = 0;
    653     uint32_t sampleTime = 0;
    654 
    655     for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
    656         uint32_t n = mTimeToSample[2 * i];
    657         uint32_t delta = mTimeToSample[2 * i + 1];
    658 
    659         for (uint32_t j = 0; j < n; ++j) {
    660             if (sampleIndex < mNumSampleSizes) {
    661                 // Technically this should always be the case if the file
    662                 // is well-formed, but you know... there's (gasp) malformed
    663                 // content out there.
    664 
    665                 mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
    666 
    667                 int32_t compTimeDelta =
    668                     mCompositionDeltaLookup->getCompositionTimeOffset(
    669                             sampleIndex);
    670 
    671                 if ((compTimeDelta < 0 && sampleTime <
    672                         (compTimeDelta == INT32_MIN ?
    673                                 INT32_MAX : uint32_t(-compTimeDelta)))
    674                         || (compTimeDelta > 0 &&
    675                                 sampleTime > UINT32_MAX - compTimeDelta)) {
    676                     ALOGE("%u + %d would overflow, clamping",
    677                             sampleTime, compTimeDelta);
    678                     if (compTimeDelta < 0) {
    679                         sampleTime = 0;
    680                     } else {
    681                         sampleTime = UINT32_MAX;
    682                     }
    683                     compTimeDelta = 0;
    684                 }
    685 
    686                 mSampleTimeEntries[sampleIndex].mCompositionTime =
    687                         compTimeDelta > 0 ? sampleTime + compTimeDelta:
    688                                 sampleTime - (-compTimeDelta);
    689             }
    690 
    691             ++sampleIndex;
    692             sampleTime += delta;
    693         }
    694     }
    695 
    696     qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry),
    697           CompareIncreasingTime);
    698 }
    699 
    700 status_t SampleTable::findSampleAtTime(
    701         uint64_t req_time, uint64_t scale_num, uint64_t scale_den,
    702         uint32_t *sample_index, uint32_t flags) {
    703     buildSampleEntriesTable();
    704 
    705     if (mSampleTimeEntries == NULL) {
    706         return ERROR_OUT_OF_RANGE;
    707     }
    708 
    709     uint32_t left = 0;
    710     uint32_t right_plus_one = mNumSampleSizes;
    711     while (left < right_plus_one) {
    712         uint32_t center = left + (right_plus_one - left) / 2;
    713         uint64_t centerTime =
    714             getSampleTime(center, scale_num, scale_den);
    715 
    716         if (req_time < centerTime) {
    717             right_plus_one = center;
    718         } else if (req_time > centerTime) {
    719             left = center + 1;
    720         } else {
    721             *sample_index = mSampleTimeEntries[center].mSampleIndex;
    722             return OK;
    723         }
    724     }
    725 
    726     uint32_t closestIndex = left;
    727 
    728     if (closestIndex == mNumSampleSizes) {
    729         if (flags == kFlagAfter) {
    730             return ERROR_OUT_OF_RANGE;
    731         }
    732         flags = kFlagBefore;
    733     } else if (closestIndex == 0) {
    734         if (flags == kFlagBefore) {
    735             // normally we should return out of range, but that is
    736             // treated as end-of-stream.  instead return first sample
    737             //
    738             // return ERROR_OUT_OF_RANGE;
    739         }
    740         flags = kFlagAfter;
    741     }
    742 
    743     switch (flags) {
    744         case kFlagBefore:
    745         {
    746             --closestIndex;
    747             break;
    748         }
    749 
    750         case kFlagAfter:
    751         {
    752             // nothing to do
    753             break;
    754         }
    755 
    756         default:
    757         {
    758             CHECK(flags == kFlagClosest);
    759             // pick closest based on timestamp. use abs_difference for safety
    760             if (abs_difference(
    761                     getSampleTime(closestIndex, scale_num, scale_den), req_time) >
    762                 abs_difference(
    763                     req_time, getSampleTime(closestIndex - 1, scale_num, scale_den))) {
    764                 --closestIndex;
    765             }
    766             break;
    767         }
    768     }
    769 
    770     *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;
    771     return OK;
    772 }
    773 
    774 status_t SampleTable::findSyncSampleNear(
    775         uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
    776     Mutex::Autolock autoLock(mLock);
    777 
    778     *sample_index = 0;
    779 
    780     if (mSyncSampleOffset < 0) {
    781         // All samples are sync-samples.
    782         *sample_index = start_sample_index;
    783         return OK;
    784     }
    785 
    786     if (mNumSyncSamples == 0) {
    787         *sample_index = 0;
    788         return OK;
    789     }
    790 
    791     uint32_t left = 0;
    792     uint32_t right_plus_one = mNumSyncSamples;
    793     while (left < right_plus_one) {
    794         uint32_t center = left + (right_plus_one - left) / 2;
    795         uint32_t x = mSyncSamples[center];
    796 
    797         if (start_sample_index < x) {
    798             right_plus_one = center;
    799         } else if (start_sample_index > x) {
    800             left = center + 1;
    801         } else {
    802             *sample_index = x;
    803             return OK;
    804         }
    805     }
    806 
    807     if (left == mNumSyncSamples) {
    808         if (flags == kFlagAfter) {
    809             ALOGE("tried to find a sync frame after the last one: %d", left);
    810             return ERROR_OUT_OF_RANGE;
    811         }
    812         flags = kFlagBefore;
    813     }
    814     else if (left == 0) {
    815         if (flags == kFlagBefore) {
    816             ALOGE("tried to find a sync frame before the first one: %d", left);
    817 
    818             // normally we should return out of range, but that is
    819             // treated as end-of-stream.  instead seek to first sync
    820             //
    821             // return ERROR_OUT_OF_RANGE;
    822         }
    823         flags = kFlagAfter;
    824     }
    825 
    826     // Now ssi[left - 1] <(=) start_sample_index <= ssi[left]
    827     switch (flags) {
    828         case kFlagBefore:
    829         {
    830             --left;
    831             break;
    832         }
    833         case kFlagAfter:
    834         {
    835             // nothing to do
    836             break;
    837         }
    838         default:
    839         {
    840             // this route is not used, but implement it nonetheless
    841             CHECK(flags == kFlagClosest);
    842 
    843             status_t err = mSampleIterator->seekTo(start_sample_index);
    844             if (err != OK) {
    845                 return err;
    846             }
    847             uint32_t sample_time = mSampleIterator->getSampleTime();
    848 
    849             err = mSampleIterator->seekTo(mSyncSamples[left]);
    850             if (err != OK) {
    851                 return err;
    852             }
    853             uint32_t upper_time = mSampleIterator->getSampleTime();
    854 
    855             err = mSampleIterator->seekTo(mSyncSamples[left - 1]);
    856             if (err != OK) {
    857                 return err;
    858             }
    859             uint32_t lower_time = mSampleIterator->getSampleTime();
    860 
    861             // use abs_difference for safety
    862             if (abs_difference(upper_time, sample_time) >
    863                 abs_difference(sample_time, lower_time)) {
    864                 --left;
    865             }
    866             break;
    867         }
    868     }
    869 
    870     *sample_index = mSyncSamples[left];
    871     return OK;
    872 }
    873 
    874 status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
    875     Mutex::Autolock autoLock(mLock);
    876 
    877     if (mSyncSampleOffset < 0) {
    878         // All samples are sync-samples.
    879         *sample_index = 0;
    880         return OK;
    881     }
    882 
    883     uint32_t bestSampleIndex = 0;
    884     size_t maxSampleSize = 0;
    885 
    886     static const size_t kMaxNumSyncSamplesToScan = 20;
    887 
    888     // Consider the first kMaxNumSyncSamplesToScan sync samples and
    889     // pick the one with the largest (compressed) size as the thumbnail.
    890 
    891     size_t numSamplesToScan = mNumSyncSamples;
    892     if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
    893         numSamplesToScan = kMaxNumSyncSamplesToScan;
    894     }
    895 
    896     for (size_t i = 0; i < numSamplesToScan; ++i) {
    897         uint32_t x = mSyncSamples[i];
    898 
    899         // Now x is a sample index.
    900         size_t sampleSize;
    901         status_t err = getSampleSize_l(x, &sampleSize);
    902         if (err != OK) {
    903             return err;
    904         }
    905 
    906         if (i == 0 || sampleSize > maxSampleSize) {
    907             bestSampleIndex = x;
    908             maxSampleSize = sampleSize;
    909         }
    910     }
    911 
    912     *sample_index = bestSampleIndex;
    913 
    914     return OK;
    915 }
    916 
    917 status_t SampleTable::getSampleSize_l(
    918         uint32_t sampleIndex, size_t *sampleSize) {
    919     return mSampleIterator->getSampleSizeDirect(
    920             sampleIndex, sampleSize);
    921 }
    922 
    923 status_t SampleTable::getMetaDataForSample(
    924         uint32_t sampleIndex,
    925         off64_t *offset,
    926         size_t *size,
    927         uint32_t *compositionTime,
    928         bool *isSyncSample,
    929         uint32_t *sampleDuration) {
    930     Mutex::Autolock autoLock(mLock);
    931 
    932     status_t err;
    933     if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
    934         return err;
    935     }
    936 
    937     if (offset) {
    938         *offset = mSampleIterator->getSampleOffset();
    939     }
    940 
    941     if (size) {
    942         *size = mSampleIterator->getSampleSize();
    943     }
    944 
    945     if (compositionTime) {
    946         *compositionTime = mSampleIterator->getSampleTime();
    947     }
    948 
    949     if (isSyncSample) {
    950         *isSyncSample = false;
    951         if (mSyncSampleOffset < 0) {
    952             // Every sample is a sync sample.
    953             *isSyncSample = true;
    954         } else {
    955             size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
    956                     && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
    957                 ? mLastSyncSampleIndex : 0;
    958 
    959             while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
    960                 ++i;
    961             }
    962 
    963             if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
    964                 *isSyncSample = true;
    965             }
    966 
    967             mLastSyncSampleIndex = i;
    968         }
    969     }
    970 
    971     if (sampleDuration) {
    972         *sampleDuration = mSampleIterator->getSampleDuration();
    973     }
    974 
    975     return OK;
    976 }
    977 
    978 int32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
    979     return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
    980 }
    981 
    982 }  // namespace android
    983 
    984