AVIExtractor.cpp revision c639aad6d8894f57c02e620f52ccf49e51b64866
1f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber/*
2f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * Copyright (C) 2011 The Android Open Source Project
3f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *
4f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * you may not use this file except in compliance with the License.
6f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * You may obtain a copy of the License at
7f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *
8f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *
10f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * Unless required by applicable law or agreed to in writing, software
11f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * See the License for the specific language governing permissions and
14f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * limitations under the License.
15f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber */
16f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
17f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber//#define LOG_NDEBUG 0
18f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#define LOG_TAG "AVIExtractor"
19f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <utils/Log.h>
20f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
21c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber#include "include/avc_utils.h"
22f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include "include/AVIExtractor.h"
23f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
24f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <binder/ProcessState.h>
25f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/foundation/hexdump.h>
26f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
27f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/foundation/ADebug.h>
28f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/DataSource.h>
29f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaBuffer.h>
30f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
31f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaDefs.h>
32f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaErrors.h>
33f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MetaData.h>
34f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/Utils.h>
35f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
36f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubernamespace android {
37f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
38f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstruct AVIExtractor::AVISource : public MediaSource {
39f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    AVISource(const sp<AVIExtractor> &extractor, size_t trackIndex);
40f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
41f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual status_t start(MetaData *params);
42f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual status_t stop();
43f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
44f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual sp<MetaData> getFormat();
45f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
46f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual status_t read(
47f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            MediaBuffer **buffer, const ReadOptions *options);
48f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
49f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberprotected:
50f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual ~AVISource();
51f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
52f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberprivate:
53f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<AVIExtractor> mExtractor;
54f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t mTrackIndex;
55f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const AVIExtractor::Track &mTrack;
56f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    MediaBufferGroup *mBufferGroup;
57f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t mSampleIndex;
58f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
59f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(AVISource);
60f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber};
61f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
62f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber////////////////////////////////////////////////////////////////////////////////
63f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
64f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::AVISource::AVISource(
65f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const sp<AVIExtractor> &extractor, size_t trackIndex)
66f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    : mExtractor(extractor),
67f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber      mTrackIndex(trackIndex),
68f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber      mTrack(mExtractor->mTracks.itemAt(trackIndex)),
69f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber      mBufferGroup(NULL) {
70f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
71f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
72f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::AVISource::~AVISource() {
73f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mBufferGroup) {
74f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        stop();
75f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
76f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
77f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
78f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::AVISource::start(MetaData *params) {
79f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    CHECK(!mBufferGroup);
80f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
81f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mBufferGroup = new MediaBufferGroup;
82f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
83f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
84f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
85f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mSampleIndex = 0;
86f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
87f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
88f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
89f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
90f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::AVISource::stop() {
91f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    CHECK(mBufferGroup);
92f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
93f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    delete mBufferGroup;
94f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mBufferGroup = NULL;
95f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
96f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
97f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
98f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
99f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MetaData> AVIExtractor::AVISource::getFormat() {
100f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return mTrack.mMeta;
101f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
102f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
103f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::AVISource::read(
104f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
105f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    CHECK(mBufferGroup);
106f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
107f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *buffer = NULL;
108f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
109f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    int64_t seekTimeUs;
110f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ReadOptions::SeekMode seekMode;
111f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
112f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        status_t err =
113f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            mExtractor->getSampleIndexAtTime(
114f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    mTrackIndex, seekTimeUs, seekMode, &mSampleIndex);
115f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
116f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (err != OK) {
117f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_END_OF_STREAM;
118f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
119f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
120f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
121f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    off64_t offset;
122f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t size;
123f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    bool isKey;
1247de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    int64_t timeUs;
125f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    status_t err = mExtractor->getSampleInfo(
1267de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber            mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs);
127f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
128f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ++mSampleIndex;
129f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
130f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (err != OK) {
131f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_END_OF_STREAM;
132f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
133f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
134f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    MediaBuffer *out;
135f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK);
136f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
137f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size);
138f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
139f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < (ssize_t)size) {
140f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
141f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
142f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
143f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    out->set_range(0, size);
144f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
145f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    out->meta_data()->setInt64(kKeyTime, timeUs);
146f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
147f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (isKey) {
148f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        out->meta_data()->setInt32(kKeyIsSyncFrame, 1);
149f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
150f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
151f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *buffer = out;
152f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
153f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
154f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
155f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
156f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber////////////////////////////////////////////////////////////////////////////////
157f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
158f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::AVIExtractor(const sp<DataSource> &dataSource)
159f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    : mDataSource(dataSource) {
160f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mInitCheck = parseHeaders();
161f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
162f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mInitCheck != OK) {
163f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        mTracks.clear();
164f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
165f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
166f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
167f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::~AVIExtractor() {
168f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
169f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
170f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersize_t AVIExtractor::countTracks() {
171f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return mTracks.size();
172f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
173f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
174f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MediaSource> AVIExtractor::getTrack(size_t index) {
175f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return index < mTracks.size() ? new AVISource(this, index) : NULL;
176f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
177f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
178f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MetaData> AVIExtractor::getTrackMetaData(
179f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t index, uint32_t flags) {
180f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL;
181f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
182f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
183f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MetaData> AVIExtractor::getMetaData() {
184f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<MetaData> meta = new MetaData;
185f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
186f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mInitCheck == OK) {
187f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_AVI);
188f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
189f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
190f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return meta;
191f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
192f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
193f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseHeaders() {
194f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mTracks.clear();
195f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mMovieOffset = 0;
196f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mFoundIndex = false;
197f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mOffsetsAreAbsolute = false;
198f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
199f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t res = parseChunk(0ll, -1ll);
200f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
201f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (res < 0) {
202f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return (status_t)res;
203f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
204f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
205f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mMovieOffset == 0ll || !mFoundIndex) {
206f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
207f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
208f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
209f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
210f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
211f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
212f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberssize_t AVIExtractor::parseChunk(off64_t offset, off64_t size, int depth) {
213f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (size >= 0 && size < 8) {
214f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
215f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
216f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
217f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t tmp[12];
218f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, tmp, 8);
219f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
220f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < 8) {
221f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
222f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
223f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
224f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t fourcc = U32_AT(tmp);
225f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t chunkSize = U32LE_AT(&tmp[4]);
226f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
227f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (size >= 0 && chunkSize + 8 > size) {
228f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
229f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
230f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
231f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    static const char kPrefix[] = "                              ";
232f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const char *prefix = &kPrefix[strlen(kPrefix) - 2 * depth];
233f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
234f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (fourcc == FOURCC('L', 'I', 'S', 'T')
235f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            || fourcc == FOURCC('R', 'I', 'F', 'F')) {
236f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        // It's a list of chunks
237f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
238f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (size >= 0 && size < 12) {
239f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
240f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
241f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
242f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        n = mDataSource->readAt(offset + 8, &tmp[8], 4);
243f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
244f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (n < 4) {
245f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
246f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
247f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
248f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t subFourcc = U32_AT(&tmp[8]);
249f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
250f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        LOGV("%s offset 0x%08llx LIST of '%c%c%c%c', size %d",
251f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             prefix,
252f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             offset,
253f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)(subFourcc >> 24),
254f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)((subFourcc >> 16) & 0xff),
255f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)((subFourcc >> 8) & 0xff),
256f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)(subFourcc & 0xff),
257f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             chunkSize - 4);
258f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
259f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (subFourcc == FOURCC('m', 'o', 'v', 'i')) {
260f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            // We're not going to parse this, but will take note of the
261f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            // offset.
262f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
263f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            mMovieOffset = offset;
264f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        } else {
265f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            off64_t subOffset = offset + 12;
266f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            off64_t subOffsetLimit = subOffset + chunkSize - 4;
267f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            while (subOffset < subOffsetLimit) {
268f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                ssize_t res =
269f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    parseChunk(subOffset, subOffsetLimit - subOffset, depth + 1);
270f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
271f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                if (res < 0) {
272f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    return res;
273f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                }
274f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
275f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                subOffset += res;
276f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
277f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
278f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else {
279f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        LOGV("%s offset 0x%08llx CHUNK '%c%c%c%c'",
280f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             prefix,
281f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             offset,
282f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)(fourcc >> 24),
283f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)((fourcc >> 16) & 0xff),
284f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)((fourcc >> 8) & 0xff),
285f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)(fourcc & 0xff));
286f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
287f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        status_t err = OK;
288f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
289f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        switch (fourcc) {
290f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            case FOURCC('s', 't', 'r', 'h'):
291f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            {
292f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                err = parseStreamHeader(offset + 8, chunkSize);
293f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                break;
294f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
295f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
296f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            case FOURCC('s', 't', 'r', 'f'):
297f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            {
298f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                err = parseStreamFormat(offset + 8, chunkSize);
299f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                break;
300f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
301f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
302f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            case FOURCC('i', 'd', 'x', '1'):
303f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            {
304f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                err = parseIndex(offset + 8, chunkSize);
305f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                break;
306f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
307f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
308f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            default:
309f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                break;
310f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
311f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
312f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (err != OK) {
313f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return err;
314f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
315f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
316f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
317f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (chunkSize & 1) {
318f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ++chunkSize;
319f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
320f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
321f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return chunkSize + 8;
322f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
323f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
324f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatic const char *GetMIMETypeForHandler(uint32_t handler) {
325f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    switch (handler) {
326f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        // Wow... shamelessly copied from
327f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        // http://wiki.multimedia.cx/index.php?title=ISO_MPEG-4
328f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
329f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('3', 'I', 'V', '2'):
330f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('3', 'i', 'v', '2'):
331f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('B', 'L', 'Z', '0'):
332f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'I', 'G', 'I'):
333f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'I', 'V', '1'):
334f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('d', 'i', 'v', '1'):
335f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'I', 'V', 'X'):
336f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('d', 'i', 'v', 'x'):
337f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'X', '5', '0'):
338f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('d', 'x', '5', '0'):
339f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'X', 'G', 'M'):
340f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('E', 'M', '4', 'A'):
341f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('E', 'P', 'H', 'V'):
342f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('F', 'M', 'P', '4'):
343f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('f', 'm', 'p', '4'):
344f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('F', 'V', 'F', 'W'):
345f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('H', 'D', 'X', '4'):
346f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('h', 'd', 'x', '4'):
347f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', '4', 'C', 'C'):
348f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', '4', 'S', '2'):
349f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('m', '4', 's', '2'):
350f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', 'P', '4', 'S'):
351f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('m', 'p', '4', 's'):
352f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', 'P', '4', 'V'):
353f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
354f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', 'V', 'X', 'M'):
355f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('R', 'M', 'P', '4'):
356f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('S', 'E', 'D', 'G'):
357f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('S', 'M', 'P', '4'):
358f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('U', 'M', 'P', '4'):
359f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('W', 'V', '1', 'F'):
360f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('X', 'V', 'I', 'D'):
361f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('X', 'v', 'i', 'D'):
362f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('x', 'v', 'i', 'd'):
363f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('X', 'V', 'I', 'X'):
364f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
365f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
366c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        // from http://wiki.multimedia.cx/index.php?title=H264
367c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
368c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        case FOURCC('d', 'a', 'v', 'c'):
369c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        case FOURCC('x', '2', '6', '4'):
370c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        case FOURCC('v', 's', 's', 'h'):
371c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
372c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
373f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        default:
374f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return NULL;
375f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
376f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
377f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
378f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) {
379f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (size != 56) {
380f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
381f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
382f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
383f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mTracks.size() > 99) {
384f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return -ERANGE;
385f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
386f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
387f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
388f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
389f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
390f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < (ssize_t)size) {
391f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
392f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
393f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
394f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const uint8_t *data = buffer->data();
395f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
396f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t type = U32_AT(data);
397f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t handler = U32_AT(&data[4]);
398f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t flags = U32LE_AT(&data[8]);
399f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
400f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<MetaData> meta = new MetaData;
401f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
402f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t rate = U32LE_AT(&data[20]);
403f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t scale = U32LE_AT(&data[24]);
404f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
4057de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    uint32_t sampleSize = U32LE_AT(&data[44]);
4067de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber
407f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const char *mime = NULL;
408f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    Track::Kind kind = Track::OTHER;
409f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
410f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (type == FOURCC('v', 'i', 'd', 's')) {
411f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        mime = GetMIMETypeForHandler(handler);
412f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
413f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (mime && strncasecmp(mime, "video/", 6)) {
414f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
415f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
416f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
417c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        if (mime == NULL) {
418c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            LOGW("Unsupported video format '%c%c%c%c'",
419c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                 (char)(handler >> 24),
420c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                 (char)((handler >> 16) & 0xff),
421c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                 (char)((handler >> 8) & 0xff),
422c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                 (char)(handler & 0xff));
423c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        }
424c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
425f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        kind = Track::VIDEO;
426f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else if (type == FOURCC('a', 'u', 'd', 's')) {
427f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (mime && strncasecmp(mime, "audio/", 6)) {
428f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
429f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
430f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
431f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        kind = Track::AUDIO;
432f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
433f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
434f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!mime) {
435f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        mime = "application/octet-stream";
436f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
437f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
438f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    meta->setCString(kKeyMIMEType, mime);
439f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
440f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mTracks.push();
441f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
442f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
443f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mMeta = meta;
444f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mRate = rate;
445f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mScale = scale;
4467de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    track->mBytesPerSample = sampleSize;
447f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mKind = kind;
448f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mNumSyncSamples = 0;
449f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mThumbnailSampleSize = 0;
450f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mThumbnailSampleIndex = -1;
451f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mMaxSampleSize = 0;
452f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
453f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
454f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
455f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
456f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) {
457f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mTracks.isEmpty()) {
458f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
459f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
460f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
461f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
462f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
463f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (track->mKind == Track::OTHER) {
464f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        // We don't support this content, but that's not a parsing error.
465f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return OK;
466f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
467f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
468f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    bool isVideo = (track->mKind == Track::VIDEO);
469f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
470f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if ((isVideo && size < 40) || (!isVideo && size < 18)) {
471f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        // Expected a BITMAPINFO or WAVEFORMATEX structure, respectively.
472f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
473f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
474f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
475f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
476f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
477f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
478f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < (ssize_t)size) {
479f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
480f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
481f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
482f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const uint8_t *data = buffer->data();
483f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
484f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (isVideo) {
485f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t width = U32LE_AT(&data[4]);
486f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t height = U32LE_AT(&data[8]);
487f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
488f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeyWidth, width);
489f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeyHeight, height);
490f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else {
491f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t format = U16LE_AT(data);
492c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
493f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (format == 0x55) {
494f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
495c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        } else {
496c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            LOGW("Unsupported audio format = 0x%04x", format);
497f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
498f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
499f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t numChannels = U16LE_AT(&data[2]);
500f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t sampleRate = U32LE_AT(&data[4]);
501f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
502f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeyChannelCount, numChannels);
503f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeySampleRate, sampleRate);
504f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
505f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
506f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
507f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
508f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
509f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber// static
510f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberbool AVIExtractor::IsCorrectChunkType(
511f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) {
512f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t chunkBase = chunkType & 0xffff;
513f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
514f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    switch (kind) {
515f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case Track::VIDEO:
516f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
517f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (chunkBase != FOURCC(0, 0, 'd', 'c')
518f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    && chunkBase != FOURCC(0, 0, 'd', 'b')) {
519f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return false;
520f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
521f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
522f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
523f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
524f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case Track::AUDIO:
525f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
526f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (chunkBase != FOURCC(0, 0, 'w', 'b')) {
527f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return false;
528f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
529f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
530f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
531f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
532f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        default:
533f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
534f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
535f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
536f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (trackIndex < 0) {
537f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return true;
538f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
539f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
540f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t hi = chunkType >> 24;
541f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t lo = (chunkType >> 16) & 0xff;
542f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
543f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
544f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return false;
545f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
546f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
547f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (trackIndex != (10 * (hi - '0') + (lo - '0'))) {
548f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return false;
549f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
550f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
551f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return true;
552f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
553f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
554f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
555f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if ((size % 16) != 0) {
556f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
557f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
558f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
559f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
560f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
561f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
562f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < (ssize_t)size) {
563f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
564f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
565f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
566f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const uint8_t *data = buffer->data();
567f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
568f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (size > 0) {
569f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t chunkType = U32_AT(data);
570f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
571f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint8_t hi = chunkType >> 24;
572f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint8_t lo = (chunkType >> 16) & 0xff;
573f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
574f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
575f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
576f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
577f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
578f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t trackIndex = 10 * (hi - '0') + (lo - '0');
579f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
580f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (trackIndex >= mTracks.size()) {
581f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
582f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
583f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
584f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        Track *track = &mTracks.editItemAt(trackIndex);
585f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
586f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (!IsCorrectChunkType(-1, track->mKind, chunkType)) {
587f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
588f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
589f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
590f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (track->mKind == Track::OTHER) {
591f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            data += 16;
592f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            size -= 16;
593f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            continue;
594f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
595f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
596f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t flags = U32LE_AT(&data[4]);
597f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t offset = U32LE_AT(&data[8]);
598f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t chunkSize = U32LE_AT(&data[12]);
599f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
600f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (chunkSize > track->mMaxSampleSize) {
601f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            track->mMaxSampleSize = chunkSize;
602f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
603f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
604f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mSamples.push();
605f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
606f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        SampleInfo *info =
607f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            &track->mSamples.editItemAt(track->mSamples.size() - 1);
608f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
609f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        info->mOffset = offset;
610f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        info->mIsKey = (flags & 0x10) != 0;
611f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
612f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (info->mIsKey) {
613f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            static const size_t kMaxNumSyncSamplesToScan = 20;
614f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
615f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) {
616f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                if (chunkSize > track->mThumbnailSampleSize) {
617f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    track->mThumbnailSampleSize = chunkSize;
618f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
619f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    track->mThumbnailSampleIndex =
620f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                        track->mSamples.size() - 1;
621f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                }
622f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
623f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
624f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            ++track->mNumSyncSamples;
625f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
626f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
627f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        data += 16;
628f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size -= 16;
629f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
630f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
631f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!mTracks.isEmpty()) {
632f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        off64_t offset;
633f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t size;
634f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        bool isKey;
6357de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        int64_t timeUs;
6367de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        status_t err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
637f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
638f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (err != OK) {
639f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            mOffsetsAreAbsolute = !mOffsetsAreAbsolute;
6407de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber            err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
641f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
642f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (err != OK) {
643f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return err;
644f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
645f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
646f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
647f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        LOGV("Chunk offsets are %s",
648f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative");
649f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
650f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
651f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
652f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        Track *track = &mTracks.editItemAt(i);
653f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
6547de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        int64_t durationUs;
6557de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        CHECK_EQ((status_t)OK,
6567de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber                 getSampleTime(i, track->mSamples.size() - 1, &durationUs));
657f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
658f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        LOGV("track %d duration = %.2f secs", i, durationUs / 1E6);
659f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
660f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt64(kKeyDuration, durationUs);
661f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize);
662f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
663f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const char *tmp;
664f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp));
665f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
666f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        AString mime = tmp;
667f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
668c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        if (!strncasecmp("video/", mime.c_str(), 6)) {
669c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            if (track->mThumbnailSampleIndex >= 0) {
670c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                int64_t thumbnailTimeUs;
671c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                CHECK_EQ((status_t)OK,
672c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                         getSampleTime(i, track->mThumbnailSampleIndex,
673c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                                       &thumbnailTimeUs));
674f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
675c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
676c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            }
677c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
678c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            status_t err = OK;
679f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
680f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
681c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                err = addMPEG4CodecSpecificData(i);
682c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
683c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                err = addH264CodecSpecificData(i);
684c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            }
685f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
686c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            if (err != OK) {
687c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                return err;
688f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
689f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
6907de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber
6917de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        if (track->mBytesPerSample != 0) {
6927de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber            // Assume all chunks are the same size for now.
6937de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber
6947de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber            off64_t offset;
6957de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber            size_t size;
6967de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber            bool isKey;
6977de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber            int64_t sampleTimeUs;
6987de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber            CHECK_EQ((status_t)OK,
6997de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber                     getSampleInfo(
7007de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber                         i, 0,
7017de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber                         &offset, &size, &isKey, &sampleTimeUs));
7027de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber
7037de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber            track->mRate *= size / track->mBytesPerSample;
7047de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        }
705f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
706f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
707f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mFoundIndex = true;
708f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
709f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
710f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
711f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
712f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatic size_t GetSizeWidth(size_t x) {
713f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t n = 1;
714f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (x > 127) {
715f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ++n;
716f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        x >>= 7;
717f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
718f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return n;
719f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
720f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
721f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatic uint8_t *EncodeSize(uint8_t *dst, size_t x) {
722f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (x > 127) {
723f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *dst++ = (x & 0x7f) | 0x80;
724f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        x >>= 7;
725f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
726f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = x;
727f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return dst;
728f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
729f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
730f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) {
731f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
732f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
733f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
734f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
735f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> csd = new ABuffer(len3);
736f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t *dst = csd->data();
737f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x03;
738f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    dst = EncodeSize(dst, len2 + 3);
739f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x00;  // ES_ID
740f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x00;
741f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
742f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
743f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x04;
744f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    dst = EncodeSize(dst, len1 + 13);
745f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x01;  // Video ISO/IEC 14496-2 Simple Profile
746f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    for (size_t i = 0; i < 12; ++i) {
747f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *dst++ = 0x00;
748f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
749f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
750f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x05;
751f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    dst = EncodeSize(dst, config->size());
752f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    memcpy(dst, config->data(), config->size());
753f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    dst += config->size();
754f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
755f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    // hexdump(csd->data(), csd->size());
756f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
757f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return csd;
758f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
759f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
760f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) {
761f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    Track *track = &mTracks.editItemAt(trackIndex);
762f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
763f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    off64_t offset;
764f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t size;
765f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    bool isKey;
7667de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    int64_t timeUs;
7677de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    status_t err =
7687de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        getSampleInfo(trackIndex, 0, &offset, &size, &isKey, &timeUs);
769f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
770f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (err != OK) {
771f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return err;
772f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
773f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
774f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
775f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
776f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
777f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < (ssize_t)size) {
778f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
779f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
780f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
781f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    // Extract everything up to the first VOP start code from the first
782f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    // frame's encoded data and use it to construct an ESDS with the
783f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    // codec specific data.
784f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
785f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t i = 0;
786f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    bool found = false;
787f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (i + 3 < buffer->size()) {
788f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) {
789f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            found = true;
790f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
791f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
792f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
793f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ++i;
794f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
795f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
796f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!found) {
797f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
798f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
799f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
800f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    buffer->setRange(0, i);
801f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
802f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer);
803f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size());
804f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
805f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
806f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
807f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
808c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huberstatus_t AVIExtractor::addH264CodecSpecificData(size_t trackIndex) {
809c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    Track *track = &mTracks.editItemAt(trackIndex);
810c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
811c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    off64_t offset;
812c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    size_t size;
813c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    bool isKey;
814c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    int64_t timeUs;
815c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
816c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    // Extract codec specific data from the first non-empty sample.
817c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
818c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    size_t sampleIndex = 0;
819c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    for (;;) {
820c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        status_t err =
821c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            getSampleInfo(
822c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                    trackIndex, sampleIndex, &offset, &size, &isKey, &timeUs);
823c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
824c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        if (err != OK) {
825c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            return err;
826c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        }
827c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
828c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        if (size > 0) {
829c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            break;
830c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        }
831c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
832c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        ++sampleIndex;
833c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    }
834c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
835c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
836c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
837c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
838c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    if (n < (ssize_t)size) {
839c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
840c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    }
841c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
842c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    sp<MetaData> meta = MakeAVCCodecSpecificData(buffer);
843c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
844c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    if (meta == NULL) {
845c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        LOGE("Unable to extract AVC codec specific data");
846c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        return ERROR_MALFORMED;
847c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    }
848c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
849c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    int32_t width, height;
850c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    CHECK(meta->findInt32(kKeyWidth, &width));
851c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    CHECK(meta->findInt32(kKeyHeight, &height));
852c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
853c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    uint32_t type;
854c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    const void *csd;
855c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    size_t csdSize;
856c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize));
857c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
858c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    track->mMeta->setInt32(kKeyWidth, width);
859c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    track->mMeta->setInt32(kKeyHeight, width);
860c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    track->mMeta->setData(kKeyAVCC, type, csd, csdSize);
861c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
862c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    return OK;
863c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber}
864c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
865f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::getSampleInfo(
866f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t trackIndex, size_t sampleIndex,
8677de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        off64_t *offset, size_t *size, bool *isKey,
8687de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        int64_t *sampleTimeUs) {
869f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (trackIndex >= mTracks.size()) {
870f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return -ERANGE;
871f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
872f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
873f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const Track &track = mTracks.itemAt(trackIndex);
874f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
875f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (sampleIndex >= track.mSamples.size()) {
876f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return -ERANGE;
877f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
878f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
879f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const SampleInfo &info = track.mSamples.itemAt(sampleIndex);
880f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
881f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!mOffsetsAreAbsolute) {
882f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *offset = info.mOffset + mMovieOffset + 8;
883f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else {
884f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *offset = info.mOffset;
885f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
886f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
887f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *size = 0;
888f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
889f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t tmp[8];
890f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(*offset, tmp, 8);
891f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
892f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < 8) {
893f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
894f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
895f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
896f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t chunkType = U32_AT(tmp);
897f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
898f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) {
899f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
900f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
901f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
902f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *offset += 8;
903f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *size = U32LE_AT(&tmp[4]);
904f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
905f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *isKey = info.mIsKey;
906f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
9077de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale;
9087de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber
909f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
910f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
911f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
9127de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huberstatus_t AVIExtractor::getSampleTime(
9137de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs) {
9147de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    off64_t offset;
9157de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    size_t size;
9167de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    bool isKey;
9177de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    return getSampleInfo(
9187de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber            trackIndex, sampleIndex, &offset, &size, &isKey, sampleTimeUs);
9197de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber}
9207de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber
921f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::getSampleIndexAtTime(
922f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t trackIndex,
923f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
924f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t *sampleIndex) const {
925f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (trackIndex >= mTracks.size()) {
926f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return -ERANGE;
927f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
928f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
929f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const Track &track = mTracks.itemAt(trackIndex);
930f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
931f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t closestSampleIndex =
932f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        timeUs / track.mRate * track.mScale / 1000000ll;
933f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
934f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t numSamples = track.mSamples.size();
935f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
936f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (closestSampleIndex < 0) {
937f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        closestSampleIndex = 0;
938f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else if (closestSampleIndex >= numSamples) {
939f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        closestSampleIndex = numSamples - 1;
940f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
941f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
942f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) {
943f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *sampleIndex = closestSampleIndex;
944f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
945f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return OK;
946f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
947f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
948f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t prevSyncSampleIndex = closestSampleIndex;
949f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (prevSyncSampleIndex >= 0) {
950f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const SampleInfo &info =
951f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            track.mSamples.itemAt(prevSyncSampleIndex);
952f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
953f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (info.mIsKey) {
954f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
955f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
956f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
957f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        --prevSyncSampleIndex;
958f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
959f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
960f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t nextSyncSampleIndex = closestSampleIndex;
961f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (nextSyncSampleIndex < numSamples) {
962f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const SampleInfo &info =
963f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            track.mSamples.itemAt(nextSyncSampleIndex);
964f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
965f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (info.mIsKey) {
966f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
967f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
968f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
969f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ++nextSyncSampleIndex;
970f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
971f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
972f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    switch (mode) {
973f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC:
974f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
975f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            *sampleIndex = prevSyncSampleIndex;
976f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
977f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR;
978f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
979f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
980f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case MediaSource::ReadOptions::SEEK_NEXT_SYNC:
981f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
982f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            *sampleIndex = nextSyncSampleIndex;
983f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
984f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR;
985f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
986f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
987f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC:
988f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
989f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) {
990f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return UNKNOWN_ERROR;
991f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
992f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
993f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (prevSyncSampleIndex < 0) {
994f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                *sampleIndex = nextSyncSampleIndex;
995f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return OK;
996f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
997f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
998f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (nextSyncSampleIndex >= numSamples) {
999f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                *sampleIndex = prevSyncSampleIndex;
1000f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return OK;
1001f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
1002f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1003f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            size_t dist1 = closestSampleIndex - prevSyncSampleIndex;
1004f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            size_t dist2 = nextSyncSampleIndex - closestSampleIndex;
1005f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1006f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            *sampleIndex =
1007f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex;
1008f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1009f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return OK;
1010f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
1011f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1012f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        default:
1013f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            TRESPASS();
1014f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
1015f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1016f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
1017f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1018f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberbool SniffAVI(
1019f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
1020f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        sp<AMessage> *) {
1021f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    char tmp[12];
1022f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (source->readAt(0, tmp, 12) < 12) {
1023f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return false;
1024f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1025f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1026f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) {
1027f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI);
1028c6c4572cd35f739bfac2aa439b3664032e03dcd8Andreas Huber
1029c6c4572cd35f739bfac2aa439b3664032e03dcd8Andreas Huber        // Just a tad over the mp3 extractor's confidence, since
1030c6c4572cd35f739bfac2aa439b3664032e03dcd8Andreas Huber        // these .avi files may contain .mp3 content that otherwise would
1031c6c4572cd35f739bfac2aa439b3664032e03dcd8Andreas Huber        // mistakenly lead to us identifying the entire file as a .mp3 file.
1032c6c4572cd35f739bfac2aa439b3664032e03dcd8Andreas Huber        *confidence = 0.21;
1033f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1034f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return true;
1035f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1036f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1037f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return false;
1038f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
1039f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1040f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}  // namespace android
1041