SampleTable.cpp revision 170056540e9ce65261b45efd15f67e72e2df1bed
1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2009 The Android Open Source Project
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License");
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * you may not use this file except in compliance with the License.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * You may obtain a copy of the License at
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *      http://www.apache.org/licenses/LICENSE-2.0
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * Unless required by applicable law or agreed to in writing, software
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS,
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See the License for the specific language governing permissions and
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * limitations under the License.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LOG_TAG "SampleTable"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//#define LOG_NDEBUG 0
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utils/Log.h>
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "include/SampleTable.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "include/SampleIterator.h"
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <arpa/inet.h>
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <media/stagefright/foundation/ADebug.h>
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <media/stagefright/DataSource.h>
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <media/stagefright/Utils.h>
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace android {
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const uint32_t SampleTable::kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o');
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const uint32_t SampleTable::kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static
378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// static
398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)struct SampleTable::CompositionDeltaLookup {
448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    CompositionDeltaLookup();
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    void setEntries(
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const uint32_t *deltaEntries, size_t numDeltaEntries);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t getCompositionTimeOffset(uint32_t sampleIndex);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)private:
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mutex mLock;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t *mDeltaEntries;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t mNumDeltaEntries;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t mCurrentDeltaEntry;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t mCurrentEntrySampleIndex;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DISALLOW_EVIL_CONSTRUCTORS(CompositionDeltaLookup);
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SampleTable::CompositionDeltaLookup::CompositionDeltaLookup()
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : mDeltaEntries(NULL),
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mNumDeltaEntries(0),
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      mCurrentDeltaEntry(0),
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      mCurrentEntrySampleIndex(0) {
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SampleTable::CompositionDeltaLookup::setEntries(
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const uint32_t *deltaEntries, size_t numDeltaEntries) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mutex::Autolock autolock(mLock);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mDeltaEntries = deltaEntries;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mNumDeltaEntries = numDeltaEntries;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mCurrentDeltaEntry = 0;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mCurrentEntrySampleIndex = 0;
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32_t sampleIndex) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Mutex::Autolock autolock(mLock);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mDeltaEntries == NULL) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 0;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sampleIndex < mCurrentEntrySampleIndex) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mCurrentDeltaEntry = 0;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mCurrentEntrySampleIndex = 0;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (mCurrentDeltaEntry < mNumDeltaEntries) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32_t sampleCount = mDeltaEntries[2 * mCurrentDeltaEntry];
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (sampleIndex < mCurrentEntrySampleIndex + sampleCount) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return mDeltaEntries[2 * mCurrentDeltaEntry + 1];
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mCurrentEntrySampleIndex += sampleCount;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++mCurrentDeltaEntry;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SampleTable::SampleTable(const sp<DataSource> &source)
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : mDataSource(source),
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mChunkOffsetOffset(-1),
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mChunkOffsetType(0),
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mNumChunkOffsets(0),
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mSampleToChunkOffset(-1),
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mNumSampleToChunkOffsets(0),
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mSampleSizeOffset(-1),
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mSampleSizeFieldSize(0),
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mDefaultSampleSize(0),
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mNumSampleSizes(0),
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mTimeToSampleCount(0),
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mTimeToSample(NULL),
1218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      mSampleTimeEntries(NULL),
1228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      mCompositionTimeDeltaEntries(NULL),
1238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      mNumCompositionTimeDeltaEntries(0),
1248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      mCompositionDeltaLookup(new CompositionDeltaLookup),
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mSyncSampleOffset(-1),
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mNumSyncSamples(0),
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mSyncSamples(NULL),
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mLastSyncSampleIndex(0),
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mSampleToChunkEntries(NULL) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mSampleIterator = new SampleIterator(this);
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SampleTable::~SampleTable() {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete[] mSampleToChunkEntries;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mSampleToChunkEntries = NULL;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete[] mSyncSamples;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mSyncSamples = NULL;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete mCompositionDeltaLookup;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mCompositionDeltaLookup = NULL;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete[] mCompositionTimeDeltaEntries;
1448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    mCompositionTimeDeltaEntries = NULL;
1458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    delete[] mSampleTimeEntries;
1478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    mSampleTimeEntries = NULL;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    delete[] mTimeToSample;
1508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    mTimeToSample = NULL;
1518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    delete mSampleIterator;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mSampleIterator = NULL;
1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool SampleTable::isValid() const {
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return mChunkOffsetOffset >= 0
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        && mSampleToChunkOffset >= 0
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        && mSampleSizeOffset >= 0
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        && mTimeToSample != NULL;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)status_t SampleTable::setChunkOffsetParams(
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32_t type, off64_t data_offset, size_t data_size) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mChunkOffsetOffset >= 0) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERROR_MALFORMED;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(type == kChunkOffsetType32 || type == kChunkOffsetType64);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mChunkOffsetOffset = data_offset;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mChunkOffsetType = type;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (data_size < 8) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERROR_MALFORMED;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t header[8];
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mDataSource->readAt(
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERROR_IO;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (U32_AT(header) != 0) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Expected version = 0, flags = 0.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERROR_MALFORMED;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mNumChunkOffsets = U32_AT(&header[4]);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (mChunkOffsetType == kChunkOffsetType32) {
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if (data_size < 8 + mNumChunkOffsets * 4) {
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            return ERROR_MALFORMED;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (data_size < 8 + mNumChunkOffsets * 8) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return ERROR_MALFORMED;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)status_t SampleTable::setSampleToChunkParams(
2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        off64_t data_offset, size_t data_size) {
206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (mSampleToChunkOffset >= 0) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERROR_MALFORMED;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mSampleToChunkOffset = data_offset;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (data_size < 8) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERROR_MALFORMED;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t header[8];
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mDataSource->readAt(
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERROR_IO;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (U32_AT(header) != 0) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Expected version = 0, flags = 0.
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        return ERROR_MALFORMED;
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mNumSampleToChunkOffsets = U32_AT(&header[4]);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (data_size < 8 + mNumSampleToChunkOffsets * 12) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERROR_MALFORMED;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mSampleToChunkEntries =
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new SampleToChunkEntry[mNumSampleToChunkOffsets];
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        uint8_t buffer[12];
2387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (mDataSource->readAt(
2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                    mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer))
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                != (ssize_t)sizeof(buffer)) {
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            return ERROR_IO;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CHECK(U32_AT(buffer) >= 1);  // chunk index is 1 based in the spec.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We want the chunk index to be 0-based.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)status_t SampleTable::setSampleSizeParams(
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32_t type, off64_t data_offset, size_t data_size) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mSampleSizeOffset >= 0) {
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        return ERROR_MALFORMED;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mSampleSizeOffset = data_offset;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (data_size < 12) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERROR_MALFORMED;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t header[12];
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mDataSource->readAt(
2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        return ERROR_IO;
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (U32_AT(header) != 0) {
2767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        // Expected version = 0, flags = 0.
2778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        return ERROR_MALFORMED;
2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
2797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    mDefaultSampleSize = U32_AT(&header[4]);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mNumSampleSizes = U32_AT(&header[8]);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == kSampleSizeType32) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mSampleSizeFieldSize = 32;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (mDefaultSampleSize != 0) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return OK;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (data_size < 12 + mNumSampleSizes * 4) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return ERROR_MALFORMED;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((mDefaultSampleSize & 0xffffff00) != 0) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // The high 24 bits are reserved and must be 0.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return ERROR_MALFORMED;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mSampleSizeFieldSize = mDefaultSampleSize & 0xff;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mDefaultSampleSize = 0;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            && mSampleSizeFieldSize != 16) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return ERROR_MALFORMED;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            return ERROR_MALFORMED;
3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        }
3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return OK;
3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)status_t SampleTable::setTimeToSampleParams(
3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        off64_t data_offset, size_t data_size) {
3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (mTimeToSample != NULL || data_size < 8) {
3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return ERROR_MALFORMED;
3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    uint8_t header[8];
3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (mDataSource->readAt(
3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return ERROR_IO;
3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (U32_AT(header) != 0) {
3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // Expected version = 0, flags = 0.
3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        return ERROR_MALFORMED;
3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    mTimeToSampleCount = U32_AT(&header[4]);
3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    mTimeToSample = new uint32_t[mTimeToSampleCount * 2];
3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2;
3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (mDataSource->readAt(
3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                data_offset + 8, mTimeToSample, size) < (ssize_t)size) {
3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return ERROR_IO;
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) {
3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        mTimeToSample[i] = ntohl(mTimeToSample[i]);
3438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
3448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return OK;
3468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)status_t SampleTable::setCompositionTimeToSampleParams(
349a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        off64_t data_offset, size_t data_size) {
3508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ALOGI("There are reordered frames present.");
351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
3538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        return ERROR_MALFORMED;
3548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    uint8_t header[8];
357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (mDataSource->readAt(
3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                data_offset, header, sizeof(header))
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            < (ssize_t)sizeof(header)) {
360        return ERROR_IO;
361    }
362
363    if (U32_AT(header) != 0) {
364        // Expected version = 0, flags = 0.
365        return ERROR_MALFORMED;
366    }
367
368    size_t numEntries = U32_AT(&header[4]);
369
370    if (data_size != (numEntries + 1) * 8) {
371        return ERROR_MALFORMED;
372    }
373
374    mNumCompositionTimeDeltaEntries = numEntries;
375    mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries];
376
377    if (mDataSource->readAt(
378                data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8)
379            < (ssize_t)numEntries * 8) {
380        delete[] mCompositionTimeDeltaEntries;
381        mCompositionTimeDeltaEntries = NULL;
382
383        return ERROR_IO;
384    }
385
386    for (size_t i = 0; i < 2 * numEntries; ++i) {
387        mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
388    }
389
390    mCompositionDeltaLookup->setEntries(
391            mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries);
392
393    return OK;
394}
395
396status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
397    if (mSyncSampleOffset >= 0 || data_size < 8) {
398        return ERROR_MALFORMED;
399    }
400
401    mSyncSampleOffset = data_offset;
402
403    uint8_t header[8];
404    if (mDataSource->readAt(
405                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
406        return ERROR_IO;
407    }
408
409    if (U32_AT(header) != 0) {
410        // Expected version = 0, flags = 0.
411        return ERROR_MALFORMED;
412    }
413
414    mNumSyncSamples = U32_AT(&header[4]);
415
416    if (mNumSyncSamples < 2) {
417        ALOGV("Table of sync samples is empty or has only a single entry!");
418    }
419
420    mSyncSamples = new uint32_t[mNumSyncSamples];
421    size_t size = mNumSyncSamples * sizeof(uint32_t);
422    if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size)
423            != (ssize_t)size) {
424        return ERROR_IO;
425    }
426
427    for (size_t i = 0; i < mNumSyncSamples; ++i) {
428        mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
429    }
430
431    return OK;
432}
433
434uint32_t SampleTable::countChunkOffsets() const {
435    return mNumChunkOffsets;
436}
437
438uint32_t SampleTable::countSamples() const {
439    return mNumSampleSizes;
440}
441
442status_t SampleTable::getMaxSampleSize(size_t *max_size) {
443    Mutex::Autolock autoLock(mLock);
444
445    *max_size = 0;
446
447    for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
448        size_t sample_size;
449        status_t err = getSampleSize_l(i, &sample_size);
450
451        if (err != OK) {
452            return err;
453        }
454
455        if (sample_size > *max_size) {
456            *max_size = sample_size;
457        }
458    }
459
460    return OK;
461}
462
463uint32_t abs_difference(uint32_t time1, uint32_t time2) {
464    return time1 > time2 ? time1 - time2 : time2 - time1;
465}
466
467// static
468int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
469    const SampleTimeEntry *a = (const SampleTimeEntry *)_a;
470    const SampleTimeEntry *b = (const SampleTimeEntry *)_b;
471
472    if (a->mCompositionTime < b->mCompositionTime) {
473        return -1;
474    } else if (a->mCompositionTime > b->mCompositionTime) {
475        return 1;
476    }
477
478    return 0;
479}
480
481void SampleTable::buildSampleEntriesTable() {
482    Mutex::Autolock autoLock(mLock);
483
484    if (mSampleTimeEntries != NULL) {
485        return;
486    }
487
488    mSampleTimeEntries = new SampleTimeEntry[mNumSampleSizes];
489
490    uint32_t sampleIndex = 0;
491    uint32_t sampleTime = 0;
492
493    for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
494        uint32_t n = mTimeToSample[2 * i];
495        uint32_t delta = mTimeToSample[2 * i + 1];
496
497        for (uint32_t j = 0; j < n; ++j) {
498            if (sampleIndex < mNumSampleSizes) {
499                // Technically this should always be the case if the file
500                // is well-formed, but you know... there's (gasp) malformed
501                // content out there.
502
503                mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
504
505                uint32_t compTimeDelta =
506                    mCompositionDeltaLookup->getCompositionTimeOffset(
507                            sampleIndex);
508
509                mSampleTimeEntries[sampleIndex].mCompositionTime =
510                    sampleTime + compTimeDelta;
511            }
512
513            ++sampleIndex;
514            sampleTime += delta;
515        }
516    }
517
518    qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry),
519          CompareIncreasingTime);
520}
521
522status_t SampleTable::findSampleAtTime(
523        uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
524    buildSampleEntriesTable();
525
526    uint32_t left = 0;
527    uint32_t right = mNumSampleSizes;
528    while (left < right) {
529        uint32_t center = (left + right) / 2;
530        uint32_t centerTime = mSampleTimeEntries[center].mCompositionTime;
531
532        if (req_time < centerTime) {
533            right = center;
534        } else if (req_time > centerTime) {
535            left = center + 1;
536        } else {
537            left = center;
538            break;
539        }
540    }
541
542    if (left == mNumSampleSizes) {
543        if (flags == kFlagAfter) {
544            return ERROR_OUT_OF_RANGE;
545        }
546
547        --left;
548    }
549
550    uint32_t closestIndex = left;
551
552    switch (flags) {
553        case kFlagBefore:
554        {
555            while (closestIndex > 0
556                    && mSampleTimeEntries[closestIndex].mCompositionTime
557                            > req_time) {
558                --closestIndex;
559            }
560            break;
561        }
562
563        case kFlagAfter:
564        {
565            while (closestIndex + 1 < mNumSampleSizes
566                    && mSampleTimeEntries[closestIndex].mCompositionTime
567                            < req_time) {
568                ++closestIndex;
569            }
570            break;
571        }
572
573        default:
574        {
575            CHECK(flags == kFlagClosest);
576
577            if (closestIndex > 0) {
578                // Check left neighbour and pick closest.
579                uint32_t absdiff1 =
580                    abs_difference(
581                            mSampleTimeEntries[closestIndex].mCompositionTime,
582                            req_time);
583
584                uint32_t absdiff2 =
585                    abs_difference(
586                            mSampleTimeEntries[closestIndex - 1].mCompositionTime,
587                            req_time);
588
589                if (absdiff1 > absdiff2) {
590                    closestIndex = closestIndex - 1;
591                }
592            }
593
594            break;
595        }
596    }
597
598    *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;
599
600    return OK;
601}
602
603status_t SampleTable::findSyncSampleNear(
604        uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
605    Mutex::Autolock autoLock(mLock);
606
607    *sample_index = 0;
608
609    if (mSyncSampleOffset < 0) {
610        // All samples are sync-samples.
611        *sample_index = start_sample_index;
612        return OK;
613    }
614
615    if (mNumSyncSamples == 0) {
616        *sample_index = 0;
617        return OK;
618    }
619
620    uint32_t left = 0;
621    uint32_t right = mNumSyncSamples;
622    while (left < right) {
623        uint32_t center = left + (right - left) / 2;
624        uint32_t x = mSyncSamples[center];
625
626        if (start_sample_index < x) {
627            right = center;
628        } else if (start_sample_index > x) {
629            left = center + 1;
630        } else {
631            left = center;
632            break;
633        }
634    }
635    if (left == mNumSyncSamples) {
636        if (flags == kFlagAfter) {
637            ALOGE("tried to find a sync frame after the last one: %d", left);
638            return ERROR_OUT_OF_RANGE;
639        }
640        left = left - 1;
641    }
642
643    // Now ssi[left] is the sync sample index just before (or at)
644    // start_sample_index.
645    // Also start_sample_index < ssi[left + 1], if left + 1 < mNumSyncSamples.
646
647    uint32_t x = mSyncSamples[left];
648
649    if (left + 1 < mNumSyncSamples) {
650        uint32_t y = mSyncSamples[left + 1];
651
652        // our sample lies between sync samples x and y.
653
654        status_t err = mSampleIterator->seekTo(start_sample_index);
655        if (err != OK) {
656            return err;
657        }
658
659        uint32_t sample_time = mSampleIterator->getSampleTime();
660
661        err = mSampleIterator->seekTo(x);
662        if (err != OK) {
663            return err;
664        }
665        uint32_t x_time = mSampleIterator->getSampleTime();
666
667        err = mSampleIterator->seekTo(y);
668        if (err != OK) {
669            return err;
670        }
671
672        uint32_t y_time = mSampleIterator->getSampleTime();
673
674        if (abs_difference(x_time, sample_time)
675                > abs_difference(y_time, sample_time)) {
676            // Pick the sync sample closest (timewise) to the start-sample.
677            x = y;
678            ++left;
679        }
680    }
681
682    switch (flags) {
683        case kFlagBefore:
684        {
685            if (x > start_sample_index) {
686                CHECK(left > 0);
687
688                x = mSyncSamples[left - 1];
689
690                if (x > start_sample_index) {
691                    // The table of sync sample indices was not sorted
692                    // properly.
693                    return ERROR_MALFORMED;
694                }
695            }
696            break;
697        }
698
699        case kFlagAfter:
700        {
701            if (x < start_sample_index) {
702                if (left + 1 >= mNumSyncSamples) {
703                    return ERROR_OUT_OF_RANGE;
704                }
705
706                x = mSyncSamples[left + 1];
707
708                if (x < start_sample_index) {
709                    // The table of sync sample indices was not sorted
710                    // properly.
711                    return ERROR_MALFORMED;
712                }
713            }
714
715            break;
716        }
717
718        default:
719            break;
720    }
721
722    *sample_index = x;
723
724    return OK;
725}
726
727status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
728    Mutex::Autolock autoLock(mLock);
729
730    if (mSyncSampleOffset < 0) {
731        // All samples are sync-samples.
732        *sample_index = 0;
733        return OK;
734    }
735
736    uint32_t bestSampleIndex = 0;
737    size_t maxSampleSize = 0;
738
739    static const size_t kMaxNumSyncSamplesToScan = 20;
740
741    // Consider the first kMaxNumSyncSamplesToScan sync samples and
742    // pick the one with the largest (compressed) size as the thumbnail.
743
744    size_t numSamplesToScan = mNumSyncSamples;
745    if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
746        numSamplesToScan = kMaxNumSyncSamplesToScan;
747    }
748
749    for (size_t i = 0; i < numSamplesToScan; ++i) {
750        uint32_t x = mSyncSamples[i];
751
752        // Now x is a sample index.
753        size_t sampleSize;
754        status_t err = getSampleSize_l(x, &sampleSize);
755        if (err != OK) {
756            return err;
757        }
758
759        if (i == 0 || sampleSize > maxSampleSize) {
760            bestSampleIndex = x;
761            maxSampleSize = sampleSize;
762        }
763    }
764
765    *sample_index = bestSampleIndex;
766
767    return OK;
768}
769
770status_t SampleTable::getSampleSize_l(
771        uint32_t sampleIndex, size_t *sampleSize) {
772    return mSampleIterator->getSampleSizeDirect(
773            sampleIndex, sampleSize);
774}
775
776status_t SampleTable::getMetaDataForSample(
777        uint32_t sampleIndex,
778        off64_t *offset,
779        size_t *size,
780        uint32_t *compositionTime,
781        bool *isSyncSample,
782        uint32_t *sampleDuration) {
783    Mutex::Autolock autoLock(mLock);
784
785    status_t err;
786    if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
787        return err;
788    }
789
790    if (offset) {
791        *offset = mSampleIterator->getSampleOffset();
792    }
793
794    if (size) {
795        *size = mSampleIterator->getSampleSize();
796    }
797
798    if (compositionTime) {
799        *compositionTime = mSampleIterator->getSampleTime();
800    }
801
802    if (isSyncSample) {
803        *isSyncSample = false;
804        if (mSyncSampleOffset < 0) {
805            // Every sample is a sync sample.
806            *isSyncSample = true;
807        } else {
808            size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
809                    && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
810                ? mLastSyncSampleIndex : 0;
811
812            while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
813                ++i;
814            }
815
816            if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
817                *isSyncSample = true;
818            }
819
820            mLastSyncSampleIndex = i;
821        }
822    }
823
824    if (sampleDuration) {
825        *sampleDuration = mSampleIterator->getSampleDuration();
826    }
827
828    return OK;
829}
830
831uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
832    return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
833}
834
835}  // namespace android
836
837