AVIExtractor.cpp revision 63749954aa828b3f73b4738659eaea5eaeeca874
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    off64_t offset;
121cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t size;
122cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    bool isKey;
12363749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    int64_t timeUs;
124cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    status_t err = mExtractor->getSampleInfo(
12563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs);
126cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
127cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ++mSampleIndex;
128cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
129cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (err != OK) {
130cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_END_OF_STREAM;
131cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
132cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
133cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    MediaBuffer *out;
134cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK);
135cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
136cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size);
137cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
138cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < (ssize_t)size) {
139cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
140cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
141cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
142cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    out->set_range(0, size);
143cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
144cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    out->meta_data()->setInt64(kKeyTime, timeUs);
145cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
146cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (isKey) {
147cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        out->meta_data()->setInt32(kKeyIsSyncFrame, 1);
148cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
149cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
150cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *buffer = out;
151cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
152cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
153cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
154cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
155cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber////////////////////////////////////////////////////////////////////////////////
156cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
157cabb7da7125a80c55233bd23959327424e9646ccAndreas HuberAVIExtractor::AVIExtractor(const sp<DataSource> &dataSource)
158cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    : mDataSource(dataSource) {
159cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mInitCheck = parseHeaders();
160cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
161cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mInitCheck != OK) {
162cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        mTracks.clear();
163cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
164cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
165cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
166cabb7da7125a80c55233bd23959327424e9646ccAndreas HuberAVIExtractor::~AVIExtractor() {
167cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
168cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
169cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersize_t AVIExtractor::countTracks() {
170cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return mTracks.size();
171cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
172cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
173cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MediaSource> AVIExtractor::getTrack(size_t index) {
174cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return index < mTracks.size() ? new AVISource(this, index) : NULL;
175cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
176cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
177cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MetaData> AVIExtractor::getTrackMetaData(
178cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t index, uint32_t flags) {
179cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL;
180cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
181cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
182cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MetaData> AVIExtractor::getMetaData() {
183cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<MetaData> meta = new MetaData;
184cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
185cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mInitCheck == OK) {
186cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_AVI);
187cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
188cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
189cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return meta;
190cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
191cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
192cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseHeaders() {
193cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mTracks.clear();
194cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mMovieOffset = 0;
195cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mFoundIndex = false;
196cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mOffsetsAreAbsolute = false;
197cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
198cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t res = parseChunk(0ll, -1ll);
199cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
200cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (res < 0) {
201cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return (status_t)res;
202cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
203cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
204cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mMovieOffset == 0ll || !mFoundIndex) {
205cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
206cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
207cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
208cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
209cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
210cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
211cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberssize_t AVIExtractor::parseChunk(off64_t offset, off64_t size, int depth) {
212cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (size >= 0 && size < 8) {
213cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
214cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
215cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
216cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t tmp[12];
217cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, tmp, 8);
218cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
219cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < 8) {
220cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
221cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
222cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
223cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t fourcc = U32_AT(tmp);
224cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t chunkSize = U32LE_AT(&tmp[4]);
225cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
226cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (size >= 0 && chunkSize + 8 > size) {
227cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
228cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
229cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
230cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    static const char kPrefix[] = "                              ";
231cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const char *prefix = &kPrefix[strlen(kPrefix) - 2 * depth];
232cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
233cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (fourcc == FOURCC('L', 'I', 'S', 'T')
234cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            || fourcc == FOURCC('R', 'I', 'F', 'F')) {
235cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        // It's a list of chunks
236cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
237cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (size >= 0 && size < 12) {
238cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
239cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
240cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
241cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        n = mDataSource->readAt(offset + 8, &tmp[8], 4);
242cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
243cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (n < 4) {
244cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
245cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
246cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
247cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t subFourcc = U32_AT(&tmp[8]);
248cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
249cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        LOGV("%s offset 0x%08llx LIST of '%c%c%c%c', size %d",
250cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             prefix,
251cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             offset,
252cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)(subFourcc >> 24),
253cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)((subFourcc >> 16) & 0xff),
254cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)((subFourcc >> 8) & 0xff),
255cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)(subFourcc & 0xff),
256cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             chunkSize - 4);
257cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
258cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (subFourcc == FOURCC('m', 'o', 'v', 'i')) {
259cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            // We're not going to parse this, but will take note of the
260cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            // offset.
261cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
262cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            mMovieOffset = offset;
263cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        } else {
264cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            off64_t subOffset = offset + 12;
265cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            off64_t subOffsetLimit = subOffset + chunkSize - 4;
266cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            while (subOffset < subOffsetLimit) {
267cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                ssize_t res =
268cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    parseChunk(subOffset, subOffsetLimit - subOffset, depth + 1);
269cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
270cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                if (res < 0) {
271cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    return res;
272cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                }
273cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
274cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                subOffset += res;
275cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
276cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
277cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    } else {
278cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        LOGV("%s offset 0x%08llx CHUNK '%c%c%c%c'",
279cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             prefix,
280cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             offset,
281cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)(fourcc >> 24),
282cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)((fourcc >> 16) & 0xff),
283cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)((fourcc >> 8) & 0xff),
284cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)(fourcc & 0xff));
285cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
286cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        status_t err = OK;
287cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
288cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        switch (fourcc) {
289cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            case FOURCC('s', 't', 'r', 'h'):
290cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            {
291cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                err = parseStreamHeader(offset + 8, chunkSize);
292cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                break;
293cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
294cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
295cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            case FOURCC('s', 't', 'r', 'f'):
296cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            {
297cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                err = parseStreamFormat(offset + 8, chunkSize);
298cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                break;
299cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
300cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
301cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            case FOURCC('i', 'd', 'x', '1'):
302cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            {
303cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                err = parseIndex(offset + 8, chunkSize);
304cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                break;
305cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
306cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
307cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            default:
308cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                break;
309cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
310cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
311cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (err != OK) {
312cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return err;
313cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
314cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
315cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
316cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (chunkSize & 1) {
317cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ++chunkSize;
318cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
319cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
320cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return chunkSize + 8;
321cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
322cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
323cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatic const char *GetMIMETypeForHandler(uint32_t handler) {
324cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    switch (handler) {
325cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        // Wow... shamelessly copied from
326cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        // http://wiki.multimedia.cx/index.php?title=ISO_MPEG-4
327cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
328cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('3', 'I', 'V', '2'):
329cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('3', 'i', 'v', '2'):
330cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('B', 'L', 'Z', '0'):
331cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'I', 'G', 'I'):
332cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'I', 'V', '1'):
333cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('d', 'i', 'v', '1'):
334cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'I', 'V', 'X'):
335cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('d', 'i', 'v', 'x'):
336cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'X', '5', '0'):
337cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('d', 'x', '5', '0'):
338cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'X', 'G', 'M'):
339cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('E', 'M', '4', 'A'):
340cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('E', 'P', 'H', 'V'):
341cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('F', 'M', 'P', '4'):
342cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('f', 'm', 'p', '4'):
343cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('F', 'V', 'F', 'W'):
344cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('H', 'D', 'X', '4'):
345cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('h', 'd', 'x', '4'):
346cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', '4', 'C', 'C'):
347cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', '4', 'S', '2'):
348cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('m', '4', 's', '2'):
349cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', 'P', '4', 'S'):
350cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('m', 'p', '4', 's'):
351cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', 'P', '4', 'V'):
352cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('m', 'p', '4', 'v'):
353cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', 'V', 'X', 'M'):
354cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('R', 'M', 'P', '4'):
355cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('S', 'E', 'D', 'G'):
356cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('S', 'M', 'P', '4'):
357cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('U', 'M', 'P', '4'):
358cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('W', 'V', '1', 'F'):
359cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('X', 'V', 'I', 'D'):
360cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('X', 'v', 'i', 'D'):
361cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('x', 'v', 'i', 'd'):
362cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('X', 'V', 'I', 'X'):
363cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
364cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
365cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        default:
366cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return NULL;
367cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
368cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
369cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
370cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) {
371cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (size != 56) {
372cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
373cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
374cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
375cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mTracks.size() > 99) {
376cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return -ERANGE;
377cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
378cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
379cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> buffer = new ABuffer(size);
380cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
381cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
382cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < (ssize_t)size) {
383cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
384cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
385cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
386cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const uint8_t *data = buffer->data();
387cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
388cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t type = U32_AT(data);
389cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t handler = U32_AT(&data[4]);
390cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t flags = U32LE_AT(&data[8]);
391cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
392cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<MetaData> meta = new MetaData;
393cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
394cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t rate = U32LE_AT(&data[20]);
395cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t scale = U32LE_AT(&data[24]);
396cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
39763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    uint32_t sampleSize = U32LE_AT(&data[44]);
39863749954aa828b3f73b4738659eaea5eaeeca874Andreas 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;
43063749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    track->mBytesPerSample = sampleSize;
431cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mKind = kind;
432cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mNumSyncSamples = 0;
433cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mThumbnailSampleSize = 0;
434cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mThumbnailSampleIndex = -1;
435cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mMaxSampleSize = 0;
436cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
437cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
438cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
439cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
440cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) {
441cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mTracks.isEmpty()) {
442cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
443cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
444cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
445cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
446cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
447cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (track->mKind == Track::OTHER) {
448cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        // We don't support this content, but that's not a parsing error.
449cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return OK;
450cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
451cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
452cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    bool isVideo = (track->mKind == Track::VIDEO);
453cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
454cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if ((isVideo && size < 40) || (!isVideo && size < 18)) {
455cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        // Expected a BITMAPINFO or WAVEFORMATEX structure, respectively.
456cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
457cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
458cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
459cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> buffer = new ABuffer(size);
460cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
461cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
462cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < (ssize_t)size) {
463cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
464cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
465cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
466cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const uint8_t *data = buffer->data();
467cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
468cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (isVideo) {
469cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t width = U32LE_AT(&data[4]);
470cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t height = U32LE_AT(&data[8]);
471cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
472cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeyWidth, width);
473cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeyHeight, height);
474cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    } else {
475cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t format = U16LE_AT(data);
476cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (format == 0x55) {
477cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
478cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
479cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
480cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t numChannels = U16LE_AT(&data[2]);
481cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t sampleRate = U32LE_AT(&data[4]);
482cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
483cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeyChannelCount, numChannels);
484cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeySampleRate, sampleRate);
485cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
486cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
487cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
488cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
489cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
490cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber// static
491cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberbool AVIExtractor::IsCorrectChunkType(
492cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) {
493cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t chunkBase = chunkType & 0xffff;
494cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
495cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    switch (kind) {
496cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case Track::VIDEO:
497cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
498cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (chunkBase != FOURCC(0, 0, 'd', 'c')
499cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    && chunkBase != FOURCC(0, 0, 'd', 'b')) {
500cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return false;
501cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
502cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
503cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
504cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
505cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case Track::AUDIO:
506cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
507cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (chunkBase != FOURCC(0, 0, 'w', 'b')) {
508cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return false;
509cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
510cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
511cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
512cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
513cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        default:
514cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
515cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
516cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
517cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (trackIndex < 0) {
518cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return true;
519cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
520cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
521cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t hi = chunkType >> 24;
522cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t lo = (chunkType >> 16) & 0xff;
523cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
524cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
525cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return false;
526cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
527cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
528cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (trackIndex != (10 * (hi - '0') + (lo - '0'))) {
529cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return false;
530cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
531cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
532cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return true;
533cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
534cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
535cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
536cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if ((size % 16) != 0) {
537cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
538cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
539cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
540cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> buffer = new ABuffer(size);
541cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
542cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
543cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < (ssize_t)size) {
544cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
545cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
546cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
547cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const uint8_t *data = buffer->data();
548cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
549cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (size > 0) {
550cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t chunkType = U32_AT(data);
551cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
552cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint8_t hi = chunkType >> 24;
553cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint8_t lo = (chunkType >> 16) & 0xff;
554cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
555cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
556cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
557cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
558cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
559cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t trackIndex = 10 * (hi - '0') + (lo - '0');
560cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
561cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (trackIndex >= mTracks.size()) {
562cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
563cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
564cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
565cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        Track *track = &mTracks.editItemAt(trackIndex);
566cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
567cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (!IsCorrectChunkType(-1, track->mKind, chunkType)) {
568cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
569cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
570cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
571cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (track->mKind == Track::OTHER) {
572cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            data += 16;
573cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            size -= 16;
574cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            continue;
575cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
576cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
577cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t flags = U32LE_AT(&data[4]);
578cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t offset = U32LE_AT(&data[8]);
579cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t chunkSize = U32LE_AT(&data[12]);
580cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
581cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (chunkSize > track->mMaxSampleSize) {
582cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            track->mMaxSampleSize = chunkSize;
583cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
584cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
585cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mSamples.push();
586cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
587cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        SampleInfo *info =
588cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            &track->mSamples.editItemAt(track->mSamples.size() - 1);
589cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
590cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        info->mOffset = offset;
591cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        info->mIsKey = (flags & 0x10) != 0;
592cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
593cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (info->mIsKey) {
594cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            static const size_t kMaxNumSyncSamplesToScan = 20;
595cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
596cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) {
597cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                if (chunkSize > track->mThumbnailSampleSize) {
598cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    track->mThumbnailSampleSize = chunkSize;
599cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
600cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    track->mThumbnailSampleIndex =
601cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                        track->mSamples.size() - 1;
602cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                }
603cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
604cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
605cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            ++track->mNumSyncSamples;
606cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
607cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
608cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        data += 16;
609cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size -= 16;
610cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
611cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
612cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!mTracks.isEmpty()) {
613cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        off64_t offset;
614cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t size;
615cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        bool isKey;
61663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        int64_t timeUs;
61763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        status_t err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
618cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
619cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (err != OK) {
620cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            mOffsetsAreAbsolute = !mOffsetsAreAbsolute;
62163749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
622cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
623cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (err != OK) {
624cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return err;
625cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
626cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
627cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
628cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        LOGV("Chunk offsets are %s",
629cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative");
630cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
631cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
632cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
633cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        Track *track = &mTracks.editItemAt(i);
634cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
63563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        int64_t durationUs;
63663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        CHECK_EQ((status_t)OK,
63763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber                 getSampleTime(i, track->mSamples.size() - 1, &durationUs));
638cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
639cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        LOGV("track %d duration = %.2f secs", i, durationUs / 1E6);
640cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
641cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt64(kKeyDuration, durationUs);
642cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize);
643cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
644cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        const char *tmp;
645cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp));
646cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
647cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        AString mime = tmp;
648cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
649cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (!strncasecmp("video/", mime.c_str(), 6)
650cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                && track->mThumbnailSampleIndex >= 0) {
65163749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            int64_t thumbnailTimeUs;
65263749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            CHECK_EQ((status_t)OK,
65363749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber                     getSampleTime(i, track->mThumbnailSampleIndex,
65463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber                                   &thumbnailTimeUs));
655cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
656cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
657cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
658cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
659cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                status_t err = addMPEG4CodecSpecificData(i);
660cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
661cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                if (err != OK) {
662cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    return err;
663cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                }
664cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
665cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
66663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber
66763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        if (track->mBytesPerSample != 0) {
66863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            // Assume all chunks are the same size for now.
66963749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber
67063749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            off64_t offset;
67163749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            size_t size;
67263749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            bool isKey;
67363749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            int64_t sampleTimeUs;
67463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            CHECK_EQ((status_t)OK,
67563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber                     getSampleInfo(
67663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber                         i, 0,
67763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber                         &offset, &size, &isKey, &sampleTimeUs));
67863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber
67963749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            track->mRate *= size / track->mBytesPerSample;
68063749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        }
681cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
682cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
683cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mFoundIndex = true;
684cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
685cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
686cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
687cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
688cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatic size_t GetSizeWidth(size_t x) {
689cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t n = 1;
690cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (x > 127) {
691cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ++n;
692cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        x >>= 7;
693cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
694cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return n;
695cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
696cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
697cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatic uint8_t *EncodeSize(uint8_t *dst, size_t x) {
698cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (x > 127) {
699cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *dst++ = (x & 0x7f) | 0x80;
700cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        x >>= 7;
701cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
702cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = x;
703cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return dst;
704cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
705cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
706cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) {
707cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
708cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
709cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
710cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
711cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> csd = new ABuffer(len3);
712cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t *dst = csd->data();
713cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x03;
714cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    dst = EncodeSize(dst, len2 + 3);
715cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x00;  // ES_ID
716cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x00;
717cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
718cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
719cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x04;
720cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    dst = EncodeSize(dst, len1 + 13);
721cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x01;  // Video ISO/IEC 14496-2 Simple Profile
722cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    for (size_t i = 0; i < 12; ++i) {
723cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *dst++ = 0x00;
724cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
725cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
726cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x05;
727cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    dst = EncodeSize(dst, config->size());
728cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    memcpy(dst, config->data(), config->size());
729cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    dst += config->size();
730cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
731cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    // hexdump(csd->data(), csd->size());
732cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
733cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return csd;
734cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
735cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
736cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) {
737cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    Track *track = &mTracks.editItemAt(trackIndex);
738cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
739cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    off64_t offset;
740cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t size;
741cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    bool isKey;
74263749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    int64_t timeUs;
74363749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    status_t err =
74463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        getSampleInfo(trackIndex, 0, &offset, &size, &isKey, &timeUs);
745cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
746cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (err != OK) {
747cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return err;
748cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
749cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
750cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> buffer = new ABuffer(size);
751cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
752cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
753cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < (ssize_t)size) {
754cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
755cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
756cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
757cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    // Extract everything up to the first VOP start code from the first
758cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    // frame's encoded data and use it to construct an ESDS with the
759cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    // codec specific data.
760cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
761cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t i = 0;
762cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    bool found = false;
763cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (i + 3 < buffer->size()) {
764cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) {
765cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            found = true;
766cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
767cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
768cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
769cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ++i;
770cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
771cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
772cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!found) {
773cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
774cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
775cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
776cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    buffer->setRange(0, i);
777cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
778cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer);
779cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size());
780cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
781cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
782cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
783cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
784cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::getSampleInfo(
785cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t trackIndex, size_t sampleIndex,
78663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        off64_t *offset, size_t *size, bool *isKey,
78763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        int64_t *sampleTimeUs) {
788cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (trackIndex >= mTracks.size()) {
789cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return -ERANGE;
790cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
791cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
792cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const Track &track = mTracks.itemAt(trackIndex);
793cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
794cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (sampleIndex >= track.mSamples.size()) {
795cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return -ERANGE;
796cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
797cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
798cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const SampleInfo &info = track.mSamples.itemAt(sampleIndex);
799cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
800cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!mOffsetsAreAbsolute) {
801cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *offset = info.mOffset + mMovieOffset + 8;
802cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    } else {
803cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *offset = info.mOffset;
804cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
805cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
806cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *size = 0;
807cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
808cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t tmp[8];
809cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(*offset, tmp, 8);
810cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
811cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < 8) {
812cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
813cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
814cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
815cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t chunkType = U32_AT(tmp);
816cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
817cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) {
818cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
819cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
820cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
821cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *offset += 8;
822cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *size = U32LE_AT(&tmp[4]);
823cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
824cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *isKey = info.mIsKey;
825cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
82663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale;
82763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber
828cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
829cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
830cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
83163749954aa828b3f73b4738659eaea5eaeeca874Andreas Huberstatus_t AVIExtractor::getSampleTime(
83263749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs) {
83363749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    off64_t offset;
83463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    size_t size;
83563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    bool isKey;
83663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    return getSampleInfo(
83763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            trackIndex, sampleIndex, &offset, &size, &isKey, sampleTimeUs);
83863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber}
83963749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber
840cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::getSampleIndexAtTime(
841cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t trackIndex,
842cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
843cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t *sampleIndex) const {
844cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (trackIndex >= mTracks.size()) {
845cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return -ERANGE;
846cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
847cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
848cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const Track &track = mTracks.itemAt(trackIndex);
849cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
850cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t closestSampleIndex =
851cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        timeUs / track.mRate * track.mScale / 1000000ll;
852cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
853cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t numSamples = track.mSamples.size();
854cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
855cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (closestSampleIndex < 0) {
856cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        closestSampleIndex = 0;
857cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    } else if (closestSampleIndex >= numSamples) {
858cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        closestSampleIndex = numSamples - 1;
859cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
860cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
861cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) {
862cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *sampleIndex = closestSampleIndex;
863cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
864cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return OK;
865cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
866cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
867cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t prevSyncSampleIndex = closestSampleIndex;
868cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (prevSyncSampleIndex >= 0) {
869cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        const SampleInfo &info =
870cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            track.mSamples.itemAt(prevSyncSampleIndex);
871cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
872cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (info.mIsKey) {
873cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
874cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
875cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
876cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        --prevSyncSampleIndex;
877cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
878cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
879cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t nextSyncSampleIndex = closestSampleIndex;
880cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (nextSyncSampleIndex < numSamples) {
881cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        const SampleInfo &info =
882cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            track.mSamples.itemAt(nextSyncSampleIndex);
883cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
884cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (info.mIsKey) {
885cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
886cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
887cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
888cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ++nextSyncSampleIndex;
889cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
890cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
891cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    switch (mode) {
892cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC:
893cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
894cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            *sampleIndex = prevSyncSampleIndex;
895cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
896cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR;
897cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
898cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
899cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case MediaSource::ReadOptions::SEEK_NEXT_SYNC:
900cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
901cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            *sampleIndex = nextSyncSampleIndex;
902cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
903cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR;
904cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
905cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
906cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC:
907cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
908cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) {
909cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return UNKNOWN_ERROR;
910cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
911cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
912cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (prevSyncSampleIndex < 0) {
913cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                *sampleIndex = nextSyncSampleIndex;
914cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return OK;
915cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
916cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
917cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (nextSyncSampleIndex >= numSamples) {
918cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                *sampleIndex = prevSyncSampleIndex;
919cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return OK;
920cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
921cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
922cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            size_t dist1 = closestSampleIndex - prevSyncSampleIndex;
923cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            size_t dist2 = nextSyncSampleIndex - closestSampleIndex;
924cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
925cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            *sampleIndex =
926cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex;
927cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
928cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return OK;
929cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
930cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
931cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        default:
932cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            TRESPASS();
933cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
934cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
935cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
936cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
937cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberbool SniffAVI(
938cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
939cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        sp<AMessage> *) {
940cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    char tmp[12];
941cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (source->readAt(0, tmp, 12) < 12) {
942cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return false;
943cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
944cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
945cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) {
946cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI);
947f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber
948f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber        // Just a tad over the mp3 extractor's confidence, since
949f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber        // these .avi files may contain .mp3 content that otherwise would
950f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber        // mistakenly lead to us identifying the entire file as a .mp3 file.
951f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber        *confidence = 0.21;
952cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
953cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return true;
954cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
955cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
956cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return false;
957cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
958cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
959cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}  // namespace android
960