TrackFragment.cpp revision b7e75cfd64893dde230dfc1c3b281a00ca1b4470
1840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber/*
2840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * Copyright (C) 2012 The Android Open Source Project
3840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber *
4840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * you may not use this file except in compliance with the License.
6840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * You may obtain a copy of the License at
7840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber *
8840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber *
10840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * Unless required by applicable law or agreed to in writing, software
11840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * See the License for the specific language governing permissions and
14840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber * limitations under the License.
15840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber */
16840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
17840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber//#define LOG_NDEBUG 0
18840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#define LOG_TAG "TrackFragment"
19840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include <utils/Log.h>
20840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
21840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include "TrackFragment.h"
22840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
23840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include <media/stagefright/MediaErrors.h>
24840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include <media/stagefright/Utils.h>
25840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
26840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber#include <media/stagefright/foundation/ADebug.h>
27840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
28840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Hubernamespace android {
29840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
30840667883fd09d44015716d79bc3ac4d60edc0f0Andreas HuberParser::DynamicTrackFragment::DynamicTrackFragment()
31840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    : mComplete(false),
32840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber      mSampleIndex(0) {
33840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
34840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
35840667883fd09d44015716d79bc3ac4d60edc0f0Andreas HuberParser::DynamicTrackFragment::~DynamicTrackFragment() {
36840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
37840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
38840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberstatus_t Parser::DynamicTrackFragment::getSample(SampleInfo *info) {
39840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (mSampleIndex >= mSamples.size()) {
40840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return mComplete ? ERROR_END_OF_STREAM : -EWOULDBLOCK;
41840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
42840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
43840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    *info = mSamples.itemAt(mSampleIndex);
44840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
45840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
46840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
47840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
48840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Hubervoid Parser::DynamicTrackFragment::advance() {
49840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    ++mSampleIndex;
50840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
51840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
52840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Hubervoid Parser::DynamicTrackFragment::addSample(
53840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        off64_t dataOffset, size_t sampleSize,
54840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t presentationTime,
55840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        size_t sampleDescIndex,
56840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t flags) {
57840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mSamples.push();
58840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    SampleInfo *sampleInfo = &mSamples.editItemAt(mSamples.size() - 1);
59840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
60840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sampleInfo->mOffset = dataOffset;
61840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sampleInfo->mSize = sampleSize;
62840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sampleInfo->mPresentationTime = presentationTime;
63840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sampleInfo->mSampleDescIndex = sampleDescIndex;
64840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    sampleInfo->mFlags = flags;
65840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
66840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
67840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberstatus_t Parser::DynamicTrackFragment::signalCompletion() {
68840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mComplete = true;
69840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
70840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
71840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
72840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
73840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberbool Parser::DynamicTrackFragment::complete() const {
74840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return mComplete;
75840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
76840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
77840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber////////////////////////////////////////////////////////////////////////////////
78840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
79840667883fd09d44015716d79bc3ac4d60edc0f0Andreas HuberParser::StaticTrackFragment::StaticTrackFragment()
80840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    : mSampleIndex(0),
81840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber      mSampleCount(0),
82840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber      mSampleToChunkIndex(-1),
83840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber      mSampleToChunkRemaining(0),
84840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber      mPrevChunkIndex(0xffffffff),
85840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber      mNextSampleOffset(0) {
86840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
87840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
88840667883fd09d44015716d79bc3ac4d60edc0f0Andreas HuberParser::StaticTrackFragment::~StaticTrackFragment() {
89840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
90840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
91840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberstatus_t Parser::StaticTrackFragment::getSample(SampleInfo *info) {
92840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (mSampleIndex >= mSampleCount) {
93840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_END_OF_STREAM;
94840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
95840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
96840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    *info = mSampleInfo;
97840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
98840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    ALOGV("returning sample %d at [0x%08llx, 0x%08llx)",
99840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber          mSampleIndex,
100840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber          info->mOffset, info->mOffset + info->mSize);
101840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
102840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
103840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
104840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
105840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Hubervoid Parser::StaticTrackFragment::updateSampleInfo() {
106840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (mSampleIndex >= mSampleCount) {
107840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return;
108840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
109840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
110840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (mSampleSizes != NULL) {
111840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t defaultSampleSize = U32_AT(mSampleSizes->data() + 4);
112840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (defaultSampleSize > 0) {
113840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            mSampleInfo.mSize = defaultSampleSize;
114840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        } else {
115840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            mSampleInfo.mSize= U32_AT(mSampleSizes->data() + 12 + 4 * mSampleIndex);
116840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
117840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    } else {
118840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        CHECK(mCompactSampleSizes != NULL);
119840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
120840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t fieldSize = U32_AT(mCompactSampleSizes->data() + 4);
121840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
122840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        switch (fieldSize) {
123840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            case 4:
124840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            {
125840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                unsigned byte = mCompactSampleSizes->data()[12 + mSampleIndex / 2];
126840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                mSampleInfo.mSize = (mSampleIndex & 1) ? byte & 0x0f : byte >> 4;
127840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                break;
128840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
129840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
130840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            case 8:
131840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            {
132840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                mSampleInfo.mSize = mCompactSampleSizes->data()[12 + mSampleIndex];
133840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                break;
134840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
135840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
136840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            default:
137840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            {
138840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                CHECK_EQ(fieldSize, 16);
139840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                mSampleInfo.mSize =
140840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                    U16_AT(mCompactSampleSizes->data() + 12 + mSampleIndex * 2);
141840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                break;
142840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
143840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
144840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
145840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
146840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    CHECK_GT(mSampleToChunkRemaining, 0);
147840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
148840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    // The sample desc index is 1-based... XXX
149840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mSampleInfo.mSampleDescIndex =
150840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex + 8);
151840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
152840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t chunkIndex =
153840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex);
154840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
155840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    CHECK_GE(chunkIndex, 1);
156840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    --chunkIndex;
157840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
158840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (chunkIndex != mPrevChunkIndex) {
159840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        mPrevChunkIndex = chunkIndex;
160840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
161840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if (mChunkOffsets != NULL) {
162840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            uint32_t entryCount = U32_AT(mChunkOffsets->data() + 4);
163840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
164840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (chunkIndex >= entryCount) {
165840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                mSampleIndex = mSampleCount;
166840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                return;
167840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
168840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
169840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            mNextSampleOffset =
170840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                U32_AT(mChunkOffsets->data() + 8 + 4 * chunkIndex);
171840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        } else {
172840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            CHECK(mChunkOffsets64 != NULL);
173840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
174840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            uint32_t entryCount = U32_AT(mChunkOffsets64->data() + 4);
175840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
176840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            if (chunkIndex >= entryCount) {
177840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                mSampleIndex = mSampleCount;
178840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                return;
179840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            }
180840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
181840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            mNextSampleOffset =
182840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber                U64_AT(mChunkOffsets64->data() + 8 + 8 * chunkIndex);
183840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
184840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
185840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
186840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mSampleInfo.mOffset = mNextSampleOffset;
187840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
188840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mSampleInfo.mPresentationTime = 0;
189840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mSampleInfo.mFlags = 0;
190840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
191840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
192840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Hubervoid Parser::StaticTrackFragment::advance() {
193840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mNextSampleOffset += mSampleInfo.mSize;
194840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
195840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    ++mSampleIndex;
196840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (--mSampleToChunkRemaining == 0) {
197840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t entryCount = U32_AT(mSampleToChunk->data() + 4);
198840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
199840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        if ((uint32_t)(mSampleToChunkIndex + 1) == entryCount) {
200840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            mSampleIndex = mSampleCount;  // EOS.
201840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            return;
202840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        }
203840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
204840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        ++mSampleToChunkIndex;
205840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        mSampleToChunkRemaining =
206840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex + 4);
207840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
208840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
209840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    updateSampleInfo();
210840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
211840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
212840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberstatic void setU32At(uint8_t *ptr, uint32_t x) {
213840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    ptr[0] = x >> 24;
214840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    ptr[1] = (x >> 16) & 0xff;
215840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    ptr[2] = (x >> 8) & 0xff;
216840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    ptr[3] = x & 0xff;
217840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
218840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
219840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Hubervoid Parser::StaticTrackFragment::fixSampleToChunkTableIfNecessary() {
220b7e75cfd64893dde230dfc1c3b281a00ca1b4470Marco Nelissen    if (mSampleToChunk == NULL) {
221b7e75cfd64893dde230dfc1c3b281a00ca1b4470Marco Nelissen        return;
222b7e75cfd64893dde230dfc1c3b281a00ca1b4470Marco Nelissen    }
223840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t entryCount = U32_AT(mSampleToChunk->data() + 4);
224840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t totalSamples = 0;
225840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    for (uint32_t i = 0; i < entryCount; ++i) {
226840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        totalSamples += U32_AT(mSampleToChunk->data() + 8 + 12 * i + 4);
227840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
228840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
229840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (totalSamples < mSampleCount) {
230840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        // Some samples are not accounted for in the sample-to-chunk
231840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        // data. Fabricate an extra chunk adjacent to the last one
232840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        // in the table with the same sample desription index.
233840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
234840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        ALOGW("Faking an extra sample-to-chunk entry for %d samples.",
235840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber              mSampleCount - totalSamples);
236840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
237840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t lastChunkIndex =
238840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            U32_AT(mSampleToChunk->data() + 8 + 12 * (entryCount - 1));
239840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
240840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint32_t lastSampleDescriptionIndex =
241840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber            U32_AT(mSampleToChunk->data() + 8 + 12 * (entryCount - 1) + 8);
242840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
243840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        uint8_t *ptr = mSampleToChunk->data() + 8 + 12 * entryCount;
244840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
245840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        setU32At(ptr, lastChunkIndex + 1);
246840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        setU32At(ptr + 4, mSampleCount - totalSamples);
247840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        setU32At(ptr + 8, lastSampleDescriptionIndex);
248840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        setU32At(mSampleToChunk->data() + 4, entryCount + 1);
249840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
250840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
251840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
252840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberstatus_t Parser::StaticTrackFragment::signalCompletion() {
253840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    fixSampleToChunkTableIfNecessary();
254840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
255840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mSampleToChunkIndex = 0;
256840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
257b7e75cfd64893dde230dfc1c3b281a00ca1b4470Marco Nelissen    mSampleToChunkRemaining = (mSampleToChunk == NULL) ? 0 :
258840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex + 4);
259840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
260840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    updateSampleInfo();
261840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
262840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
263840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
264840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
265840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberbool Parser::StaticTrackFragment::complete() const {
266840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return true;
267840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
268840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
269840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberstatus_t Parser::StaticTrackFragment::parseSampleSizes(
270840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        Parser *parser, uint32_t type, size_t offset, uint64_t size) {
271840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 12 > size) {
272840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
273840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
274840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
275840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (parser->readU32(offset) != 0) {
276840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
277840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
278840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
279840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t sampleSize = parser->readU32(offset + 4);
280840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t sampleCount = parser->readU32(offset + 8);
281840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
282840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (sampleSize == 0 && offset + 12 + sampleCount * 4 != size) {
283840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
284840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
285840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
286840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    parser->copyBuffer(&mSampleSizes, offset, size);
287840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
288840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mSampleCount = sampleCount;
289840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
290840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
291840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
292840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
293840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberstatus_t Parser::StaticTrackFragment::parseCompactSampleSizes(
294840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        Parser *parser, uint32_t type, size_t offset, uint64_t size) {
295840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 12 > size) {
296840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
297840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
298840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
299840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (parser->readU32(offset) != 0) {
300840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
301840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
302840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
303840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t fieldSize = parser->readU32(offset + 4);
304840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
305840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (fieldSize != 4 && fieldSize != 8 && fieldSize != 16) {
306840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
307840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
308840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
309840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t sampleCount = parser->readU32(offset + 8);
310840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
311840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 12 + (sampleCount * fieldSize + 4) / 8 != size) {
312840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
313840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
314840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
315840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    parser->copyBuffer(&mCompactSampleSizes, offset, size);
316840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
317840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    mSampleCount = sampleCount;
318840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
319840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
320840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
321840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
322840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberstatus_t Parser::StaticTrackFragment::parseSampleToChunk(
323840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        Parser *parser, uint32_t type, size_t offset, uint64_t size) {
324840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 8 > size) {
325840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
326840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
327840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
328840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (parser->readU32(offset) != 0) {
329840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
330840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
331840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
332840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t entryCount = parser->readU32(offset + 4);
333840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
334b7e75cfd64893dde230dfc1c3b281a00ca1b4470Marco Nelissen    if (entryCount == 0) {
335b7e75cfd64893dde230dfc1c3b281a00ca1b4470Marco Nelissen        return OK;
336b7e75cfd64893dde230dfc1c3b281a00ca1b4470Marco Nelissen    }
337b7e75cfd64893dde230dfc1c3b281a00ca1b4470Marco Nelissen
338b7e75cfd64893dde230dfc1c3b281a00ca1b4470Marco Nelissen    if (offset + 8 + entryCount * 12 != size) {
339840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
340840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
341840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
342840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    parser->copyBuffer(&mSampleToChunk, offset, size, 12 /* extra */);
343840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
344840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
345840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
346840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
347840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberstatus_t Parser::StaticTrackFragment::parseChunkOffsets(
348840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        Parser *parser, uint32_t type, size_t offset, uint64_t size) {
349840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 8 > size) {
350840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
351840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
352840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
353840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (parser->readU32(offset) != 0) {
354840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
355840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
356840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
357840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t entryCount = parser->readU32(offset + 4);
358840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
359840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 8 + entryCount * 4 != size) {
360840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
361840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
362840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
363840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    parser->copyBuffer(&mChunkOffsets, offset, size);
364840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
365840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
366840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
367840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
368840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huberstatus_t Parser::StaticTrackFragment::parseChunkOffsets64(
369840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        Parser *parser, uint32_t type, size_t offset, uint64_t size) {
370840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 8 > size) {
371840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
372840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
373840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
374840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (parser->readU32(offset) != 0) {
375840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
376840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
377840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
378840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    uint32_t entryCount = parser->readU32(offset + 4);
379840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
380840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    if (offset + 8 + entryCount * 8 != size) {
381840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber        return ERROR_MALFORMED;
382840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    }
383840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
384840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    parser->copyBuffer(&mChunkOffsets64, offset, size);
385840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
386840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber    return OK;
387840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}
388840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
389840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber}  // namespace android
390840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Huber
391