AVIExtractor.cpp revision 3001e4721237af2754fc2ac57100dd4ea00c67cb
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
213001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber#include "include/avc_utils.h"
22cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include "include/AVIExtractor.h"
23cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
24cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <binder/ProcessState.h>
25cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/foundation/hexdump.h>
26cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/foundation/ABuffer.h>
27cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/foundation/ADebug.h>
28cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/DataSource.h>
29cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/MediaBuffer.h>
30cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/MediaBufferGroup.h>
31cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/MediaDefs.h>
32cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/MediaErrors.h>
33cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/MetaData.h>
34cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/Utils.h>
35cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
36cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubernamespace android {
37cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
38cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstruct AVIExtractor::AVISource : public MediaSource {
39cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    AVISource(const sp<AVIExtractor> &extractor, size_t trackIndex);
40cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
41cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    virtual status_t start(MetaData *params);
42cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    virtual status_t stop();
43cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
44cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    virtual sp<MetaData> getFormat();
45cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
46cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    virtual status_t read(
47cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            MediaBuffer **buffer, const ReadOptions *options);
48cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
49cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberprotected:
50cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    virtual ~AVISource();
51cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
52cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberprivate:
53cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<AVIExtractor> mExtractor;
54cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t mTrackIndex;
55cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const AVIExtractor::Track &mTrack;
56cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    MediaBufferGroup *mBufferGroup;
57cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t mSampleIndex;
58cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
59cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    DISALLOW_EVIL_CONSTRUCTORS(AVISource);
60cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber};
61cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
62cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber////////////////////////////////////////////////////////////////////////////////
63cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
64cabb7da7125a80c55233bd23959327424e9646ccAndreas HuberAVIExtractor::AVISource::AVISource(
65cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        const sp<AVIExtractor> &extractor, size_t trackIndex)
66cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    : mExtractor(extractor),
67cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber      mTrackIndex(trackIndex),
68cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber      mTrack(mExtractor->mTracks.itemAt(trackIndex)),
69cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber      mBufferGroup(NULL) {
70cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
71cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
72cabb7da7125a80c55233bd23959327424e9646ccAndreas HuberAVIExtractor::AVISource::~AVISource() {
73cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mBufferGroup) {
74cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        stop();
75cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
76cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
77cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
78cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::AVISource::start(MetaData *params) {
79cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    CHECK(!mBufferGroup);
80cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
81cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mBufferGroup = new MediaBufferGroup;
82cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
83cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
84cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
85cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mSampleIndex = 0;
86cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
87cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
88cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
89cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
90cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::AVISource::stop() {
91cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    CHECK(mBufferGroup);
92cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
93cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    delete mBufferGroup;
94cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mBufferGroup = NULL;
95cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
96cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
97cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
98cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
99cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MetaData> AVIExtractor::AVISource::getFormat() {
100cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return mTrack.mMeta;
101cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
102cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
103cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::AVISource::read(
104cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
105cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    CHECK(mBufferGroup);
106cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
107cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *buffer = NULL;
108cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
109cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    int64_t seekTimeUs;
110cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ReadOptions::SeekMode seekMode;
111cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
112cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        status_t err =
113cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            mExtractor->getSampleIndexAtTime(
114cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    mTrackIndex, seekTimeUs, seekMode, &mSampleIndex);
115cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
116cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (err != OK) {
117cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_END_OF_STREAM;
118cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
119cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
120cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
121cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    off64_t offset;
122cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t size;
123cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    bool isKey;
12463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    int64_t timeUs;
125cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    status_t err = mExtractor->getSampleInfo(
12663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs);
127cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
128cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ++mSampleIndex;
129cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
130cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (err != OK) {
131cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_END_OF_STREAM;
132cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
133cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
134cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    MediaBuffer *out;
135cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK);
136cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
137cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size);
138cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
139cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < (ssize_t)size) {
140cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
141cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
142cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
143cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    out->set_range(0, size);
144cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
145cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    out->meta_data()->setInt64(kKeyTime, timeUs);
146cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
147cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (isKey) {
148cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        out->meta_data()->setInt32(kKeyIsSyncFrame, 1);
149cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
150cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
151cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *buffer = out;
152cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
153cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
154cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
155cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
156cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber////////////////////////////////////////////////////////////////////////////////
157cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
158cabb7da7125a80c55233bd23959327424e9646ccAndreas HuberAVIExtractor::AVIExtractor(const sp<DataSource> &dataSource)
159cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    : mDataSource(dataSource) {
160cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mInitCheck = parseHeaders();
161cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
162cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mInitCheck != OK) {
163cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        mTracks.clear();
164cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
165cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
166cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
167cabb7da7125a80c55233bd23959327424e9646ccAndreas HuberAVIExtractor::~AVIExtractor() {
168cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
169cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
170cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersize_t AVIExtractor::countTracks() {
171cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return mTracks.size();
172cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
173cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
174cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MediaSource> AVIExtractor::getTrack(size_t index) {
175cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return index < mTracks.size() ? new AVISource(this, index) : NULL;
176cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
177cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
178cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MetaData> AVIExtractor::getTrackMetaData(
179cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t index, uint32_t flags) {
180cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL;
181cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
182cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
183cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MetaData> AVIExtractor::getMetaData() {
184cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<MetaData> meta = new MetaData;
185cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
186cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mInitCheck == OK) {
187cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_AVI);
188cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
189cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
190cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return meta;
191cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
192cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
193cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseHeaders() {
194cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mTracks.clear();
195cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mMovieOffset = 0;
196cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mFoundIndex = false;
197cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mOffsetsAreAbsolute = false;
198cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
199cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t res = parseChunk(0ll, -1ll);
200cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
201cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (res < 0) {
202cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return (status_t)res;
203cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
204cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
205cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mMovieOffset == 0ll || !mFoundIndex) {
206cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
207cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
208cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
209cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
210cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
211cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
212cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberssize_t AVIExtractor::parseChunk(off64_t offset, off64_t size, int depth) {
213cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (size >= 0 && size < 8) {
214cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
215cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
216cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
217cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t tmp[12];
218cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, tmp, 8);
219cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
220cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < 8) {
221cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
222cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
223cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
224cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t fourcc = U32_AT(tmp);
225cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t chunkSize = U32LE_AT(&tmp[4]);
226cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
227cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (size >= 0 && chunkSize + 8 > size) {
228cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
229cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
230cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
231cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    static const char kPrefix[] = "                              ";
232cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const char *prefix = &kPrefix[strlen(kPrefix) - 2 * depth];
233cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
234cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (fourcc == FOURCC('L', 'I', 'S', 'T')
235cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            || fourcc == FOURCC('R', 'I', 'F', 'F')) {
236cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        // It's a list of chunks
237cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
238cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (size >= 0 && size < 12) {
239cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
240cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
241cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
242cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        n = mDataSource->readAt(offset + 8, &tmp[8], 4);
243cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
244cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (n < 4) {
245cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
246cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
247cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
248cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t subFourcc = U32_AT(&tmp[8]);
249cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
250cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        LOGV("%s offset 0x%08llx LIST of '%c%c%c%c', size %d",
251cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             prefix,
252cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             offset,
253cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)(subFourcc >> 24),
254cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)((subFourcc >> 16) & 0xff),
255cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)((subFourcc >> 8) & 0xff),
256cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)(subFourcc & 0xff),
257cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             chunkSize - 4);
258cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
259cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (subFourcc == FOURCC('m', 'o', 'v', 'i')) {
260cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            // We're not going to parse this, but will take note of the
261cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            // offset.
262cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
263cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            mMovieOffset = offset;
264cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        } else {
265cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            off64_t subOffset = offset + 12;
266cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            off64_t subOffsetLimit = subOffset + chunkSize - 4;
267cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            while (subOffset < subOffsetLimit) {
268cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                ssize_t res =
269cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    parseChunk(subOffset, subOffsetLimit - subOffset, depth + 1);
270cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
271cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                if (res < 0) {
272cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    return res;
273cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                }
274cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
275cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                subOffset += res;
276cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
277cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
278cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    } else {
279cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        LOGV("%s offset 0x%08llx CHUNK '%c%c%c%c'",
280cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             prefix,
281cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             offset,
282cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)(fourcc >> 24),
283cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)((fourcc >> 16) & 0xff),
284cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)((fourcc >> 8) & 0xff),
285cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)(fourcc & 0xff));
286cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
287cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        status_t err = OK;
288cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
289cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        switch (fourcc) {
290cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            case FOURCC('s', 't', 'r', 'h'):
291cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            {
292cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                err = parseStreamHeader(offset + 8, chunkSize);
293cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                break;
294cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
295cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
296cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            case FOURCC('s', 't', 'r', 'f'):
297cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            {
298cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                err = parseStreamFormat(offset + 8, chunkSize);
299cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                break;
300cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
301cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
302cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            case FOURCC('i', 'd', 'x', '1'):
303cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            {
304cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                err = parseIndex(offset + 8, chunkSize);
305cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                break;
306cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
307cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
308cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            default:
309cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                break;
310cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
311cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
312cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (err != OK) {
313cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return err;
314cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
315cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
316cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
317cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (chunkSize & 1) {
318cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ++chunkSize;
319cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
320cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
321cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return chunkSize + 8;
322cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
323cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
324cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatic const char *GetMIMETypeForHandler(uint32_t handler) {
325cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    switch (handler) {
326cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        // Wow... shamelessly copied from
327cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        // http://wiki.multimedia.cx/index.php?title=ISO_MPEG-4
328cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
329cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('3', 'I', 'V', '2'):
330cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('3', 'i', 'v', '2'):
331cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('B', 'L', 'Z', '0'):
332cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'I', 'G', 'I'):
333cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'I', 'V', '1'):
334cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('d', 'i', 'v', '1'):
335cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'I', 'V', 'X'):
336cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('d', 'i', 'v', 'x'):
337cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'X', '5', '0'):
338cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('d', 'x', '5', '0'):
339cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'X', 'G', 'M'):
340cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('E', 'M', '4', 'A'):
341cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('E', 'P', 'H', 'V'):
342cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('F', 'M', 'P', '4'):
343cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('f', 'm', 'p', '4'):
344cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('F', 'V', 'F', 'W'):
345cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('H', 'D', 'X', '4'):
346cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('h', 'd', 'x', '4'):
347cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', '4', 'C', 'C'):
348cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', '4', 'S', '2'):
349cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('m', '4', 's', '2'):
350cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', 'P', '4', 'S'):
351cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('m', 'p', '4', 's'):
352cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', 'P', '4', 'V'):
353cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('m', 'p', '4', 'v'):
354cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', 'V', 'X', 'M'):
355cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('R', 'M', 'P', '4'):
356cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('S', 'E', 'D', 'G'):
357cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('S', 'M', 'P', '4'):
358cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('U', 'M', 'P', '4'):
359cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('W', 'V', '1', 'F'):
360cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('X', 'V', 'I', 'D'):
361cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('X', 'v', 'i', 'D'):
362cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('x', 'v', 'i', 'd'):
363cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('X', 'V', 'I', 'X'):
364cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
365cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
3663001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        // from http://wiki.multimedia.cx/index.php?title=H264
3673001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        case FOURCC('a', 'v', 'c', '1'):
3683001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        case FOURCC('d', 'a', 'v', 'c'):
3693001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        case FOURCC('x', '2', '6', '4'):
3703001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        case FOURCC('v', 's', 's', 'h'):
3713001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
3723001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
373cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        default:
374cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return NULL;
375cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
376cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
377cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
378cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) {
379cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (size != 56) {
380cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
381cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
382cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
383cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mTracks.size() > 99) {
384cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return -ERANGE;
385cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
386cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
387cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> buffer = new ABuffer(size);
388cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
389cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
390cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < (ssize_t)size) {
391cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
392cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
393cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
394cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const uint8_t *data = buffer->data();
395cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
396cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t type = U32_AT(data);
397cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t handler = U32_AT(&data[4]);
398cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t flags = U32LE_AT(&data[8]);
399cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
400cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<MetaData> meta = new MetaData;
401cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
402cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t rate = U32LE_AT(&data[20]);
403cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t scale = U32LE_AT(&data[24]);
404cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
40563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    uint32_t sampleSize = U32LE_AT(&data[44]);
40663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber
407cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const char *mime = NULL;
408cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    Track::Kind kind = Track::OTHER;
409cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
410cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (type == FOURCC('v', 'i', 'd', 's')) {
411cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        mime = GetMIMETypeForHandler(handler);
412cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
413cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (mime && strncasecmp(mime, "video/", 6)) {
414cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
415cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
416cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
4173001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        if (mime == NULL) {
4183001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            LOGW("Unsupported video format '%c%c%c%c'",
4193001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                 (char)(handler >> 24),
4203001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                 (char)((handler >> 16) & 0xff),
4213001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                 (char)((handler >> 8) & 0xff),
4223001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                 (char)(handler & 0xff));
4233001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        }
4243001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
425cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        kind = Track::VIDEO;
426cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    } else if (type == FOURCC('a', 'u', 'd', 's')) {
427cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (mime && strncasecmp(mime, "audio/", 6)) {
428cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
429cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
430cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
431cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        kind = Track::AUDIO;
432cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
433cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
434cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!mime) {
435cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        mime = "application/octet-stream";
436cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
437cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
438cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    meta->setCString(kKeyMIMEType, mime);
439cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
440cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mTracks.push();
441cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
442cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
443cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mMeta = meta;
444cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mRate = rate;
445cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mScale = scale;
44663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    track->mBytesPerSample = sampleSize;
447cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mKind = kind;
448cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mNumSyncSamples = 0;
449cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mThumbnailSampleSize = 0;
450cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mThumbnailSampleIndex = -1;
451cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mMaxSampleSize = 0;
452cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
453cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
454cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
455cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
456cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) {
457cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mTracks.isEmpty()) {
458cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
459cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
460cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
461cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
462cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
463cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (track->mKind == Track::OTHER) {
464cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        // We don't support this content, but that's not a parsing error.
465cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return OK;
466cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
467cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
468cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    bool isVideo = (track->mKind == Track::VIDEO);
469cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
470cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if ((isVideo && size < 40) || (!isVideo && size < 18)) {
471cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        // Expected a BITMAPINFO or WAVEFORMATEX structure, respectively.
472cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
473cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
474cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
475cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> buffer = new ABuffer(size);
476cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
477cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
478cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < (ssize_t)size) {
479cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
480cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
481cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
482cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const uint8_t *data = buffer->data();
483cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
484cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (isVideo) {
485cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t width = U32LE_AT(&data[4]);
486cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t height = U32LE_AT(&data[8]);
487cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
488cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeyWidth, width);
489cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeyHeight, height);
490cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    } else {
491cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t format = U16LE_AT(data);
4923001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
493cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (format == 0x55) {
494cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
4953001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        } else {
4963001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            LOGW("Unsupported audio format = 0x%04x", format);
497cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
498cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
499cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t numChannels = U16LE_AT(&data[2]);
500cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t sampleRate = U32LE_AT(&data[4]);
501cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
502cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeyChannelCount, numChannels);
503cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeySampleRate, sampleRate);
504cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
505cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
506cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
507cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
508cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
509cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber// static
510cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberbool AVIExtractor::IsCorrectChunkType(
511cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) {
512cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t chunkBase = chunkType & 0xffff;
513cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
514cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    switch (kind) {
515cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case Track::VIDEO:
516cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
517cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (chunkBase != FOURCC(0, 0, 'd', 'c')
518cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    && chunkBase != FOURCC(0, 0, 'd', 'b')) {
519cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return false;
520cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
521cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
522cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
523cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
524cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case Track::AUDIO:
525cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
526cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (chunkBase != FOURCC(0, 0, 'w', 'b')) {
527cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return false;
528cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
529cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
530cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
531cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
532cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        default:
533cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
534cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
535cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
536cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (trackIndex < 0) {
537cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return true;
538cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
539cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
540cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t hi = chunkType >> 24;
541cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t lo = (chunkType >> 16) & 0xff;
542cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
543cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
544cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return false;
545cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
546cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
547cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (trackIndex != (10 * (hi - '0') + (lo - '0'))) {
548cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return false;
549cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
550cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
551cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return true;
552cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
553cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
554cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
555cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if ((size % 16) != 0) {
556cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
557cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
558cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
559cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> buffer = new ABuffer(size);
560cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
561cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
562cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < (ssize_t)size) {
563cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
564cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
565cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
566cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const uint8_t *data = buffer->data();
567cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
568cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (size > 0) {
569cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t chunkType = U32_AT(data);
570cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
571cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint8_t hi = chunkType >> 24;
572cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint8_t lo = (chunkType >> 16) & 0xff;
573cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
574cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
575cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
576cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
577cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
578cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t trackIndex = 10 * (hi - '0') + (lo - '0');
579cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
580cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (trackIndex >= mTracks.size()) {
581cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
582cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
583cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
584cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        Track *track = &mTracks.editItemAt(trackIndex);
585cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
586cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (!IsCorrectChunkType(-1, track->mKind, chunkType)) {
587cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
588cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
589cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
590cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (track->mKind == Track::OTHER) {
591cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            data += 16;
592cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            size -= 16;
593cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            continue;
594cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
595cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
596cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t flags = U32LE_AT(&data[4]);
597cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t offset = U32LE_AT(&data[8]);
598cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t chunkSize = U32LE_AT(&data[12]);
599cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
600cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (chunkSize > track->mMaxSampleSize) {
601cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            track->mMaxSampleSize = chunkSize;
602cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
603cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
604cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mSamples.push();
605cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
606cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        SampleInfo *info =
607cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            &track->mSamples.editItemAt(track->mSamples.size() - 1);
608cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
609cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        info->mOffset = offset;
610cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        info->mIsKey = (flags & 0x10) != 0;
611cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
612cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (info->mIsKey) {
613cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            static const size_t kMaxNumSyncSamplesToScan = 20;
614cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
615cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) {
616cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                if (chunkSize > track->mThumbnailSampleSize) {
617cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    track->mThumbnailSampleSize = chunkSize;
618cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
619cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    track->mThumbnailSampleIndex =
620cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                        track->mSamples.size() - 1;
621cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                }
622cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
623cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
624cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            ++track->mNumSyncSamples;
625cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
626cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
627cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        data += 16;
628cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size -= 16;
629cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
630cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
631cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!mTracks.isEmpty()) {
632cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        off64_t offset;
633cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t size;
634cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        bool isKey;
63563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        int64_t timeUs;
63663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        status_t err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
637cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
638cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (err != OK) {
639cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            mOffsetsAreAbsolute = !mOffsetsAreAbsolute;
64063749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
641cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
642cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (err != OK) {
643cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return err;
644cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
645cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
646cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
647cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        LOGV("Chunk offsets are %s",
648cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative");
649cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
650cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
651cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
652cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        Track *track = &mTracks.editItemAt(i);
653cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
65463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        int64_t durationUs;
65563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        CHECK_EQ((status_t)OK,
65663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber                 getSampleTime(i, track->mSamples.size() - 1, &durationUs));
657cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
658cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        LOGV("track %d duration = %.2f secs", i, durationUs / 1E6);
659cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
660cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt64(kKeyDuration, durationUs);
661cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize);
662cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
663cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        const char *tmp;
664cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp));
665cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
666cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        AString mime = tmp;
667cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
6683001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        if (!strncasecmp("video/", mime.c_str(), 6)) {
6693001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            if (track->mThumbnailSampleIndex >= 0) {
6703001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                int64_t thumbnailTimeUs;
6713001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                CHECK_EQ((status_t)OK,
6723001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                         getSampleTime(i, track->mThumbnailSampleIndex,
6733001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                                       &thumbnailTimeUs));
674cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
6753001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
6763001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            }
6773001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
6783001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            status_t err = OK;
679cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
680cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
6813001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                err = addMPEG4CodecSpecificData(i);
6823001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
6833001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                err = addH264CodecSpecificData(i);
6843001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            }
685cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
6863001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            if (err != OK) {
6873001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                return err;
688cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
689cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
69063749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber
69163749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        if (track->mBytesPerSample != 0) {
69263749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            // Assume all chunks are the same size for now.
69363749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber
69463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            off64_t offset;
69563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            size_t size;
69663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            bool isKey;
69763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            int64_t sampleTimeUs;
69863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            CHECK_EQ((status_t)OK,
69963749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber                     getSampleInfo(
70063749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber                         i, 0,
70163749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber                         &offset, &size, &isKey, &sampleTimeUs));
70263749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber
70363749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            track->mRate *= size / track->mBytesPerSample;
70463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        }
705cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
706cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
707cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mFoundIndex = true;
708cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
709cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
710cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
711cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
712cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatic size_t GetSizeWidth(size_t x) {
713cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t n = 1;
714cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (x > 127) {
715cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ++n;
716cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        x >>= 7;
717cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
718cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return n;
719cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
720cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
721cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatic uint8_t *EncodeSize(uint8_t *dst, size_t x) {
722cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (x > 127) {
723cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *dst++ = (x & 0x7f) | 0x80;
724cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        x >>= 7;
725cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
726cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = x;
727cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return dst;
728cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
729cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
730cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) {
731cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
732cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
733cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
734cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
735cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> csd = new ABuffer(len3);
736cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t *dst = csd->data();
737cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x03;
738cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    dst = EncodeSize(dst, len2 + 3);
739cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x00;  // ES_ID
740cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x00;
741cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
742cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
743cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x04;
744cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    dst = EncodeSize(dst, len1 + 13);
745cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x01;  // Video ISO/IEC 14496-2 Simple Profile
746cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    for (size_t i = 0; i < 12; ++i) {
747cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *dst++ = 0x00;
748cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
749cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
750cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x05;
751cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    dst = EncodeSize(dst, config->size());
752cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    memcpy(dst, config->data(), config->size());
753cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    dst += config->size();
754cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
755cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    // hexdump(csd->data(), csd->size());
756cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
757cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return csd;
758cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
759cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
760cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) {
761cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    Track *track = &mTracks.editItemAt(trackIndex);
762cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
763cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    off64_t offset;
764cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t size;
765cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    bool isKey;
76663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    int64_t timeUs;
76763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    status_t err =
76863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        getSampleInfo(trackIndex, 0, &offset, &size, &isKey, &timeUs);
769cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
770cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (err != OK) {
771cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return err;
772cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
773cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
774cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> buffer = new ABuffer(size);
775cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
776cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
777cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < (ssize_t)size) {
778cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
779cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
780cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
781cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    // Extract everything up to the first VOP start code from the first
782cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    // frame's encoded data and use it to construct an ESDS with the
783cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    // codec specific data.
784cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
785cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t i = 0;
786cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    bool found = false;
787cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (i + 3 < buffer->size()) {
788cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) {
789cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            found = true;
790cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
791cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
792cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
793cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ++i;
794cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
795cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
796cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!found) {
797cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
798cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
799cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
800cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    buffer->setRange(0, i);
801cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
802cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer);
803cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size());
804cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
805cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
806cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
807cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
8083001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huberstatus_t AVIExtractor::addH264CodecSpecificData(size_t trackIndex) {
8093001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    Track *track = &mTracks.editItemAt(trackIndex);
8103001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
8113001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    off64_t offset;
8123001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    size_t size;
8133001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    bool isKey;
8143001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    int64_t timeUs;
8153001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
8163001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    // Extract codec specific data from the first non-empty sample.
8173001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
8183001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    size_t sampleIndex = 0;
8193001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    for (;;) {
8203001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        status_t err =
8213001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            getSampleInfo(
8223001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                    trackIndex, sampleIndex, &offset, &size, &isKey, &timeUs);
8233001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
8243001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        if (err != OK) {
8253001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            return err;
8263001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        }
8273001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
8283001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        if (size > 0) {
8293001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            break;
8303001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        }
8313001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
8323001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        ++sampleIndex;
8333001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    }
8343001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
8353001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    sp<ABuffer> buffer = new ABuffer(size);
8363001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
8373001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
8383001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    if (n < (ssize_t)size) {
8393001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
8403001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    }
8413001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
8423001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    sp<MetaData> meta = MakeAVCCodecSpecificData(buffer);
8433001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
8443001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    if (meta == NULL) {
8453001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        LOGE("Unable to extract AVC codec specific data");
8463001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        return ERROR_MALFORMED;
8473001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    }
8483001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
8493001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    int32_t width, height;
8503001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    CHECK(meta->findInt32(kKeyWidth, &width));
8513001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    CHECK(meta->findInt32(kKeyHeight, &height));
8523001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
8533001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    uint32_t type;
8543001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    const void *csd;
8553001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    size_t csdSize;
8563001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize));
8573001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
8583001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    track->mMeta->setInt32(kKeyWidth, width);
8593001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    track->mMeta->setInt32(kKeyHeight, width);
8603001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    track->mMeta->setData(kKeyAVCC, type, csd, csdSize);
8613001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
8623001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    return OK;
8633001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber}
8643001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
865cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::getSampleInfo(
866cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t trackIndex, size_t sampleIndex,
86763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        off64_t *offset, size_t *size, bool *isKey,
86863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        int64_t *sampleTimeUs) {
869cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (trackIndex >= mTracks.size()) {
870cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return -ERANGE;
871cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
872cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
873cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const Track &track = mTracks.itemAt(trackIndex);
874cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
875cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (sampleIndex >= track.mSamples.size()) {
876cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return -ERANGE;
877cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
878cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
879cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const SampleInfo &info = track.mSamples.itemAt(sampleIndex);
880cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
881cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!mOffsetsAreAbsolute) {
882cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *offset = info.mOffset + mMovieOffset + 8;
883cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    } else {
884cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *offset = info.mOffset;
885cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
886cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
887cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *size = 0;
888cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
889cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t tmp[8];
890cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(*offset, tmp, 8);
891cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
892cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < 8) {
893cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
894cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
895cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
896cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t chunkType = U32_AT(tmp);
897cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
898cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) {
899cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
900cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
901cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
902cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *offset += 8;
903cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *size = U32LE_AT(&tmp[4]);
904cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
905cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *isKey = info.mIsKey;
906cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
90763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale;
90863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber
909cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
910cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
911cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
91263749954aa828b3f73b4738659eaea5eaeeca874Andreas Huberstatus_t AVIExtractor::getSampleTime(
91363749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs) {
91463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    off64_t offset;
91563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    size_t size;
91663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    bool isKey;
91763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    return getSampleInfo(
91863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            trackIndex, sampleIndex, &offset, &size, &isKey, sampleTimeUs);
91963749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber}
92063749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber
921cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::getSampleIndexAtTime(
922cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t trackIndex,
923cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
924cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t *sampleIndex) const {
925cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (trackIndex >= mTracks.size()) {
926cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return -ERANGE;
927cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
928cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
929cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const Track &track = mTracks.itemAt(trackIndex);
930cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
931cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t closestSampleIndex =
932cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        timeUs / track.mRate * track.mScale / 1000000ll;
933cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
934cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t numSamples = track.mSamples.size();
935cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
936cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (closestSampleIndex < 0) {
937cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        closestSampleIndex = 0;
938cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    } else if (closestSampleIndex >= numSamples) {
939cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        closestSampleIndex = numSamples - 1;
940cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
941cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
942cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) {
943cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *sampleIndex = closestSampleIndex;
944cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
945cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return OK;
946cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
947cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
948cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t prevSyncSampleIndex = closestSampleIndex;
949cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (prevSyncSampleIndex >= 0) {
950cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        const SampleInfo &info =
951cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            track.mSamples.itemAt(prevSyncSampleIndex);
952cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
953cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (info.mIsKey) {
954cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
955cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
956cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
957cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        --prevSyncSampleIndex;
958cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
959cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
960cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t nextSyncSampleIndex = closestSampleIndex;
961cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (nextSyncSampleIndex < numSamples) {
962cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        const SampleInfo &info =
963cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            track.mSamples.itemAt(nextSyncSampleIndex);
964cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
965cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (info.mIsKey) {
966cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
967cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
968cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
969cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ++nextSyncSampleIndex;
970cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
971cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
972cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    switch (mode) {
973cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC:
974cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
975cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            *sampleIndex = prevSyncSampleIndex;
976cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
977cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR;
978cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
979cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
980cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case MediaSource::ReadOptions::SEEK_NEXT_SYNC:
981cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
982cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            *sampleIndex = nextSyncSampleIndex;
983cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
984cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR;
985cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
986cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
987cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC:
988cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
989cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) {
990cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return UNKNOWN_ERROR;
991cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
992cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
993cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (prevSyncSampleIndex < 0) {
994cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                *sampleIndex = nextSyncSampleIndex;
995cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return OK;
996cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
997cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
998cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (nextSyncSampleIndex >= numSamples) {
999cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                *sampleIndex = prevSyncSampleIndex;
1000cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return OK;
1001cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
1002cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1003cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            size_t dist1 = closestSampleIndex - prevSyncSampleIndex;
1004cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            size_t dist2 = nextSyncSampleIndex - closestSampleIndex;
1005cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1006cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            *sampleIndex =
1007cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex;
1008cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1009cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return OK;
1010cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
1011cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1012cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        default:
1013cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            TRESPASS();
1014cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
1015cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1016cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
1017cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1018cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberbool SniffAVI(
1019cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
1020cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        sp<AMessage> *) {
1021cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    char tmp[12];
1022cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (source->readAt(0, tmp, 12) < 12) {
1023cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return false;
1024cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1025cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1026cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) {
1027cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI);
1028f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber
1029f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber        // Just a tad over the mp3 extractor's confidence, since
1030f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber        // these .avi files may contain .mp3 content that otherwise would
1031f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber        // mistakenly lead to us identifying the entire file as a .mp3 file.
1032f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber        *confidence = 0.21;
1033cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1034cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return true;
1035cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1036cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1037cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return false;
1038cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
1039cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1040cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}  // namespace android
1041