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