120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#define LOG_TAG "SampleTable"
18c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber//#define LOG_NDEBUG 0
1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/Log.h>
2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
211ab38dcf9bc3388c54adba8c144fd1ee018cd8c5Wonsik Kim#include <limits>
221ab38dcf9bc3388c54adba8c144fd1ee018cd8c5Wonsik Kim
2375226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen#include "SampleTable.h"
2475226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen#include "SampleIterator.h"
2589e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
282a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen#include <media/DataSourceBase.h>
2989aa8fe4cb00d2f24260005b008602232d678684Andreas Huber#include <media/stagefright/foundation/ADebug.h>
30607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang#include <media/stagefright/foundation/ByteUtils.h>
3120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
323564c4562f46bede6ef1ea716c4fd4f77e470ae8Wei Jia/* TODO: remove after being merged into other branches */
333564c4562f46bede6ef1ea716c4fd4f77e470ae8Wei Jia#ifndef UINT32_MAX
343564c4562f46bede6ef1ea716c4fd4f77e470ae8Wei Jia#define UINT32_MAX       (4294967295U)
353564c4562f46bede6ef1ea716c4fd4f77e470ae8Wei Jia#endif
363564c4562f46bede6ef1ea716c4fd4f77e470ae8Wei Jia
3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber// static
40c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huberconst uint32_t SampleTable::kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o');
41c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber// static
42c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huberconst uint32_t SampleTable::kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
43c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber// static
44c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huberconst uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
45c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber// static
46c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huberconst uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
47c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
48c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber////////////////////////////////////////////////////////////////////////////////
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
501ab38dcf9bc3388c54adba8c144fd1ee018cd8c5Wonsik Kimconst off64_t kMaxOffset = std::numeric_limits<off64_t>::max();
511ab38dcf9bc3388c54adba8c144fd1ee018cd8c5Wonsik Kim
5289aa8fe4cb00d2f24260005b008602232d678684Andreas Huberstruct SampleTable::CompositionDeltaLookup {
5389aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    CompositionDeltaLookup();
5489aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
5589aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    void setEntries(
56b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen            const int32_t *deltaEntries, size_t numDeltaEntries);
5789aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
58b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen    int32_t getCompositionTimeOffset(uint32_t sampleIndex);
5989aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
6089aa8fe4cb00d2f24260005b008602232d678684Andreas Huberprivate:
6189aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    Mutex mLock;
6289aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
63b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen    const int32_t *mDeltaEntries;
6489aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    size_t mNumDeltaEntries;
6589aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
6689aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    size_t mCurrentDeltaEntry;
6789aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    size_t mCurrentEntrySampleIndex;
6889aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
6989aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(CompositionDeltaLookup);
7089aa8fe4cb00d2f24260005b008602232d678684Andreas Huber};
7189aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
7289aa8fe4cb00d2f24260005b008602232d678684Andreas HuberSampleTable::CompositionDeltaLookup::CompositionDeltaLookup()
7389aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    : mDeltaEntries(NULL),
7489aa8fe4cb00d2f24260005b008602232d678684Andreas Huber      mNumDeltaEntries(0),
7589aa8fe4cb00d2f24260005b008602232d678684Andreas Huber      mCurrentDeltaEntry(0),
7689aa8fe4cb00d2f24260005b008602232d678684Andreas Huber      mCurrentEntrySampleIndex(0) {
7789aa8fe4cb00d2f24260005b008602232d678684Andreas Huber}
7889aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
7989aa8fe4cb00d2f24260005b008602232d678684Andreas Hubervoid SampleTable::CompositionDeltaLookup::setEntries(
80b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen        const int32_t *deltaEntries, size_t numDeltaEntries) {
8189aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    Mutex::Autolock autolock(mLock);
8289aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
8389aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    mDeltaEntries = deltaEntries;
8489aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    mNumDeltaEntries = numDeltaEntries;
8589aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    mCurrentDeltaEntry = 0;
8689aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    mCurrentEntrySampleIndex = 0;
8789aa8fe4cb00d2f24260005b008602232d678684Andreas Huber}
8889aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
89b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissenint32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
9089aa8fe4cb00d2f24260005b008602232d678684Andreas Huber        uint32_t sampleIndex) {
9189aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    Mutex::Autolock autolock(mLock);
9289aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
9389aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    if (mDeltaEntries == NULL) {
9489aa8fe4cb00d2f24260005b008602232d678684Andreas Huber        return 0;
9589aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    }
9689aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
9789aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    if (sampleIndex < mCurrentEntrySampleIndex) {
9889aa8fe4cb00d2f24260005b008602232d678684Andreas Huber        mCurrentDeltaEntry = 0;
9989aa8fe4cb00d2f24260005b008602232d678684Andreas Huber        mCurrentEntrySampleIndex = 0;
10089aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    }
10189aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
10289aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    while (mCurrentDeltaEntry < mNumDeltaEntries) {
10389aa8fe4cb00d2f24260005b008602232d678684Andreas Huber        uint32_t sampleCount = mDeltaEntries[2 * mCurrentDeltaEntry];
10489aa8fe4cb00d2f24260005b008602232d678684Andreas Huber        if (sampleIndex < mCurrentEntrySampleIndex + sampleCount) {
10589aa8fe4cb00d2f24260005b008602232d678684Andreas Huber            return mDeltaEntries[2 * mCurrentDeltaEntry + 1];
10689aa8fe4cb00d2f24260005b008602232d678684Andreas Huber        }
10789aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
10889aa8fe4cb00d2f24260005b008602232d678684Andreas Huber        mCurrentEntrySampleIndex += sampleCount;
10989aa8fe4cb00d2f24260005b008602232d678684Andreas Huber        ++mCurrentDeltaEntry;
11089aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    }
11189aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
11289aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    return 0;
11389aa8fe4cb00d2f24260005b008602232d678684Andreas Huber}
11489aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
11589aa8fe4cb00d2f24260005b008602232d678684Andreas Huber////////////////////////////////////////////////////////////////////////////////
11689aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
1172a243f08193fe9ff1afe018e9953f01c44ced9deMarco NelissenSampleTable::SampleTable(DataSourceBase *source)
11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mDataSource(source),
11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mChunkOffsetOffset(-1),
12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mChunkOffsetType(0),
12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mNumChunkOffsets(0),
12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleToChunkOffset(-1),
12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mNumSampleToChunkOffsets(0),
12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleSizeOffset(-1),
12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleSizeFieldSize(0),
12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDefaultSampleSize(0),
12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mNumSampleSizes(0),
12870dec4dc7d1d813afaff58fb26b0fd7127e897bfPawin Vongmasa      mHasTimeToSample(false),
12920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mTimeToSampleCount(0),
130583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa      mTimeToSample(NULL),
1314678a6dc5f09008481524949a9667af5a6190374Andreas Huber      mSampleTimeEntries(NULL),
1324931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber      mCompositionTimeDeltaEntries(NULL),
1334931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber      mNumCompositionTimeDeltaEntries(0),
13489aa8fe4cb00d2f24260005b008602232d678684Andreas Huber      mCompositionDeltaLookup(new CompositionDeltaLookup),
13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSyncSampleOffset(-1),
136c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber      mNumSyncSamples(0),
1378bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber      mSyncSamples(NULL),
1388bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber      mLastSyncSampleIndex(0),
139583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa      mSampleToChunkEntries(NULL),
140583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa      mTotalSize(0) {
141c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    mSampleIterator = new SampleIterator(this);
14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberSampleTable::~SampleTable() {
145c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    delete[] mSampleToChunkEntries;
146c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    mSampleToChunkEntries = NULL;
147c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
1488bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    delete[] mSyncSamples;
1498bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    mSyncSamples = NULL;
1508bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
151583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    delete[] mTimeToSample;
152583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    mTimeToSample = NULL;
153583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa
15489aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    delete mCompositionDeltaLookup;
15589aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    mCompositionDeltaLookup = NULL;
15689aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
1574931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    delete[] mCompositionTimeDeltaEntries;
1584931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    mCompositionTimeDeltaEntries = NULL;
1594931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
1604678a6dc5f09008481524949a9667af5a6190374Andreas Huber    delete[] mSampleTimeEntries;
1614678a6dc5f09008481524949a9667af5a6190374Andreas Huber    mSampleTimeEntries = NULL;
1624678a6dc5f09008481524949a9667af5a6190374Andreas Huber
163c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    delete mSampleIterator;
164c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    mSampleIterator = NULL;
16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
167169c286ed166499c5099d2b336967e0bf3d25551Andreas Huberbool SampleTable::isValid() const {
168169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    return mChunkOffsetOffset >= 0
169169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        && mSampleToChunkOffset >= 0
170169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        && mSampleSizeOffset >= 0
17170dec4dc7d1d813afaff58fb26b0fd7127e897bfPawin Vongmasa        && mHasTimeToSample;
172169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber}
173169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber
17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t SampleTable::setChunkOffsetParams(
175c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        uint32_t type, off64_t data_offset, size_t data_size) {
17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mChunkOffsetOffset >= 0) {
17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
17920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1800c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(type == kChunkOffsetType32 || type == kChunkOffsetType64);
18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mChunkOffsetOffset = data_offset;
18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mChunkOffsetType = type;
18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (data_size < 8) {
18620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
19034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(
19120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
19220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
19420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (U32_AT(header) != 0) {
19620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // Expected version = 0, flags = 0.
19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mNumChunkOffsets = U32_AT(&header[4]);
20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mChunkOffsetType == kChunkOffsetType32) {
203ffd7950633edeb8e990770e4c8abb81bdcaa6f32Dan Austin      if ((data_size - 8) / 4 < mNumChunkOffsets) {
20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_MALFORMED;
20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
207ffd7950633edeb8e990770e4c8abb81bdcaa6f32Dan Austin      if ((data_size - 8) / 8 < mNumChunkOffsets) {
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_MALFORMED;
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t SampleTable::setSampleToChunkParams(
216c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, size_t data_size) {
21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mSampleToChunkOffset >= 0) {
2181cb23b033987e86827a4fa96550c6a3670b688f1Marco Nelissen        // already set
2191cb23b033987e86827a4fa96550c6a3670b688f1Marco Nelissen        return ERROR_MALFORMED;
2201cb23b033987e86827a4fa96550c6a3670b688f1Marco Nelissen    }
2211cb23b033987e86827a4fa96550c6a3670b688f1Marco Nelissen
2221cb23b033987e86827a4fa96550c6a3670b688f1Marco Nelissen    if (data_offset < 0) {
22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mSampleToChunkOffset = data_offset;
22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (data_size < 8) {
22920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
23120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
23334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(
23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
23520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
23620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (U32_AT(header) != 0) {
23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // Expected version = 0, flags = 0.
24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mNumSampleToChunkOffsets = U32_AT(&header[4]);
24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2451ab38dcf9bc3388c54adba8c144fd1ee018cd8c5Wonsik Kim    if ((data_size - 8) / sizeof(SampleToChunkEntry) < mNumSampleToChunkOffsets) {
24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2491ab38dcf9bc3388c54adba8c144fd1ee018cd8c5Wonsik Kim    if ((uint64_t)kMaxTotalSize / sizeof(SampleToChunkEntry) <=
250583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa            (uint64_t)mNumSampleToChunkOffsets) {
251583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Sample-to-chunk table size too large.");
2525c134e6b2047b10877f02a46f4bb293537269f00Joshua J. Drake        return ERROR_OUT_OF_RANGE;
253583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    }
254583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa
255583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    mTotalSize += (uint64_t)mNumSampleToChunkOffsets *
256583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa            sizeof(SampleToChunkEntry);
257583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    if (mTotalSize > kMaxTotalSize) {
258583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Sample-to-chunk table size would make sample table too large.\n"
259583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Requested sample-to-chunk table size = %llu\n"
260583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Eventual sample table size >= %llu\n"
261583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Allowed sample table size = %llu\n",
262583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)mNumSampleToChunkOffsets *
263583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa                      sizeof(SampleToChunkEntry),
264583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)mTotalSize,
265583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)kMaxTotalSize);
266c24607c29c96f939aed9e33bfa702b1dd79da4b7Joshua J. Drake        return ERROR_OUT_OF_RANGE;
267583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    }
268c24607c29c96f939aed9e33bfa702b1dd79da4b7Joshua J. Drake
269c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    mSampleToChunkEntries =
270ad435371a4b95e16ceb49ab28efc04da8b3680e1Joshua J. Drake        new (std::nothrow) SampleToChunkEntry[mNumSampleToChunkOffsets];
271583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    if (!mSampleToChunkEntries) {
272583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Cannot allocate sample-to-chunk table with %llu entries.",
273583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa                (unsigned long long)mNumSampleToChunkOffsets);
274ad435371a4b95e16ceb49ab28efc04da8b3680e1Joshua J. Drake        return ERROR_OUT_OF_RANGE;
275583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    }
276583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa
277583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    if (mNumSampleToChunkOffsets == 0) {
278583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        return OK;
279583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    }
280583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa
2811ab38dcf9bc3388c54adba8c144fd1ee018cd8c5Wonsik Kim    if ((off64_t)(kMaxOffset - 8 -
282583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa            ((mNumSampleToChunkOffsets - 1) * sizeof(SampleToChunkEntry)))
283583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa            < mSampleToChunkOffset) {
284583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        return ERROR_MALFORMED;
285583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    }
286c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
287c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
2881ab38dcf9bc3388c54adba8c144fd1ee018cd8c5Wonsik Kim        uint8_t buffer[sizeof(SampleToChunkEntry)];
289ffd7950633edeb8e990770e4c8abb81bdcaa6f32Dan Austin
290c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        if (mDataSource->readAt(
2911ab38dcf9bc3388c54adba8c144fd1ee018cd8c5Wonsik Kim                    mSampleToChunkOffset + 8 + i * sizeof(SampleToChunkEntry),
2921ab38dcf9bc3388c54adba8c144fd1ee018cd8c5Wonsik Kim                    buffer,
2931ab38dcf9bc3388c54adba8c144fd1ee018cd8c5Wonsik Kim                    sizeof(buffer))
294c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                != (ssize_t)sizeof(buffer)) {
295c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            return ERROR_IO;
296c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        }
297dafa42d49dd70d745697662750bb6040429ee76cMarco Nelissen        // chunk index is 1 based in the spec.
298dafa42d49dd70d745697662750bb6040429ee76cMarco Nelissen        if (U32_AT(buffer) < 1) {
299dafa42d49dd70d745697662750bb6040429ee76cMarco Nelissen            ALOGE("b/23534160");
300dafa42d49dd70d745697662750bb6040429ee76cMarco Nelissen            return ERROR_OUT_OF_RANGE;
301dafa42d49dd70d745697662750bb6040429ee76cMarco Nelissen        }
302c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
303c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        // We want the chunk index to be 0-based.
304c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
305c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]);
306c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]);
307c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    }
308c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t SampleTable::setSampleSizeParams(
313c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        uint32_t type, off64_t data_offset, size_t data_size) {
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mSampleSizeOffset >= 0) {
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3180c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact);
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mSampleSizeOffset = data_offset;
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (data_size < 12) {
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[12];
32734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (U32_AT(header) != 0) {
33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // Expected version = 0, flags = 0.
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDefaultSampleSize = U32_AT(&header[4]);
33820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mNumSampleSizes = U32_AT(&header[8]);
3393564c4562f46bede6ef1ea716c4fd4f77e470ae8Wei Jia    if (mNumSampleSizes > (UINT32_MAX - 12) / 16) {
340c27cee30d9359fa83e33b4f87f88e6bb9ef66341Wei Jia        ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes);
3413564c4562f46bede6ef1ea716c4fd4f77e470ae8Wei Jia        return ERROR_MALFORMED;
3423564c4562f46bede6ef1ea716c4fd4f77e470ae8Wei Jia    }
34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (type == kSampleSizeType32) {
34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mSampleSizeFieldSize = 32;
34620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mDefaultSampleSize != 0) {
34820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return OK;
34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (data_size < 12 + mNumSampleSizes * 4) {
35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_MALFORMED;
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if ((mDefaultSampleSize & 0xffffff00) != 0) {
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            // The high 24 bits are reserved and must be 0.
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_MALFORMED;
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3609f753df58a70f20db220af31cb202bbd21b30f36Andreas Huber        mSampleSizeFieldSize = mDefaultSampleSize & 0xff;
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mDefaultSampleSize = 0;
36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            && mSampleSizeFieldSize != 16) {
36520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_MALFORMED;
36620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
36720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_MALFORMED;
37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t SampleTable::setTimeToSampleParams(
377c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, size_t data_size) {
37870dec4dc7d1d813afaff58fb26b0fd7127e897bfPawin Vongmasa    if (mHasTimeToSample || data_size < 8) {
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
38120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
38334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(
38420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
38720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (U32_AT(header) != 0) {
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // Expected version = 0, flags = 0.
39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTimeToSampleCount = U32_AT(&header[4]);
3941ab38dcf9bc3388c54adba8c144fd1ee018cd8c5Wonsik Kim    if (mTimeToSampleCount > UINT32_MAX / (2 * sizeof(uint32_t))) {
395a3630a418b4f65277a42cd4018cd3b0b7e134d0cPawin Vongmasa        // Choose this bound because
396a3630a418b4f65277a42cd4018cd3b0b7e134d0cPawin Vongmasa        // 1) 2 * sizeof(uint32_t) is the amount of memory needed for one
397a3630a418b4f65277a42cd4018cd3b0b7e134d0cPawin Vongmasa        //    time-to-sample entry in the time-to-sample table.
398a3630a418b4f65277a42cd4018cd3b0b7e134d0cPawin Vongmasa        // 2) mTimeToSampleCount is the number of entries of the time-to-sample
399a3630a418b4f65277a42cd4018cd3b0b7e134d0cPawin Vongmasa        //    table.
400a3630a418b4f65277a42cd4018cd3b0b7e134d0cPawin Vongmasa        // 3) We hope that the table size does not exceed UINT32_MAX.
401583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Time-to-sample table size too large.");
402edd4a76eb4747bd19ed122df46fa46b452c12a0dRobert Shih        return ERROR_OUT_OF_RANGE;
403edd4a76eb4747bd19ed122df46fa46b452c12a0dRobert Shih    }
40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
405a3630a418b4f65277a42cd4018cd3b0b7e134d0cPawin Vongmasa    // Note: At this point, we know that mTimeToSampleCount * 2 will not
406a3630a418b4f65277a42cd4018cd3b0b7e134d0cPawin Vongmasa    // overflow because of the above condition.
407583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa
408583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
409583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    mTotalSize += allocSize;
410583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    if (mTotalSize > kMaxTotalSize) {
411583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Time-to-sample table size would make sample table too large.\n"
412583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Requested time-to-sample table size = %llu\n"
413583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Eventual sample table size >= %llu\n"
414583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Allowed sample table size = %llu\n",
415583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)allocSize,
416583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)mTotalSize,
417583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)kMaxTotalSize);
418583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        return ERROR_OUT_OF_RANGE;
419583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    }
420583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa
421583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2];
422583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    if (!mTimeToSample) {
423583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Cannot allocate time-to-sample table with %llu entries.",
424583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa                (unsigned long long)mTimeToSampleCount);
425583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        return ERROR_OUT_OF_RANGE;
426583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    }
427583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa
428583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    if (mDataSource->readAt(data_offset + 8, mTimeToSample,
429583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa            (size_t)allocSize) < (ssize_t)allocSize) {
430583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Incomplete data read for time-to-sample table.");
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
434583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    for (size_t i = 0; i < mTimeToSampleCount * 2; ++i) {
435583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        mTimeToSample[i] = ntohl(mTimeToSample[i]);
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
43770dec4dc7d1d813afaff58fb26b0fd7127e897bfPawin Vongmasa
43870dec4dc7d1d813afaff58fb26b0fd7127e897bfPawin Vongmasa    mHasTimeToSample = true;
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
44120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
442b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen// NOTE: per 14996-12, version 0 ctts contains unsigned values, while version 1
443b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen// contains signed values, however some software creates version 0 files that
444b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen// contain signed values, so we're always treating the values as signed,
445b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen// regardless of version.
4464931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huberstatus_t SampleTable::setCompositionTimeToSampleParams(
4474931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        off64_t data_offset, size_t data_size) {
448df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("There are reordered frames present.");
4494931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
4504931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
4514931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        return ERROR_MALFORMED;
4524931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
4534931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
4544931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    uint8_t header[8];
4554931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    if (mDataSource->readAt(
4564931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                data_offset, header, sizeof(header))
4574931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            < (ssize_t)sizeof(header)) {
4584931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        return ERROR_IO;
4594931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
4604931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
461b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen    uint32_t flags = U32_AT(header);
462b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen    uint32_t version = flags >> 24;
463b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen    flags &= 0xffffff;
464b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen
465b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen    if ((version != 0 && version != 1) || flags != 0) {
466b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen        // Expected version = 0 or 1, flags = 0.
4674931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        return ERROR_MALFORMED;
4684931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
4694931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
4704931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    size_t numEntries = U32_AT(&header[4]);
4714931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
472ffd7950633edeb8e990770e4c8abb81bdcaa6f32Dan Austin    if (((SIZE_MAX / 8) - 1 < numEntries) || (data_size != (numEntries + 1) * 8)) {
4734931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        return ERROR_MALFORMED;
4744931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
4754931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
4764931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    mNumCompositionTimeDeltaEntries = numEntries;
477978a6cd08746164ee1f37405d55e0f0bed8f8c24Pawin Vongmasa    uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(int32_t);
4781ab38dcf9bc3388c54adba8c144fd1ee018cd8c5Wonsik Kim    if (allocSize > kMaxTotalSize) {
479583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Composition-time-to-sample table size too large.");
480edd4a76eb4747bd19ed122df46fa46b452c12a0dRobert Shih        return ERROR_OUT_OF_RANGE;
481edd4a76eb4747bd19ed122df46fa46b452c12a0dRobert Shih    }
482edd4a76eb4747bd19ed122df46fa46b452c12a0dRobert Shih
483583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    mTotalSize += allocSize;
484583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    if (mTotalSize > kMaxTotalSize) {
485583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Composition-time-to-sample table would make sample table too large.\n"
486583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Requested composition-time-to-sample table size = %llu\n"
487583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Eventual sample table size >= %llu\n"
488583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Allowed sample table size = %llu\n",
489583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)allocSize,
490583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)mTotalSize,
491583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)kMaxTotalSize);
492edd4a76eb4747bd19ed122df46fa46b452c12a0dRobert Shih        return ERROR_OUT_OF_RANGE;
493edd4a76eb4747bd19ed122df46fa46b452c12a0dRobert Shih    }
494edd4a76eb4747bd19ed122df46fa46b452c12a0dRobert Shih
495b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen    mCompositionTimeDeltaEntries = new (std::nothrow) int32_t[2 * numEntries];
496583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    if (!mCompositionTimeDeltaEntries) {
497583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Cannot allocate composition-time-to-sample table with %llu "
498583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa                "entries.", (unsigned long long)numEntries);
499ad435371a4b95e16ceb49ab28efc04da8b3680e1Joshua J. Drake        return ERROR_OUT_OF_RANGE;
500583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    }
5014931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
502583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    if (mDataSource->readAt(data_offset + 8, mCompositionTimeDeltaEntries,
503583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa            (size_t)allocSize) < (ssize_t)allocSize) {
5044931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        delete[] mCompositionTimeDeltaEntries;
5054931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        mCompositionTimeDeltaEntries = NULL;
5064931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
5074931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        return ERROR_IO;
5084931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
5094931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
5104931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    for (size_t i = 0; i < 2 * numEntries; ++i) {
5114931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
5124931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
5134931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
51489aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    mCompositionDeltaLookup->setEntries(
51589aa8fe4cb00d2f24260005b008602232d678684Andreas Huber            mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries);
51689aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
5174931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    return OK;
5184931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber}
5194931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
520c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
52120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mSyncSampleOffset >= 0 || data_size < 8) {
52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
52634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(
52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (U32_AT(header) != 0) {
53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // Expected version = 0, flags = 0.
53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
536a9660fe122ca382e1777e0c5d3c42ca67ffb0377Marco Nelissen    uint32_t numSyncSamples = U32_AT(&header[4]);
53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
538a9660fe122ca382e1777e0c5d3c42ca67ffb0377Marco Nelissen    if (numSyncSamples < 2) {
5393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Table of sync samples is empty or has only a single entry!");
54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
5418bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
542a9660fe122ca382e1777e0c5d3c42ca67ffb0377Marco Nelissen    uint64_t allocSize = (uint64_t)numSyncSamples * sizeof(uint32_t);
5431ab38dcf9bc3388c54adba8c144fd1ee018cd8c5Wonsik Kim    if (allocSize > kMaxTotalSize) {
544583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Sync sample table size too large.");
545edd4a76eb4747bd19ed122df46fa46b452c12a0dRobert Shih        return ERROR_OUT_OF_RANGE;
546edd4a76eb4747bd19ed122df46fa46b452c12a0dRobert Shih    }
547edd4a76eb4747bd19ed122df46fa46b452c12a0dRobert Shih
548583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    mTotalSize += allocSize;
549583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    if (mTotalSize > kMaxTotalSize) {
550583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Sync sample table size would make sample table too large.\n"
551583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Requested sync sample table size = %llu\n"
552583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Eventual sample table size >= %llu\n"
553583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Allowed sample table size = %llu\n",
554583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)allocSize,
555583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)mTotalSize,
556583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)kMaxTotalSize);
557edd4a76eb4747bd19ed122df46fa46b452c12a0dRobert Shih        return ERROR_OUT_OF_RANGE;
558edd4a76eb4747bd19ed122df46fa46b452c12a0dRobert Shih    }
559edd4a76eb4747bd19ed122df46fa46b452c12a0dRobert Shih
560a9660fe122ca382e1777e0c5d3c42ca67ffb0377Marco Nelissen    mSyncSamples = new (std::nothrow) uint32_t[numSyncSamples];
561583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    if (!mSyncSamples) {
562583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Cannot allocate sync sample table with %llu entries.",
563a9660fe122ca382e1777e0c5d3c42ca67ffb0377Marco Nelissen                (unsigned long long)numSyncSamples);
564ad435371a4b95e16ceb49ab28efc04da8b3680e1Joshua J. Drake        return ERROR_OUT_OF_RANGE;
565583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    }
566ad435371a4b95e16ceb49ab28efc04da8b3680e1Joshua J. Drake
567a9660fe122ca382e1777e0c5d3c42ca67ffb0377Marco Nelissen    if (mDataSource->readAt(data_offset + 8, mSyncSamples,
568583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa            (size_t)allocSize) != (ssize_t)allocSize) {
569158c197b668ad684f92829db6a31bee3aec794baCaroline Tice        delete[] mSyncSamples;
570a9660fe122ca382e1777e0c5d3c42ca67ffb0377Marco Nelissen        mSyncSamples = NULL;
5718bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        return ERROR_IO;
5728bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    }
5738bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
574a9660fe122ca382e1777e0c5d3c42ca67ffb0377Marco Nelissen    for (size_t i = 0; i < numSyncSamples; ++i) {
575698616546b4f2936c8bbf0dee0f8139ebc446278Roger        if (mSyncSamples[i] == 0) {
576698616546b4f2936c8bbf0dee0f8139ebc446278Roger            ALOGE("b/32423862, unexpected zero value in stss");
577698616546b4f2936c8bbf0dee0f8139ebc446278Roger            continue;
578698616546b4f2936c8bbf0dee0f8139ebc446278Roger        }
5798bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
5808bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    }
5818bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
582a9660fe122ca382e1777e0c5d3c42ca67ffb0377Marco Nelissen    mSyncSampleOffset = data_offset;
583a9660fe122ca382e1777e0c5d3c42ca67ffb0377Marco Nelissen    mNumSyncSamples = numSyncSamples;
584a9660fe122ca382e1777e0c5d3c42ca67ffb0377Marco Nelissen
58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberuint32_t SampleTable::countChunkOffsets() const {
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mNumChunkOffsets;
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberuint32_t SampleTable::countSamples() const {
59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mNumSampleSizes;
59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t SampleTable::getMaxSampleSize(size_t *max_size) {
59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Mutex::Autolock autoLock(mLock);
59820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *max_size = 0;
60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t sample_size;
603c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err = getSampleSize_l(i, &sample_size);
604da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber
60520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
60820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (sample_size > *max_size) {
61020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *max_size = sample_size;
61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
61220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
61520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
61620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
617da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huberuint32_t abs_difference(uint32_t time1, uint32_t time2) {
618da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber    return time1 > time2 ? time1 - time2 : time2 - time1;
619da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber}
620da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber
6214678a6dc5f09008481524949a9667af5a6190374Andreas Huber// static
6224678a6dc5f09008481524949a9667af5a6190374Andreas Huberint SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
6234678a6dc5f09008481524949a9667af5a6190374Andreas Huber    const SampleTimeEntry *a = (const SampleTimeEntry *)_a;
6244678a6dc5f09008481524949a9667af5a6190374Andreas Huber    const SampleTimeEntry *b = (const SampleTimeEntry *)_b;
6254931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
6264678a6dc5f09008481524949a9667af5a6190374Andreas Huber    if (a->mCompositionTime < b->mCompositionTime) {
6274678a6dc5f09008481524949a9667af5a6190374Andreas Huber        return -1;
6284678a6dc5f09008481524949a9667af5a6190374Andreas Huber    } else if (a->mCompositionTime > b->mCompositionTime) {
6294678a6dc5f09008481524949a9667af5a6190374Andreas Huber        return 1;
6304678a6dc5f09008481524949a9667af5a6190374Andreas Huber    }
631abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
6324678a6dc5f09008481524949a9667af5a6190374Andreas Huber    return 0;
6334678a6dc5f09008481524949a9667af5a6190374Andreas Huber}
6344678a6dc5f09008481524949a9667af5a6190374Andreas Huber
6354678a6dc5f09008481524949a9667af5a6190374Andreas Hubervoid SampleTable::buildSampleEntriesTable() {
63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Mutex::Autolock autoLock(mLock);
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6383564c4562f46bede6ef1ea716c4fd4f77e470ae8Wei Jia    if (mSampleTimeEntries != NULL || mNumSampleSizes == 0) {
639cccd2e5e3aa015d6ce96ba0245b7161c077cdba2Wei Jia        if (mNumSampleSizes == 0) {
640cccd2e5e3aa015d6ce96ba0245b7161c077cdba2Wei Jia            ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes);
641cccd2e5e3aa015d6ce96ba0245b7161c077cdba2Wei Jia        }
6424678a6dc5f09008481524949a9667af5a6190374Andreas Huber        return;
6434678a6dc5f09008481524949a9667af5a6190374Andreas Huber    }
6444678a6dc5f09008481524949a9667af5a6190374Andreas Huber
645583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry);
646583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    if (mTotalSize > kMaxTotalSize) {
647583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Sample entry table size would make sample table too large.\n"
648583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Requested sample entry table size = %llu\n"
649583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Eventual sample table size >= %llu\n"
650583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              "    Allowed sample table size = %llu\n",
651583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry),
652583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)mTotalSize,
653583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa              (unsigned long long)kMaxTotalSize);
654583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        return;
655583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    }
656583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa
657ad435371a4b95e16ceb49ab28efc04da8b3680e1Joshua J. Drake    mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
658583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    if (!mSampleTimeEntries) {
659583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa        ALOGE("Cannot allocate sample entry table with %llu entries.",
660583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa                (unsigned long long)mNumSampleSizes);
661ad435371a4b95e16ceb49ab28efc04da8b3680e1Joshua J. Drake        return;
662583a012a9fce81162b163d3533e2644d4abad88aPawin Vongmasa    }
6634678a6dc5f09008481524949a9667af5a6190374Andreas Huber
6644678a6dc5f09008481524949a9667af5a6190374Andreas Huber    uint32_t sampleIndex = 0;
6654678a6dc5f09008481524949a9667af5a6190374Andreas Huber    uint32_t sampleTime = 0;
6664678a6dc5f09008481524949a9667af5a6190374Andreas Huber
66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
66820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t n = mTimeToSample[2 * i];
66920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t delta = mTimeToSample[2 * i + 1];
67020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6714678a6dc5f09008481524949a9667af5a6190374Andreas Huber        for (uint32_t j = 0; j < n; ++j) {
67265a2670e84f44f6cdd80d625a7248fc65319ab8cAndreas Huber            if (sampleIndex < mNumSampleSizes) {
67365a2670e84f44f6cdd80d625a7248fc65319ab8cAndreas Huber                // Technically this should always be the case if the file
67465a2670e84f44f6cdd80d625a7248fc65319ab8cAndreas Huber                // is well-formed, but you know... there's (gasp) malformed
67565a2670e84f44f6cdd80d625a7248fc65319ab8cAndreas Huber                // content out there.
67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67765a2670e84f44f6cdd80d625a7248fc65319ab8cAndreas Huber                mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
678abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
679b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                int32_t compTimeDelta =
68089aa8fe4cb00d2f24260005b008602232d678684Andreas Huber                    mCompositionDeltaLookup->getCompositionTimeOffset(
68189aa8fe4cb00d2f24260005b008602232d678684Andreas Huber                            sampleIndex);
68289aa8fe4cb00d2f24260005b008602232d678684Andreas Huber
683b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                if ((compTimeDelta < 0 && sampleTime <
684b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                        (compTimeDelta == INT32_MIN ?
685b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                                INT32_MAX : uint32_t(-compTimeDelta)))
686b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                        || (compTimeDelta > 0 &&
687b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                                sampleTime > UINT32_MAX - compTimeDelta)) {
688b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                    ALOGE("%u + %d would overflow, clamping",
689b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                            sampleTime, compTimeDelta);
690b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                    if (compTimeDelta < 0) {
691b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                        sampleTime = 0;
692b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                    } else {
693b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                        sampleTime = UINT32_MAX;
694b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                    }
695b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                    compTimeDelta = 0;
696b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                }
697b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen
69865a2670e84f44f6cdd80d625a7248fc65319ab8cAndreas Huber                mSampleTimeEntries[sampleIndex].mCompositionTime =
699b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                        compTimeDelta > 0 ? sampleTime + compTimeDelta:
700b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissen                                sampleTime - (-compTimeDelta);
70165a2670e84f44f6cdd80d625a7248fc65319ab8cAndreas Huber            }
7024678a6dc5f09008481524949a9667af5a6190374Andreas Huber
7034678a6dc5f09008481524949a9667af5a6190374Andreas Huber            ++sampleIndex;
704ed80276361a18380bacc22bde92689e0e4901726Bartosz Bialek            if (sampleTime > UINT32_MAX - delta) {
705ed80276361a18380bacc22bde92689e0e4901726Bartosz Bialek                ALOGE("%u + %u would overflow, clamping",
706ed80276361a18380bacc22bde92689e0e4901726Bartosz Bialek                    sampleTime, delta);
707ed80276361a18380bacc22bde92689e0e4901726Bartosz Bialek                sampleTime = UINT32_MAX;
708ed80276361a18380bacc22bde92689e0e4901726Bartosz Bialek            } else {
709ed80276361a18380bacc22bde92689e0e4901726Bartosz Bialek                sampleTime += delta;
710ed80276361a18380bacc22bde92689e0e4901726Bartosz Bialek            }
7114678a6dc5f09008481524949a9667af5a6190374Andreas Huber        }
7124678a6dc5f09008481524949a9667af5a6190374Andreas Huber    }
7134678a6dc5f09008481524949a9667af5a6190374Andreas Huber
7144678a6dc5f09008481524949a9667af5a6190374Andreas Huber    qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry),
7154678a6dc5f09008481524949a9667af5a6190374Andreas Huber          CompareIncreasingTime);
7164678a6dc5f09008481524949a9667af5a6190374Andreas Huber}
7174678a6dc5f09008481524949a9667af5a6190374Andreas Huber
7184678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t SampleTable::findSampleAtTime(
719599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar        uint64_t req_time, uint64_t scale_num, uint64_t scale_den,
720599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar        uint32_t *sample_index, uint32_t flags) {
7214678a6dc5f09008481524949a9667af5a6190374Andreas Huber    buildSampleEntriesTable();
7224678a6dc5f09008481524949a9667af5a6190374Andreas Huber
7233564c4562f46bede6ef1ea716c4fd4f77e470ae8Wei Jia    if (mSampleTimeEntries == NULL) {
7243564c4562f46bede6ef1ea716c4fd4f77e470ae8Wei Jia        return ERROR_OUT_OF_RANGE;
7253564c4562f46bede6ef1ea716c4fd4f77e470ae8Wei Jia    }
7263564c4562f46bede6ef1ea716c4fd4f77e470ae8Wei Jia
727d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang    if (flags == kFlagFrameIndex) {
728d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang        if (req_time >= mNumSampleSizes) {
729d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang            return ERROR_OUT_OF_RANGE;
730d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang        }
731d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang        *sample_index = mSampleTimeEntries[req_time].mSampleIndex;
732d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang        return OK;
733d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang    }
734d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang
7354678a6dc5f09008481524949a9667af5a6190374Andreas Huber    uint32_t left = 0;
736225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar    uint32_t right_plus_one = mNumSampleSizes;
737225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar    while (left < right_plus_one) {
738225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar        uint32_t center = left + (right_plus_one - left) / 2;
739599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar        uint64_t centerTime =
740599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            getSampleTime(center, scale_num, scale_den);
7414678a6dc5f09008481524949a9667af5a6190374Andreas Huber
7424678a6dc5f09008481524949a9667af5a6190374Andreas Huber        if (req_time < centerTime) {
743225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar            right_plus_one = center;
7444678a6dc5f09008481524949a9667af5a6190374Andreas Huber        } else if (req_time > centerTime) {
7454678a6dc5f09008481524949a9667af5a6190374Andreas Huber            left = center + 1;
7464678a6dc5f09008481524949a9667af5a6190374Andreas Huber        } else {
747599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            *sample_index = mSampleTimeEntries[center].mSampleIndex;
748599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            return OK;
7494678a6dc5f09008481524949a9667af5a6190374Andreas Huber        }
7504678a6dc5f09008481524949a9667af5a6190374Andreas Huber    }
7514678a6dc5f09008481524949a9667af5a6190374Andreas Huber
752599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar    uint32_t closestIndex = left;
753599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar
754599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar    if (closestIndex == mNumSampleSizes) {
755a488c7daf91357611fcdbff7a32e5a73ec630070Andreas Huber        if (flags == kFlagAfter) {
756a488c7daf91357611fcdbff7a32e5a73ec630070Andreas Huber            return ERROR_OUT_OF_RANGE;
757a488c7daf91357611fcdbff7a32e5a73ec630070Andreas Huber        }
758599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar        flags = kFlagBefore;
759599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar    } else if (closestIndex == 0) {
760599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar        if (flags == kFlagBefore) {
761599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            // normally we should return out of range, but that is
762599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            // treated as end-of-stream.  instead return first sample
763599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            //
764599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            // return ERROR_OUT_OF_RANGE;
765599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar        }
766599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar        flags = kFlagAfter;
7674678a6dc5f09008481524949a9667af5a6190374Andreas Huber    }
7684678a6dc5f09008481524949a9667af5a6190374Andreas Huber
7694678a6dc5f09008481524949a9667af5a6190374Andreas Huber    switch (flags) {
7704678a6dc5f09008481524949a9667af5a6190374Andreas Huber        case kFlagBefore:
7714678a6dc5f09008481524949a9667af5a6190374Andreas Huber        {
772599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            --closestIndex;
7734678a6dc5f09008481524949a9667af5a6190374Andreas Huber            break;
7744678a6dc5f09008481524949a9667af5a6190374Andreas Huber        }
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7764678a6dc5f09008481524949a9667af5a6190374Andreas Huber        case kFlagAfter:
7774678a6dc5f09008481524949a9667af5a6190374Andreas Huber        {
778599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            // nothing to do
7794678a6dc5f09008481524949a9667af5a6190374Andreas Huber            break;
78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7824678a6dc5f09008481524949a9667af5a6190374Andreas Huber        default:
7834678a6dc5f09008481524949a9667af5a6190374Andreas Huber        {
7844678a6dc5f09008481524949a9667af5a6190374Andreas Huber            CHECK(flags == kFlagClosest);
785599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            // pick closest based on timestamp. use abs_difference for safety
786599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            if (abs_difference(
787599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                    getSampleTime(closestIndex, scale_num, scale_den), req_time) >
788599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                abs_difference(
789599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                    req_time, getSampleTime(closestIndex - 1, scale_num, scale_den))) {
790599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                --closestIndex;
7914678a6dc5f09008481524949a9667af5a6190374Andreas Huber            }
7924678a6dc5f09008481524949a9667af5a6190374Andreas Huber            break;
7934678a6dc5f09008481524949a9667af5a6190374Andreas Huber        }
79420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7964678a6dc5f09008481524949a9667af5a6190374Andreas Huber    *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;
7974678a6dc5f09008481524949a9667af5a6190374Andreas Huber    return OK;
79820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
79920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
800abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huberstatus_t SampleTable::findSyncSampleNear(
801abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
802abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    Mutex::Autolock autoLock(mLock);
803abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *sample_index = 0;
80520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mSyncSampleOffset < 0) {
80720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // All samples are sync-samples.
80820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *sample_index = start_sample_index;
80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
812abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (mNumSyncSamples == 0) {
813abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        *sample_index = 0;
814abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        return OK;
815abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    }
816da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber
817abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    uint32_t left = 0;
818225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar    uint32_t right_plus_one = mNumSyncSamples;
819225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar    while (left < right_plus_one) {
820225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar        uint32_t center = left + (right_plus_one - left) / 2;
8218f76ebf90d0391a4baa8a921ed6e291dfc7891daAndreas Huber        uint32_t x = mSyncSamples[center];
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8238f76ebf90d0391a4baa8a921ed6e291dfc7891daAndreas Huber        if (start_sample_index < x) {
824225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar            right_plus_one = center;
8258f76ebf90d0391a4baa8a921ed6e291dfc7891daAndreas Huber        } else if (start_sample_index > x) {
8268f76ebf90d0391a4baa8a921ed6e291dfc7891daAndreas Huber            left = center + 1;
8278f76ebf90d0391a4baa8a921ed6e291dfc7891daAndreas Huber        } else {
828599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            *sample_index = x;
829599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            return OK;
83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
831f53263a7d580fb550dbc6c8d4f104119beb82ad7James Dong    }
832599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar
8338d0dd8b46163ec7b42e2051c441ae2bf96dd9aecHong Teng    if (left == mNumSyncSamples) {
8348d0dd8b46163ec7b42e2051c441ae2bf96dd9aecHong Teng        if (flags == kFlagAfter) {
83529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("tried to find a sync frame after the last one: %d", left);
8368d0dd8b46163ec7b42e2051c441ae2bf96dd9aecHong Teng            return ERROR_OUT_OF_RANGE;
8378d0dd8b46163ec7b42e2051c441ae2bf96dd9aecHong Teng        }
838599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar        flags = kFlagBefore;
8398d0dd8b46163ec7b42e2051c441ae2bf96dd9aecHong Teng    }
840599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar    else if (left == 0) {
841599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar        if (flags == kFlagBefore) {
842599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            ALOGE("tried to find a sync frame before the first one: %d", left);
843abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
844599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            // normally we should return out of range, but that is
845599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            // treated as end-of-stream.  instead seek to first sync
846599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            //
847599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            // return ERROR_OUT_OF_RANGE;
848abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
849599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar        flags = kFlagAfter;
850abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    }
851abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
852599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar    // Now ssi[left - 1] <(=) start_sample_index <= ssi[left]
853abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    switch (flags) {
854abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        case kFlagBefore:
855abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        {
856599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            --left;
857abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            break;
858abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
859abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        case kFlagAfter:
860abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        {
861599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            // nothing to do
862abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            break;
863abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
864abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        default:
865599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar        {
866599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            // this route is not used, but implement it nonetheless
867599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            CHECK(flags == kFlagClosest);
868599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar
869599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            status_t err = mSampleIterator->seekTo(start_sample_index);
870599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            if (err != OK) {
871599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                return err;
872599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            }
873599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            uint32_t sample_time = mSampleIterator->getSampleTime();
874599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar
875599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            err = mSampleIterator->seekTo(mSyncSamples[left]);
876599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            if (err != OK) {
877599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                return err;
878599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            }
879599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            uint32_t upper_time = mSampleIterator->getSampleTime();
880599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar
881599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            err = mSampleIterator->seekTo(mSyncSamples[left - 1]);
882599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            if (err != OK) {
883599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                return err;
884599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            }
885599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            uint32_t lower_time = mSampleIterator->getSampleTime();
886599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar
887599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            // use abs_difference for safety
888599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            if (abs_difference(upper_time, sample_time) >
889599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                abs_difference(sample_time, lower_time)) {
890599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                --left;
891599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar            }
892abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            break;
893599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar        }
89420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
89520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
896599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar    *sample_index = mSyncSamples[left];
89720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
89820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9007e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huberstatus_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
901c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    Mutex::Autolock autoLock(mLock);
902c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
9037e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if (mSyncSampleOffset < 0) {
9047e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        // All samples are sync-samples.
9057e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        *sample_index = 0;
9067e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        return OK;
9077e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
9087e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
9097e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    uint32_t bestSampleIndex = 0;
9107e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    size_t maxSampleSize = 0;
9117e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
9127e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    static const size_t kMaxNumSyncSamplesToScan = 20;
9137e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
9147e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    // Consider the first kMaxNumSyncSamplesToScan sync samples and
9157e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    // pick the one with the largest (compressed) size as the thumbnail.
9167e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
9177e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    size_t numSamplesToScan = mNumSyncSamples;
9187e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
9197e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        numSamplesToScan = kMaxNumSyncSamplesToScan;
9207e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
9217e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
9227e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    for (size_t i = 0; i < numSamplesToScan; ++i) {
9238bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        uint32_t x = mSyncSamples[i];
9247e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
9257e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        // Now x is a sample index.
9267e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t sampleSize;
927c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err = getSampleSize_l(x, &sampleSize);
9287e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (err != OK) {
9297e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            return err;
9307e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
9317e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
9327e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (i == 0 || sampleSize > maxSampleSize) {
9337e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            bestSampleIndex = x;
9347e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            maxSampleSize = sampleSize;
9357e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
9367e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
9377e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
9387e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    *sample_index = bestSampleIndex;
9397e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
9407e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    return OK;
9417e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber}
9427e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
943c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huberstatus_t SampleTable::getSampleSize_l(
944c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        uint32_t sampleIndex, size_t *sampleSize) {
945c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    return mSampleIterator->getSampleSizeDirect(
946c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            sampleIndex, sampleSize);
947c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber}
948c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
949c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huberstatus_t SampleTable::getMetaDataForSample(
950c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        uint32_t sampleIndex,
951c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t *offset,
952c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        size_t *size,
9534678a6dc5f09008481524949a9667af5a6190374Andreas Huber        uint32_t *compositionTime,
954170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        bool *isSyncSample,
955170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        uint32_t *sampleDuration) {
956c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    Mutex::Autolock autoLock(mLock);
957c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
958c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    status_t err;
959c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
960c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        return err;
961c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    }
962c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
963c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    if (offset) {
964c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        *offset = mSampleIterator->getSampleOffset();
965c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    }
966c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
967c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    if (size) {
968c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        *size = mSampleIterator->getSampleSize();
969c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    }
970c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
9714678a6dc5f09008481524949a9667af5a6190374Andreas Huber    if (compositionTime) {
9724678a6dc5f09008481524949a9667af5a6190374Andreas Huber        *compositionTime = mSampleIterator->getSampleTime();
973c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    }
974c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
9758bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    if (isSyncSample) {
9768bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        *isSyncSample = false;
9778bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (mSyncSampleOffset < 0) {
9788bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            // Every sample is a sync sample.
9798bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            *isSyncSample = true;
9808bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        } else {
9818bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
9828bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                    && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
9838bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                ? mLastSyncSampleIndex : 0;
9848bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
9858bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
9868bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                ++i;
9878bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
9888bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
9898bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
9908bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                *isSyncSample = true;
9918bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
9928bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
9938bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mLastSyncSampleIndex = i;
9948bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
9958bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    }
9968bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
997170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih    if (sampleDuration) {
998170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        *sampleDuration = mSampleIterator->getSampleDuration();
999170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih    }
1000170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih
1001c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    return OK;
1002c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber}
1003c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
1004b1dc9e07c084d0df17de71b54f8340c0b8917824Marco Nelissenint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
100589aa8fe4cb00d2f24260005b008602232d678684Andreas Huber    return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
10064931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber}
10074931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
100820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
1009