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 "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 
     30 namespace android {
     31 
     32 // static
     33 const uint32_t SampleTable::kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o');
     34 // static
     35 const uint32_t SampleTable::kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
     36 // static
     37 const uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
     38 // static
     39 const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
     40 
     41 ////////////////////////////////////////////////////////////////////////////////
     42 
     43 struct 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 
     51 private:
     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 
     63 SampleTable::CompositionDeltaLookup::CompositionDeltaLookup()
     64     : mDeltaEntries(NULL),
     65       mNumDeltaEntries(0),
     66       mCurrentDeltaEntry(0),
     67       mCurrentEntrySampleIndex(0) {
     68 }
     69 
     70 void 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 
     80 uint32_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 
    108 SampleTable::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 
    133 SampleTable::~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 
    156 bool SampleTable::isValid() const {
    157     return mChunkOffsetOffset >= 0
    158         && mSampleToChunkOffset >= 0
    159         && mSampleSizeOffset >= 0
    160         && mTimeToSample != NULL;
    161 }
    162 
    163 status_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 
    204 status_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 
    255 status_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 
    315 status_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 * 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 
    352 status_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 * 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 
    405 status_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 * 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 
    448 uint32_t SampleTable::countChunkOffsets() const {
    449     return mNumChunkOffsets;
    450 }
    451 
    452 uint32_t SampleTable::countSamples() const {
    453     return mNumSampleSizes;
    454 }
    455 
    456 status_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 
    477 uint32_t abs_difference(uint32_t time1, uint32_t time2) {
    478     return time1 > time2 ? time1 - time2 : time2 - time1;
    479 }
    480 
    481 // static
    482 int 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 
    495 void 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 
    536 status_t SampleTable::findSampleAtTime(
    537         uint64_t req_time, uint64_t scale_num, uint64_t scale_den,
    538         uint32_t *sample_index, uint32_t flags) {
    539     buildSampleEntriesTable();
    540 
    541     uint32_t left = 0;
    542     uint32_t right_plus_one = mNumSampleSizes;
    543     while (left < right_plus_one) {
    544         uint32_t center = left + (right_plus_one - left) / 2;
    545         uint64_t centerTime =
    546             getSampleTime(center, scale_num, scale_den);
    547 
    548         if (req_time < centerTime) {
    549             right_plus_one = center;
    550         } else if (req_time > centerTime) {
    551             left = center + 1;
    552         } else {
    553             *sample_index = mSampleTimeEntries[center].mSampleIndex;
    554             return OK;
    555         }
    556     }
    557 
    558     uint32_t closestIndex = left;
    559 
    560     if (closestIndex == mNumSampleSizes) {
    561         if (flags == kFlagAfter) {
    562             return ERROR_OUT_OF_RANGE;
    563         }
    564         flags = kFlagBefore;
    565     } else if (closestIndex == 0) {
    566         if (flags == kFlagBefore) {
    567             // normally we should return out of range, but that is
    568             // treated as end-of-stream.  instead return first sample
    569             //
    570             // return ERROR_OUT_OF_RANGE;
    571         }
    572         flags = kFlagAfter;
    573     }
    574 
    575     switch (flags) {
    576         case kFlagBefore:
    577         {
    578             --closestIndex;
    579             break;
    580         }
    581 
    582         case kFlagAfter:
    583         {
    584             // nothing to do
    585             break;
    586         }
    587 
    588         default:
    589         {
    590             CHECK(flags == kFlagClosest);
    591             // pick closest based on timestamp. use abs_difference for safety
    592             if (abs_difference(
    593                     getSampleTime(closestIndex, scale_num, scale_den), req_time) >
    594                 abs_difference(
    595                     req_time, getSampleTime(closestIndex - 1, scale_num, scale_den))) {
    596                 --closestIndex;
    597             }
    598             break;
    599         }
    600     }
    601 
    602     *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;
    603     return OK;
    604 }
    605 
    606 status_t SampleTable::findSyncSampleNear(
    607         uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
    608     Mutex::Autolock autoLock(mLock);
    609 
    610     *sample_index = 0;
    611 
    612     if (mSyncSampleOffset < 0) {
    613         // All samples are sync-samples.
    614         *sample_index = start_sample_index;
    615         return OK;
    616     }
    617 
    618     if (mNumSyncSamples == 0) {
    619         *sample_index = 0;
    620         return OK;
    621     }
    622 
    623     uint32_t left = 0;
    624     uint32_t right_plus_one = mNumSyncSamples;
    625     while (left < right_plus_one) {
    626         uint32_t center = left + (right_plus_one - left) / 2;
    627         uint32_t x = mSyncSamples[center];
    628 
    629         if (start_sample_index < x) {
    630             right_plus_one = center;
    631         } else if (start_sample_index > x) {
    632             left = center + 1;
    633         } else {
    634             *sample_index = x;
    635             return OK;
    636         }
    637     }
    638 
    639     if (left == mNumSyncSamples) {
    640         if (flags == kFlagAfter) {
    641             ALOGE("tried to find a sync frame after the last one: %d", left);
    642             return ERROR_OUT_OF_RANGE;
    643         }
    644         flags = kFlagBefore;
    645     }
    646     else if (left == 0) {
    647         if (flags == kFlagBefore) {
    648             ALOGE("tried to find a sync frame before the first one: %d", left);
    649 
    650             // normally we should return out of range, but that is
    651             // treated as end-of-stream.  instead seek to first sync
    652             //
    653             // return ERROR_OUT_OF_RANGE;
    654         }
    655         flags = kFlagAfter;
    656     }
    657 
    658     // Now ssi[left - 1] <(=) start_sample_index <= ssi[left]
    659     switch (flags) {
    660         case kFlagBefore:
    661         {
    662             --left;
    663             break;
    664         }
    665         case kFlagAfter:
    666         {
    667             // nothing to do
    668             break;
    669         }
    670         default:
    671         {
    672             // this route is not used, but implement it nonetheless
    673             CHECK(flags == kFlagClosest);
    674 
    675             status_t err = mSampleIterator->seekTo(start_sample_index);
    676             if (err != OK) {
    677                 return err;
    678             }
    679             uint32_t sample_time = mSampleIterator->getSampleTime();
    680 
    681             err = mSampleIterator->seekTo(mSyncSamples[left]);
    682             if (err != OK) {
    683                 return err;
    684             }
    685             uint32_t upper_time = mSampleIterator->getSampleTime();
    686 
    687             err = mSampleIterator->seekTo(mSyncSamples[left - 1]);
    688             if (err != OK) {
    689                 return err;
    690             }
    691             uint32_t lower_time = mSampleIterator->getSampleTime();
    692 
    693             // use abs_difference for safety
    694             if (abs_difference(upper_time, sample_time) >
    695                 abs_difference(sample_time, lower_time)) {
    696                 --left;
    697             }
    698             break;
    699         }
    700     }
    701 
    702     *sample_index = mSyncSamples[left];
    703     return OK;
    704 }
    705 
    706 status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
    707     Mutex::Autolock autoLock(mLock);
    708 
    709     if (mSyncSampleOffset < 0) {
    710         // All samples are sync-samples.
    711         *sample_index = 0;
    712         return OK;
    713     }
    714 
    715     uint32_t bestSampleIndex = 0;
    716     size_t maxSampleSize = 0;
    717 
    718     static const size_t kMaxNumSyncSamplesToScan = 20;
    719 
    720     // Consider the first kMaxNumSyncSamplesToScan sync samples and
    721     // pick the one with the largest (compressed) size as the thumbnail.
    722 
    723     size_t numSamplesToScan = mNumSyncSamples;
    724     if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
    725         numSamplesToScan = kMaxNumSyncSamplesToScan;
    726     }
    727 
    728     for (size_t i = 0; i < numSamplesToScan; ++i) {
    729         uint32_t x = mSyncSamples[i];
    730 
    731         // Now x is a sample index.
    732         size_t sampleSize;
    733         status_t err = getSampleSize_l(x, &sampleSize);
    734         if (err != OK) {
    735             return err;
    736         }
    737 
    738         if (i == 0 || sampleSize > maxSampleSize) {
    739             bestSampleIndex = x;
    740             maxSampleSize = sampleSize;
    741         }
    742     }
    743 
    744     *sample_index = bestSampleIndex;
    745 
    746     return OK;
    747 }
    748 
    749 status_t SampleTable::getSampleSize_l(
    750         uint32_t sampleIndex, size_t *sampleSize) {
    751     return mSampleIterator->getSampleSizeDirect(
    752             sampleIndex, sampleSize);
    753 }
    754 
    755 status_t SampleTable::getMetaDataForSample(
    756         uint32_t sampleIndex,
    757         off64_t *offset,
    758         size_t *size,
    759         uint32_t *compositionTime,
    760         bool *isSyncSample,
    761         uint32_t *sampleDuration) {
    762     Mutex::Autolock autoLock(mLock);
    763 
    764     status_t err;
    765     if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
    766         return err;
    767     }
    768 
    769     if (offset) {
    770         *offset = mSampleIterator->getSampleOffset();
    771     }
    772 
    773     if (size) {
    774         *size = mSampleIterator->getSampleSize();
    775     }
    776 
    777     if (compositionTime) {
    778         *compositionTime = mSampleIterator->getSampleTime();
    779     }
    780 
    781     if (isSyncSample) {
    782         *isSyncSample = false;
    783         if (mSyncSampleOffset < 0) {
    784             // Every sample is a sync sample.
    785             *isSyncSample = true;
    786         } else {
    787             size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
    788                     && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
    789                 ? mLastSyncSampleIndex : 0;
    790 
    791             while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
    792                 ++i;
    793             }
    794 
    795             if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
    796                 *isSyncSample = true;
    797             }
    798 
    799             mLastSyncSampleIndex = i;
    800         }
    801     }
    802 
    803     if (sampleDuration) {
    804         *sampleDuration = mSampleIterator->getSampleDuration();
    805     }
    806 
    807     return OK;
    808 }
    809 
    810 uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
    811     return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
    812 }
    813 
    814 }  // namespace android
    815 
    816