SampleTable.cpp revision 4931bb5259d10c1fa01e7405fb7aaef58a8ffb22
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
2189e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber#include "include/SampleTable.h"
22c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include "include/SampleIterator.h"
2389e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber
2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/DataSource.h>
270c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
3120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber// static
33c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huberconst uint32_t SampleTable::kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o');
34c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber// static
35c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huberconst uint32_t SampleTable::kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
36c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber// static
37c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huberconst uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
38c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber// static
39c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huberconst uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
40c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
41c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber////////////////////////////////////////////////////////////////////////////////
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberSampleTable::SampleTable(const sp<DataSource> &source)
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mDataSource(source),
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mChunkOffsetOffset(-1),
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mChunkOffsetType(0),
4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mNumChunkOffsets(0),
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleToChunkOffset(-1),
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mNumSampleToChunkOffsets(0),
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleSizeOffset(-1),
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleSizeFieldSize(0),
5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDefaultSampleSize(0),
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mNumSampleSizes(0),
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mTimeToSampleCount(0),
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mTimeToSample(NULL),
564931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber      mCompositionTimeDeltaEntries(NULL),
574931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber      mNumCompositionTimeDeltaEntries(0),
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSyncSampleOffset(-1),
59c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber      mNumSyncSamples(0),
608bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber      mSyncSamples(NULL),
618bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber      mLastSyncSampleIndex(0),
62c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber      mSampleToChunkEntries(NULL) {
63c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    mSampleIterator = new SampleIterator(this);
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberSampleTable::~SampleTable() {
67c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    delete[] mSampleToChunkEntries;
68c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    mSampleToChunkEntries = NULL;
69c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
708bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    delete[] mSyncSamples;
718bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    mSyncSamples = NULL;
728bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
734931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    delete[] mCompositionTimeDeltaEntries;
744931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    mCompositionTimeDeltaEntries = NULL;
754931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete[] mTimeToSample;
7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTimeToSample = NULL;
78c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
79c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    delete mSampleIterator;
80c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    mSampleIterator = NULL;
8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
8220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t SampleTable::setChunkOffsetParams(
84c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        uint32_t type, off64_t data_offset, size_t data_size) {
8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mChunkOffsetOffset >= 0) {
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
890c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(type == kChunkOffsetType32 || type == kChunkOffsetType64);
9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mChunkOffsetOffset = data_offset;
9220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mChunkOffsetType = type;
9320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (data_size < 8) {
9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
9934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(
10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (U32_AT(header) != 0) {
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // Expected version = 0, flags = 0.
10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mNumChunkOffsets = U32_AT(&header[4]);
11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mChunkOffsetType == kChunkOffsetType32) {
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (data_size < 8 + mNumChunkOffsets * 4) {
11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_MALFORMED;
11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (data_size < 8 + mNumChunkOffsets * 8) {
11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_MALFORMED;
11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t SampleTable::setSampleToChunkParams(
125c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, size_t data_size) {
12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mSampleToChunkOffset >= 0) {
12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
12920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mSampleToChunkOffset = data_offset;
13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (data_size < 8) {
13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
13420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
13734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(
13820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
13920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
14120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (U32_AT(header) != 0) {
14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // Expected version = 0, flags = 0.
14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mNumSampleToChunkOffsets = U32_AT(&header[4]);
14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (data_size < 8 + mNumSampleToChunkOffsets * 12) {
15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    mSampleToChunkEntries =
154c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        new SampleToChunkEntry[mNumSampleToChunkOffsets];
155c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
156c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
157c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        uint8_t buffer[12];
158c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        if (mDataSource->readAt(
159c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                    mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer))
160c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                != (ssize_t)sizeof(buffer)) {
161c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            return ERROR_IO;
162c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        }
163c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
164c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        CHECK(U32_AT(buffer) >= 1);  // chunk index is 1 based in the spec.
165c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
166c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        // We want the chunk index to be 0-based.
167c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
168c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]);
169c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]);
170c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    }
171c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
17220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t SampleTable::setSampleSizeParams(
176c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        uint32_t type, off64_t data_offset, size_t data_size) {
17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mSampleSizeOffset >= 0) {
17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
17920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
18020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1810c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact);
18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mSampleSizeOffset = data_offset;
18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (data_size < 12) {
18620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[12];
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    mDefaultSampleSize = U32_AT(&header[4]);
20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mNumSampleSizes = U32_AT(&header[8]);
20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (type == kSampleSizeType32) {
20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mSampleSizeFieldSize = 32;
20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mDefaultSampleSize != 0) {
20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return OK;
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (data_size < 12 + mNumSampleSizes * 4) {
21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_MALFORMED;
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if ((mDefaultSampleSize & 0xffffff00) != 0) {
21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            // The high 24 bits are reserved and must be 0.
21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_MALFORMED;
21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mSampleSizeFieldSize = mDefaultSampleSize & 0xf;
22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mDefaultSampleSize = 0;
22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8
22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            && mSampleSizeFieldSize != 16) {
22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_MALFORMED;
22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
22620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_MALFORMED;
22920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
23120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t SampleTable::setTimeToSampleParams(
236c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, size_t data_size) {
23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mTimeToSample != NULL || data_size < 8) {
23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
24234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(
24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (U32_AT(header) != 0) {
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // Expected version = 0, flags = 0.
24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTimeToSampleCount = U32_AT(&header[4]);
25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mTimeToSample = new uint32_t[mTimeToSampleCount * 2];
25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2;
25634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(
25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                data_offset + 8, mTimeToSample, size) < (ssize_t)size) {
25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) {
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mTimeToSample[i] = ntohl(mTimeToSample[i]);
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2684931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huberstatus_t SampleTable::setCompositionTimeToSampleParams(
2694931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        off64_t data_offset, size_t data_size) {
2704931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    LOGI("There are reordered frames present.");
2714931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
2724931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
2734931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        return ERROR_MALFORMED;
2744931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
2754931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
2764931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    uint8_t header[8];
2774931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    if (mDataSource->readAt(
2784931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                data_offset, header, sizeof(header))
2794931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            < (ssize_t)sizeof(header)) {
2804931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        return ERROR_IO;
2814931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
2824931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
2834931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    if (U32_AT(header) != 0) {
2844931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        // Expected version = 0, flags = 0.
2854931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        return ERROR_MALFORMED;
2864931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
2874931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
2884931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    size_t numEntries = U32_AT(&header[4]);
2894931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
2904931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    if (data_size != (numEntries + 1) * 8) {
2914931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        return ERROR_MALFORMED;
2924931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
2934931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
2944931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    mNumCompositionTimeDeltaEntries = numEntries;
2954931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries];
2964931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
2974931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    if (mDataSource->readAt(
2984931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8)
2994931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            < (ssize_t)numEntries * 8) {
3004931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        delete[] mCompositionTimeDeltaEntries;
3014931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        mCompositionTimeDeltaEntries = NULL;
3024931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
3034931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        return ERROR_IO;
3044931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
3054931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
3064931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    for (size_t i = 0; i < 2 * numEntries; ++i) {
3074931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
3084931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
3094931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
3104931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    return OK;
3114931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber}
3124931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
313c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mSyncSampleOffset >= 0 || data_size < 8) {
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mSyncSampleOffset = data_offset;
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
32134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (U32_AT(header) != 0) {
32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // Expected version = 0, flags = 0.
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_MALFORMED;
32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mNumSyncSamples = U32_AT(&header[4]);
33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mNumSyncSamples < 2) {
33475fc7654280ac2a72fa8124b88e616219a3e61e2Andreas Huber        LOGV("Table of sync samples is empty or has only a single entry!");
33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
3368bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
3378bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    mSyncSamples = new uint32_t[mNumSyncSamples];
3388bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    size_t size = mNumSyncSamples * sizeof(uint32_t);
3398bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size)
3408bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            != (ssize_t)size) {
3418bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        return ERROR_IO;
3428bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    }
3438bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
3448bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    for (size_t i = 0; i < mNumSyncSamples; ++i) {
3458bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
3468bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    }
3478bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
34820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberuint32_t SampleTable::countChunkOffsets() const {
35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mNumChunkOffsets;
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberuint32_t SampleTable::countSamples() const {
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mNumSampleSizes;
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t SampleTable::getMaxSampleSize(size_t *max_size) {
36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Mutex::Autolock autoLock(mLock);
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *max_size = 0;
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
36520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t sample_size;
366c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err = getSampleSize_l(i, &sample_size);
367da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber
36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (sample_size > *max_size) {
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *max_size = sample_size;
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
380da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huberuint32_t abs_difference(uint32_t time1, uint32_t time2) {
381da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber    return time1 > time2 ? time1 - time2 : time2 - time1;
382da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber}
383da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber
384abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huberstatus_t SampleTable::findSampleAtTime(
38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
3864931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    // XXX this currently uses decoding time, instead of composition time.
3874931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
388abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    *sample_index = 0;
389abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Mutex::Autolock autoLock(mLock);
39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t cur_sample = 0;
39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t time = 0;
39420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t n = mTimeToSample[2 * i];
39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t delta = mTimeToSample[2 * i + 1];
39720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (req_time < time + n * delta) {
39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int j = (req_time - time) / delta;
40020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
401da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber            uint32_t time1 = time + j * delta;
402da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber            uint32_t time2 = time1 + delta;
403da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber
404abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            uint32_t sampleTime;
405da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber            if (i+1 == mTimeToSampleCount
406da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber                    || (abs_difference(req_time, time1)
407da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber                        < abs_difference(req_time, time2))) {
408da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber                *sample_index = cur_sample + j;
409abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                sampleTime = time1;
410da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber            } else {
411da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber                *sample_index = cur_sample + j + 1;
412abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                sampleTime = time2;
413da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber            }
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
415abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            switch (flags) {
416abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                case kFlagBefore:
417abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                {
418abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    if (sampleTime > req_time && *sample_index > 0) {
419abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        --*sample_index;
420abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    }
421abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    break;
422abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                }
423abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
424abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                case kFlagAfter:
425abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                {
426abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    if (sampleTime < req_time
427abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                            && *sample_index + 1 < mNumSampleSizes) {
428abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        ++*sample_index;
429abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    }
430abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    break;
431abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                }
432abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
433abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                default:
434abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    break;
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return OK;
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        time += delta * n;
44120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        cur_sample += n;
44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return ERROR_OUT_OF_RANGE;
44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
447abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huberstatus_t SampleTable::findSyncSampleNear(
448abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
449abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    Mutex::Autolock autoLock(mLock);
450abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
45120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *sample_index = 0;
45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mSyncSampleOffset < 0) {
45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // All samples are sync-samples.
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *sample_index = start_sample_index;
45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
459abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (mNumSyncSamples == 0) {
460abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        *sample_index = 0;
461abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        return OK;
462abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    }
463da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber
464abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    uint32_t left = 0;
465abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    while (left < mNumSyncSamples) {
4668bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        uint32_t x = mSyncSamples[left];
46720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
468abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (x >= start_sample_index) {
46920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
471abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
472abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        ++left;
473abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    }
474f53263a7d580fb550dbc6c8d4f104119beb82ad7James Dong    if (left > 0) {
475f53263a7d580fb550dbc6c8d4f104119beb82ad7James Dong        --left;
476f53263a7d580fb550dbc6c8d4f104119beb82ad7James Dong    }
477abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
478abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    uint32_t x;
479abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (mDataSource->readAt(
480abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mSyncSampleOffset + 8 + left * 4, &x, 4) != 4) {
481abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        return ERROR_IO;
482abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    }
483abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
484abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    x = ntohl(x);
485abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    --x;
486abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
487abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (left + 1 < mNumSyncSamples) {
4888bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        uint32_t y = mSyncSamples[left + 1];
489abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
490abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        // our sample lies between sync samples x and y.
491abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
492abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleIterator->seekTo(start_sample_index);
493abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err != OK) {
494abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            return err;
495abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
496abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
497abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t sample_time = mSampleIterator->getSampleTime();
498abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
499abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        err = mSampleIterator->seekTo(x);
500abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err != OK) {
501abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            return err;
502abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
503abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t x_time = mSampleIterator->getSampleTime();
504abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
505abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        err = mSampleIterator->seekTo(y);
506abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err != OK) {
507abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            return err;
508abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
509abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
510abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t y_time = mSampleIterator->getSampleTime();
511abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
512abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (abs_difference(x_time, sample_time)
513abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                > abs_difference(y_time, sample_time)) {
514abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // Pick the sync sample closest (timewise) to the start-sample.
515abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            x = y;
516abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            ++left;
517abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
518abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    }
519abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
520abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    switch (flags) {
521abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        case kFlagBefore:
522abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        {
523abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (x > start_sample_index) {
524abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(left > 0);
525abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
526abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                if (mDataSource->readAt(
527abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                            mSyncSampleOffset + 8 + (left - 1) * 4, &x, 4) != 4) {
528abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    return ERROR_IO;
529abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                }
530abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
531abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                x = ntohl(x);
532abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                --x;
533abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
534abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(x <= start_sample_index);
535abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
536abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            break;
537abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
538abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
539abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        case kFlagAfter:
540abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        {
541abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (x < start_sample_index) {
542abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                if (left + 1 >= mNumSyncSamples) {
543abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    return ERROR_OUT_OF_RANGE;
544abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                }
545abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
5468bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                x = mSyncSamples[left + 1];
547abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
548abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(x >= start_sample_index);
549abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
550abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
551abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            break;
552abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
553abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
554abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        default:
555abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            break;
55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
558abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    *sample_index = x;
55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5637e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huberstatus_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
564c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    Mutex::Autolock autoLock(mLock);
565c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
5667e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if (mSyncSampleOffset < 0) {
5677e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        // All samples are sync-samples.
5687e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        *sample_index = 0;
5697e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        return OK;
5707e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
5717e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
5727e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    uint32_t bestSampleIndex = 0;
5737e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    size_t maxSampleSize = 0;
5747e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
5757e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    static const size_t kMaxNumSyncSamplesToScan = 20;
5767e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
5777e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    // Consider the first kMaxNumSyncSamplesToScan sync samples and
5787e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    // pick the one with the largest (compressed) size as the thumbnail.
5797e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
5807e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    size_t numSamplesToScan = mNumSyncSamples;
5817e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
5827e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        numSamplesToScan = kMaxNumSyncSamplesToScan;
5837e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
5847e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
5857e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    for (size_t i = 0; i < numSamplesToScan; ++i) {
5868bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        uint32_t x = mSyncSamples[i];
5877e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
5887e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        // Now x is a sample index.
5897e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t sampleSize;
590c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err = getSampleSize_l(x, &sampleSize);
5917e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (err != OK) {
5927e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            return err;
5937e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
5947e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
5957e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (i == 0 || sampleSize > maxSampleSize) {
5967e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            bestSampleIndex = x;
5977e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            maxSampleSize = sampleSize;
5987e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
5997e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
6007e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
6017e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    *sample_index = bestSampleIndex;
6027e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
6037e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    return OK;
6047e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber}
6057e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
606c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huberstatus_t SampleTable::getSampleSize_l(
607c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        uint32_t sampleIndex, size_t *sampleSize) {
608c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    return mSampleIterator->getSampleSizeDirect(
609c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            sampleIndex, sampleSize);
610c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber}
611c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
612c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huberstatus_t SampleTable::getMetaDataForSample(
613c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        uint32_t sampleIndex,
614c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t *offset,
615c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        size_t *size,
6168bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        uint32_t *decodingTime,
6178bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        bool *isSyncSample) {
618c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    Mutex::Autolock autoLock(mLock);
619c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
620c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    status_t err;
621c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
622c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        return err;
623c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    }
624c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
625c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    if (offset) {
626c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        *offset = mSampleIterator->getSampleOffset();
627c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    }
628c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
629c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    if (size) {
630c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        *size = mSampleIterator->getSampleSize();
631c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    }
632c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
633c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    if (decodingTime) {
634c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        *decodingTime = mSampleIterator->getSampleTime();
635c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    }
636c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
6378bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    if (isSyncSample) {
6388bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        *isSyncSample = false;
6398bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (mSyncSampleOffset < 0) {
6408bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            // Every sample is a sync sample.
6418bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            *isSyncSample = true;
6428bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        } else {
6438bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
6448bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                    && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
6458bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                ? mLastSyncSampleIndex : 0;
6468bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
6478bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
6488bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                ++i;
6498bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
6508bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
6518bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
6528bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                *isSyncSample = true;
6538bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
6548bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
6558bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mLastSyncSampleIndex = i;
6568bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
6578bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    }
6588bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
659c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    return OK;
660c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber}
661c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
6624931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huberuint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) const {
6634931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    if (mCompositionTimeDeltaEntries == NULL) {
6644931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        return 0;
6654931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
6664931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
6674931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    uint32_t curSample = 0;
6684931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    for (size_t i = 0; i < mNumCompositionTimeDeltaEntries; ++i) {
6694931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        uint32_t sampleCount = mCompositionTimeDeltaEntries[2 * i];
6704931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
6714931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        if (sampleIndex < curSample + sampleCount) {
6724931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            uint32_t sampleDelta = mCompositionTimeDeltaEntries[2 * i + 1];
6734931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
6744931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            return sampleDelta;
6754931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        }
6764931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
6774931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        curSample += sampleCount;
6784931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
6794931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
6804931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    return 0;
6814931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber}
6824931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
68320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
68420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
685