AVIExtractor.cpp revision f8374dec590223ebdd6959b26d9ba90749dd8328
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
21f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include "include/AVIExtractor.h"
22f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
23f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <binder/ProcessState.h>
24f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/foundation/hexdump.h>
25f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
26f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/foundation/ADebug.h>
27f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/DataSource.h>
28f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaBuffer.h>
29f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
30f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaDefs.h>
31f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaErrors.h>
32f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MetaData.h>
33f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/Utils.h>
34f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
35f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubernamespace android {
36f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
37f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstruct AVIExtractor::AVISource : public MediaSource {
38f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    AVISource(const sp<AVIExtractor> &extractor, size_t trackIndex);
39f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
40f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual status_t start(MetaData *params);
41f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual status_t stop();
42f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
43f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual sp<MetaData> getFormat();
44f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
45f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual status_t read(
46f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            MediaBuffer **buffer, const ReadOptions *options);
47f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
48f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberprotected:
49f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual ~AVISource();
50f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
51f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberprivate:
52f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<AVIExtractor> mExtractor;
53f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t mTrackIndex;
54f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const AVIExtractor::Track &mTrack;
55f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    MediaBufferGroup *mBufferGroup;
56f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t mSampleIndex;
57f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
58f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(AVISource);
59f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber};
60f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
61f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber////////////////////////////////////////////////////////////////////////////////
62f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
63f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::AVISource::AVISource(
64f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const sp<AVIExtractor> &extractor, size_t trackIndex)
65f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    : mExtractor(extractor),
66f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber      mTrackIndex(trackIndex),
67f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber      mTrack(mExtractor->mTracks.itemAt(trackIndex)),
68f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber      mBufferGroup(NULL) {
69f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
70f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
71f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::AVISource::~AVISource() {
72f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mBufferGroup) {
73f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        stop();
74f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
75f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
76f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
77f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::AVISource::start(MetaData *params) {
78f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    CHECK(!mBufferGroup);
79f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
80f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mBufferGroup = new MediaBufferGroup;
81f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
82f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
83f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
84f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mSampleIndex = 0;
85f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
86f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
87f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
88f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
89f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::AVISource::stop() {
90f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    CHECK(mBufferGroup);
91f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
92f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    delete mBufferGroup;
93f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mBufferGroup = NULL;
94f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
95f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
96f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
97f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
98f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MetaData> AVIExtractor::AVISource::getFormat() {
99f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return mTrack.mMeta;
100f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
101f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
102f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::AVISource::read(
103f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
104f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    CHECK(mBufferGroup);
105f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
106f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *buffer = NULL;
107f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
108f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    int64_t seekTimeUs;
109f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ReadOptions::SeekMode seekMode;
110f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
111f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        status_t err =
112f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            mExtractor->getSampleIndexAtTime(
113f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    mTrackIndex, seekTimeUs, seekMode, &mSampleIndex);
114f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
115f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (err != OK) {
116f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_END_OF_STREAM;
117f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
118f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
119f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
120f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    int64_t timeUs =
121f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        (mSampleIndex * 1000000ll * mTrack.mRate) / mTrack.mScale;
122f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
123f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    off64_t offset;
124f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t size;
125f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    bool isKey;
126f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    status_t err = mExtractor->getSampleInfo(
127f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            mTrackIndex, mSampleIndex, &offset, &size, &isKey);
128f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
129f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ++mSampleIndex;
130f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
131f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (err != OK) {
132f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_END_OF_STREAM;
133f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
134f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
135f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    MediaBuffer *out;
136f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK);
137f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
138f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size);
139f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
140f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < (ssize_t)size) {
141f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
142f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
143f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
144f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    out->set_range(0, size);
145f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
146f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    out->meta_data()->setInt64(kKeyTime, timeUs);
147f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
148f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (isKey) {
149f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        out->meta_data()->setInt32(kKeyIsSyncFrame, 1);
150f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
151f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
152f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *buffer = out;
153f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
154f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
155f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
156f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
157f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber////////////////////////////////////////////////////////////////////////////////
158f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
159f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::AVIExtractor(const sp<DataSource> &dataSource)
160f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    : mDataSource(dataSource) {
161f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mInitCheck = parseHeaders();
162f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
163f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mInitCheck != OK) {
164f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        mTracks.clear();
165f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
166f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
167f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
168f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::~AVIExtractor() {
169f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
170f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
171f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersize_t AVIExtractor::countTracks() {
172f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return mTracks.size();
173f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
174f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
175f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MediaSource> AVIExtractor::getTrack(size_t index) {
176f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return index < mTracks.size() ? new AVISource(this, index) : NULL;
177f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
178f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
179f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MetaData> AVIExtractor::getTrackMetaData(
180f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t index, uint32_t flags) {
181f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL;
182f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
183f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
184f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MetaData> AVIExtractor::getMetaData() {
185f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<MetaData> meta = new MetaData;
186f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
187f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mInitCheck == OK) {
188f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_AVI);
189f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
190f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
191f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return meta;
192f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
193f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
194f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseHeaders() {
195f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mTracks.clear();
196f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mMovieOffset = 0;
197f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mFoundIndex = false;
198f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mOffsetsAreAbsolute = false;
199f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
200f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t res = parseChunk(0ll, -1ll);
201f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
202f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (res < 0) {
203f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return (status_t)res;
204f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
205f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
206f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mMovieOffset == 0ll || !mFoundIndex) {
207f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
208f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
209f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
210f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
211f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
212f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
213f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberssize_t AVIExtractor::parseChunk(off64_t offset, off64_t size, int depth) {
214f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (size >= 0 && size < 8) {
215f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
216f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
217f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
218f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t tmp[12];
219f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, tmp, 8);
220f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
221f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < 8) {
222f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
223f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
224f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
225f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t fourcc = U32_AT(tmp);
226f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t chunkSize = U32LE_AT(&tmp[4]);
227f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
228f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (size >= 0 && chunkSize + 8 > size) {
229f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
230f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
231f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
232f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    static const char kPrefix[] = "                              ";
233f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const char *prefix = &kPrefix[strlen(kPrefix) - 2 * depth];
234f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
235f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (fourcc == FOURCC('L', 'I', 'S', 'T')
236f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            || fourcc == FOURCC('R', 'I', 'F', 'F')) {
237f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        // It's a list of chunks
238f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
239f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (size >= 0 && size < 12) {
240f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
241f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
242f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
243f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        n = mDataSource->readAt(offset + 8, &tmp[8], 4);
244f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
245f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (n < 4) {
246f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
247f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
248f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
249f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t subFourcc = U32_AT(&tmp[8]);
250f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
251f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        LOGV("%s offset 0x%08llx LIST of '%c%c%c%c', size %d",
252f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             prefix,
253f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             offset,
254f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)(subFourcc >> 24),
255f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)((subFourcc >> 16) & 0xff),
256f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)((subFourcc >> 8) & 0xff),
257f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)(subFourcc & 0xff),
258f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             chunkSize - 4);
259f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
260f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (subFourcc == FOURCC('m', 'o', 'v', 'i')) {
261f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            // We're not going to parse this, but will take note of the
262f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            // offset.
263f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
264f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            mMovieOffset = offset;
265f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        } else {
266f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            off64_t subOffset = offset + 12;
267f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            off64_t subOffsetLimit = subOffset + chunkSize - 4;
268f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            while (subOffset < subOffsetLimit) {
269f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                ssize_t res =
270f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    parseChunk(subOffset, subOffsetLimit - subOffset, depth + 1);
271f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
272f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                if (res < 0) {
273f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    return res;
274f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                }
275f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
276f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                subOffset += res;
277f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
278f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
279f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else {
280f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        LOGV("%s offset 0x%08llx CHUNK '%c%c%c%c'",
281f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             prefix,
282f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             offset,
283f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)(fourcc >> 24),
284f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)((fourcc >> 16) & 0xff),
285f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)((fourcc >> 8) & 0xff),
286f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)(fourcc & 0xff));
287f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
288f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        status_t err = OK;
289f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
290f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        switch (fourcc) {
291f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            case FOURCC('s', 't', 'r', 'h'):
292f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            {
293f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                err = parseStreamHeader(offset + 8, chunkSize);
294f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                break;
295f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
296f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
297f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            case FOURCC('s', 't', 'r', 'f'):
298f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            {
299f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                err = parseStreamFormat(offset + 8, chunkSize);
300f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                break;
301f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
302f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
303f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            case FOURCC('i', 'd', 'x', '1'):
304f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            {
305f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                err = parseIndex(offset + 8, chunkSize);
306f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                break;
307f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
308f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
309f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            default:
310f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                break;
311f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
312f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
313f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (err != OK) {
314f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return err;
315f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
316f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
317f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
318f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (chunkSize & 1) {
319f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ++chunkSize;
320f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
321f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
322f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return chunkSize + 8;
323f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
324f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
325f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatic const char *GetMIMETypeForHandler(uint32_t handler) {
326f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    switch (handler) {
327f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        // Wow... shamelessly copied from
328f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        // http://wiki.multimedia.cx/index.php?title=ISO_MPEG-4
329f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
330f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('3', 'I', 'V', '2'):
331f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('3', 'i', 'v', '2'):
332f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('B', 'L', 'Z', '0'):
333f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'I', 'G', 'I'):
334f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'I', 'V', '1'):
335f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('d', 'i', 'v', '1'):
336f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'I', 'V', 'X'):
337f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('d', 'i', 'v', 'x'):
338f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'X', '5', '0'):
339f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('d', 'x', '5', '0'):
340f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'X', 'G', 'M'):
341f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('E', 'M', '4', 'A'):
342f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('E', 'P', 'H', 'V'):
343f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('F', 'M', 'P', '4'):
344f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('f', 'm', 'p', '4'):
345f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('F', 'V', 'F', 'W'):
346f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('H', 'D', 'X', '4'):
347f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('h', 'd', 'x', '4'):
348f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', '4', 'C', 'C'):
349f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', '4', 'S', '2'):
350f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('m', '4', 's', '2'):
351f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', 'P', '4', 'S'):
352f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('m', 'p', '4', 's'):
353f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', 'P', '4', 'V'):
354f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
355f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', 'V', 'X', 'M'):
356f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('R', 'M', 'P', '4'):
357f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('S', 'E', 'D', 'G'):
358f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('S', 'M', 'P', '4'):
359f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('U', 'M', 'P', '4'):
360f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('W', 'V', '1', 'F'):
361f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('X', 'V', 'I', 'D'):
362f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('X', 'v', 'i', 'D'):
363f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('x', 'v', 'i', 'd'):
364f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('X', 'V', 'I', 'X'):
365f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
366f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
367f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        default:
368f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return NULL;
369f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
370f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
371f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
372f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) {
373f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (size != 56) {
374f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
375f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
376f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
377f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mTracks.size() > 99) {
378f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return -ERANGE;
379f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
380f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
381f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
382f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
383f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
384f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < (ssize_t)size) {
385f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
386f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
387f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
388f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const uint8_t *data = buffer->data();
389f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
390f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t type = U32_AT(data);
391f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t handler = U32_AT(&data[4]);
392f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t flags = U32LE_AT(&data[8]);
393f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
394f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<MetaData> meta = new MetaData;
395f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
396f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t rate = U32LE_AT(&data[20]);
397f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t scale = U32LE_AT(&data[24]);
398f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
399f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const char *mime = NULL;
400f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    Track::Kind kind = Track::OTHER;
401f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
402f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (type == FOURCC('v', 'i', 'd', 's')) {
403f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        mime = GetMIMETypeForHandler(handler);
404f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
405f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (mime && strncasecmp(mime, "video/", 6)) {
406f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
407f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
408f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
409f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        kind = Track::VIDEO;
410f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else if (type == FOURCC('a', 'u', 'd', 's')) {
411f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (mime && strncasecmp(mime, "audio/", 6)) {
412f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
413f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
414f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
415f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        kind = Track::AUDIO;
416f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
417f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
418f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!mime) {
419f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        mime = "application/octet-stream";
420f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
421f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
422f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    meta->setCString(kKeyMIMEType, mime);
423f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
424f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mTracks.push();
425f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
426f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
427f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mMeta = meta;
428f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mRate = rate;
429f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mScale = scale;
430f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mKind = kind;
431f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mNumSyncSamples = 0;
432f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mThumbnailSampleSize = 0;
433f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mThumbnailSampleIndex = -1;
434f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mMaxSampleSize = 0;
435f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
436f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
437f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
438f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
439f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) {
440f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mTracks.isEmpty()) {
441f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
442f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
443f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
444f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
445f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
446f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (track->mKind == Track::OTHER) {
447f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        // We don't support this content, but that's not a parsing error.
448f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return OK;
449f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
450f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
451f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    bool isVideo = (track->mKind == Track::VIDEO);
452f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
453f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if ((isVideo && size < 40) || (!isVideo && size < 18)) {
454f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        // Expected a BITMAPINFO or WAVEFORMATEX structure, respectively.
455f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
456f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
457f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
458f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
459f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
460f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
461f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < (ssize_t)size) {
462f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
463f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
464f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
465f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const uint8_t *data = buffer->data();
466f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
467f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (isVideo) {
468f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t width = U32LE_AT(&data[4]);
469f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t height = U32LE_AT(&data[8]);
470f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
471f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeyWidth, width);
472f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeyHeight, height);
473f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else {
474f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t format = U16LE_AT(data);
475f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (format == 0x55) {
476f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
477f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
478f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
479f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t numChannels = U16LE_AT(&data[2]);
480f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t sampleRate = U32LE_AT(&data[4]);
481f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
482f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeyChannelCount, numChannels);
483f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeySampleRate, sampleRate);
484f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
485f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
486f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
487f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
488f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
489f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber// static
490f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberbool AVIExtractor::IsCorrectChunkType(
491f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) {
492f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t chunkBase = chunkType & 0xffff;
493f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
494f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    switch (kind) {
495f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case Track::VIDEO:
496f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
497f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (chunkBase != FOURCC(0, 0, 'd', 'c')
498f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    && chunkBase != FOURCC(0, 0, 'd', 'b')) {
499f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return false;
500f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
501f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
502f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
503f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
504f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case Track::AUDIO:
505f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
506f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (chunkBase != FOURCC(0, 0, 'w', 'b')) {
507f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return false;
508f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
509f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
510f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
511f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
512f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        default:
513f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
514f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
515f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
516f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (trackIndex < 0) {
517f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return true;
518f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
519f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
520f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t hi = chunkType >> 24;
521f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t lo = (chunkType >> 16) & 0xff;
522f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
523f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
524f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return false;
525f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
526f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
527f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (trackIndex != (10 * (hi - '0') + (lo - '0'))) {
528f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return false;
529f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
530f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
531f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return true;
532f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
533f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
534f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
535f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if ((size % 16) != 0) {
536f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
537f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
538f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
539f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
540f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
541f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
542f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < (ssize_t)size) {
543f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
544f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
545f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
546f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const uint8_t *data = buffer->data();
547f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
548f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (size > 0) {
549f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t chunkType = U32_AT(data);
550f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
551f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint8_t hi = chunkType >> 24;
552f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint8_t lo = (chunkType >> 16) & 0xff;
553f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
554f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
555f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
556f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
557f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
558f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t trackIndex = 10 * (hi - '0') + (lo - '0');
559f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
560f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (trackIndex >= mTracks.size()) {
561f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
562f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
563f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
564f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        Track *track = &mTracks.editItemAt(trackIndex);
565f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
566f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (!IsCorrectChunkType(-1, track->mKind, chunkType)) {
567f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
568f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
569f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
570f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (track->mKind == Track::OTHER) {
571f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            data += 16;
572f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            size -= 16;
573f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            continue;
574f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
575f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
576f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t flags = U32LE_AT(&data[4]);
577f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t offset = U32LE_AT(&data[8]);
578f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t chunkSize = U32LE_AT(&data[12]);
579f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
580f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (chunkSize > track->mMaxSampleSize) {
581f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            track->mMaxSampleSize = chunkSize;
582f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
583f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
584f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mSamples.push();
585f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
586f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        SampleInfo *info =
587f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            &track->mSamples.editItemAt(track->mSamples.size() - 1);
588f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
589f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        info->mOffset = offset;
590f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        info->mIsKey = (flags & 0x10) != 0;
591f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
592f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (info->mIsKey) {
593f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            static const size_t kMaxNumSyncSamplesToScan = 20;
594f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
595f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) {
596f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                if (chunkSize > track->mThumbnailSampleSize) {
597f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    track->mThumbnailSampleSize = chunkSize;
598f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
599f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    track->mThumbnailSampleIndex =
600f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                        track->mSamples.size() - 1;
601f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                }
602f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
603f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
604f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            ++track->mNumSyncSamples;
605f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
606f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
607f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        data += 16;
608f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size -= 16;
609f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
610f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
611f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!mTracks.isEmpty()) {
612f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        off64_t offset;
613f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t size;
614f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        bool isKey;
615f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        status_t err = getSampleInfo(0, 0, &offset, &size, &isKey);
616f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
617f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (err != OK) {
618f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            mOffsetsAreAbsolute = !mOffsetsAreAbsolute;
619f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            err = getSampleInfo(0, 0, &offset, &size, &isKey);
620f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
621f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (err != OK) {
622f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return err;
623f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
624f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
625f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
626f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        LOGV("Chunk offsets are %s",
627f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative");
628f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
629f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
630f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
631f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        Track *track = &mTracks.editItemAt(i);
632f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
633f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        int64_t durationUs =
634f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            (track->mSamples.size() * 1000000ll * track->mRate) / track->mScale;
635f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
636f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        LOGV("track %d duration = %.2f secs", i, durationUs / 1E6);
637f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
638f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt64(kKeyDuration, durationUs);
639f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize);
640f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
641f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const char *tmp;
642f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp));
643f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
644f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        AString mime = tmp;
645f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
646f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (!strncasecmp("video/", mime.c_str(), 6)
647f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                && track->mThumbnailSampleIndex >= 0) {
648f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            int64_t thumbnailTimeUs =
649f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                (track->mThumbnailSampleIndex * 1000000ll * track->mRate)
650f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    / track->mScale;
651f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
652f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
653f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
654f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
655f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                status_t err = addMPEG4CodecSpecificData(i);
656f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
657f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                if (err != OK) {
658f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    return err;
659f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                }
660f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
661f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
662f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
663f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
664f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mFoundIndex = true;
665f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
666f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
667f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
668f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
669f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatic size_t GetSizeWidth(size_t x) {
670f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t n = 1;
671f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (x > 127) {
672f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ++n;
673f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        x >>= 7;
674f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
675f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return n;
676f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
677f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
678f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatic uint8_t *EncodeSize(uint8_t *dst, size_t x) {
679f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (x > 127) {
680f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *dst++ = (x & 0x7f) | 0x80;
681f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        x >>= 7;
682f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
683f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = x;
684f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return dst;
685f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
686f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
687f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) {
688f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
689f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
690f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
691f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
692f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> csd = new ABuffer(len3);
693f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t *dst = csd->data();
694f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x03;
695f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    dst = EncodeSize(dst, len2 + 3);
696f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x00;  // ES_ID
697f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x00;
698f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
699f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
700f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x04;
701f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    dst = EncodeSize(dst, len1 + 13);
702f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x01;  // Video ISO/IEC 14496-2 Simple Profile
703f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    for (size_t i = 0; i < 12; ++i) {
704f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *dst++ = 0x00;
705f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
706f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
707f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x05;
708f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    dst = EncodeSize(dst, config->size());
709f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    memcpy(dst, config->data(), config->size());
710f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    dst += config->size();
711f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
712f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    // hexdump(csd->data(), csd->size());
713f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
714f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return csd;
715f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
716f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
717f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) {
718f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    Track *track = &mTracks.editItemAt(trackIndex);
719f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
720f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    off64_t offset;
721f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t size;
722f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    bool isKey;
723f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    status_t err = getSampleInfo(trackIndex, 0, &offset, &size, &isKey);
724f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
725f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (err != OK) {
726f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return err;
727f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
728f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
729f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
730f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
731f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
732f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < (ssize_t)size) {
733f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
734f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
735f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
736f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    // Extract everything up to the first VOP start code from the first
737f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    // frame's encoded data and use it to construct an ESDS with the
738f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    // codec specific data.
739f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
740f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t i = 0;
741f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    bool found = false;
742f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (i + 3 < buffer->size()) {
743f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) {
744f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            found = true;
745f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
746f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
747f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
748f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ++i;
749f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
750f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
751f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!found) {
752f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
753f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
754f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
755f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    buffer->setRange(0, i);
756f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
757f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer);
758f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size());
759f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
760f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
761f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
762f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
763f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::getSampleInfo(
764f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t trackIndex, size_t sampleIndex,
765f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        off64_t *offset, size_t *size, bool *isKey) {
766f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (trackIndex >= mTracks.size()) {
767f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return -ERANGE;
768f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
769f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
770f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const Track &track = mTracks.itemAt(trackIndex);
771f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
772f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (sampleIndex >= track.mSamples.size()) {
773f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return -ERANGE;
774f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
775f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
776f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const SampleInfo &info = track.mSamples.itemAt(sampleIndex);
777f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
778f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!mOffsetsAreAbsolute) {
779f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *offset = info.mOffset + mMovieOffset + 8;
780f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else {
781f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *offset = info.mOffset;
782f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
783f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
784f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *size = 0;
785f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
786f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t tmp[8];
787f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(*offset, tmp, 8);
788f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
789f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < 8) {
790f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
791f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
792f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
793f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t chunkType = U32_AT(tmp);
794f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
795f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) {
796f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
797f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
798f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
799f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *offset += 8;
800f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *size = U32LE_AT(&tmp[4]);
801f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
802f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *isKey = info.mIsKey;
803f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
804f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
805f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
806f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
807f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::getSampleIndexAtTime(
808f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t trackIndex,
809f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
810f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t *sampleIndex) const {
811f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (trackIndex >= mTracks.size()) {
812f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return -ERANGE;
813f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
814f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
815f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const Track &track = mTracks.itemAt(trackIndex);
816f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
817f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t closestSampleIndex =
818f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        timeUs / track.mRate * track.mScale / 1000000ll;
819f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
820f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t numSamples = track.mSamples.size();
821f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
822f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (closestSampleIndex < 0) {
823f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        closestSampleIndex = 0;
824f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else if (closestSampleIndex >= numSamples) {
825f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        closestSampleIndex = numSamples - 1;
826f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
827f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
828f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) {
829f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *sampleIndex = closestSampleIndex;
830f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
831f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return OK;
832f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
833f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
834f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t prevSyncSampleIndex = closestSampleIndex;
835f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (prevSyncSampleIndex >= 0) {
836f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const SampleInfo &info =
837f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            track.mSamples.itemAt(prevSyncSampleIndex);
838f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
839f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (info.mIsKey) {
840f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
841f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
842f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
843f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        --prevSyncSampleIndex;
844f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
845f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
846f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t nextSyncSampleIndex = closestSampleIndex;
847f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (nextSyncSampleIndex < numSamples) {
848f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const SampleInfo &info =
849f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            track.mSamples.itemAt(nextSyncSampleIndex);
850f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
851f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (info.mIsKey) {
852f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
853f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
854f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
855f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ++nextSyncSampleIndex;
856f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
857f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
858f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    switch (mode) {
859f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC:
860f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
861f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            *sampleIndex = prevSyncSampleIndex;
862f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
863f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR;
864f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
865f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
866f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case MediaSource::ReadOptions::SEEK_NEXT_SYNC:
867f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
868f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            *sampleIndex = nextSyncSampleIndex;
869f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
870f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR;
871f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
872f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
873f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC:
874f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
875f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) {
876f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return UNKNOWN_ERROR;
877f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
878f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
879f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (prevSyncSampleIndex < 0) {
880f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                *sampleIndex = nextSyncSampleIndex;
881f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return OK;
882f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
883f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
884f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (nextSyncSampleIndex >= numSamples) {
885f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                *sampleIndex = prevSyncSampleIndex;
886f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return OK;
887f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
888f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
889f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            size_t dist1 = closestSampleIndex - prevSyncSampleIndex;
890f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            size_t dist2 = nextSyncSampleIndex - closestSampleIndex;
891f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
892f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            *sampleIndex =
893f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex;
894f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
895f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return OK;
896f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
897f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
898f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        default:
899f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            TRESPASS();
900f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
901f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
902f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
903f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
904f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberbool SniffAVI(
905f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
906f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        sp<AMessage> *) {
907f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    char tmp[12];
908f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (source->readAt(0, tmp, 12) < 12) {
909f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return false;
910f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
911f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
912f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) {
913f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI);
914f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *confidence = 0.2;
915f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
916f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return true;
917f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
918f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
919f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return false;
920f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
921f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
922f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}  // namespace android
923