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