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
59bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    sp<MP3Splitter> mSplitter;
60bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
61cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    DISALLOW_EVIL_CONSTRUCTORS(AVISource);
62cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber};
63cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
64cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber////////////////////////////////////////////////////////////////////////////////
65cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
66bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huberstruct AVIExtractor::MP3Splitter : public RefBase {
67bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    MP3Splitter();
68bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
69bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    void clear();
70bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    void append(MediaBuffer *buffer);
71bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    status_t read(MediaBuffer **buffer);
72bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
73bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huberprotected:
74bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    virtual ~MP3Splitter();
75bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
76bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huberprivate:
77bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    bool mFindSync;
78bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    int64_t mBaseTimeUs;
79bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    int64_t mNumSamplesRead;
80bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    sp<ABuffer> mBuffer;
81bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
82bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    bool resync();
83bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
84bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(MP3Splitter);
85bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber};
86bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
87bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber////////////////////////////////////////////////////////////////////////////////
88bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
89cabb7da7125a80c55233bd23959327424e9646ccAndreas HuberAVIExtractor::AVISource::AVISource(
90cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        const sp<AVIExtractor> &extractor, size_t trackIndex)
91cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    : mExtractor(extractor),
92cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber      mTrackIndex(trackIndex),
93cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber      mTrack(mExtractor->mTracks.itemAt(trackIndex)),
94cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber      mBufferGroup(NULL) {
95cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
96cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
97cabb7da7125a80c55233bd23959327424e9646ccAndreas HuberAVIExtractor::AVISource::~AVISource() {
98cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mBufferGroup) {
99cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        stop();
100cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
101cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
102cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
103cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::AVISource::start(MetaData *params) {
104cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    CHECK(!mBufferGroup);
105cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
106cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mBufferGroup = new MediaBufferGroup;
107cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
108cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
109cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
110cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mSampleIndex = 0;
111cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
112bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    const char *mime;
113bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    CHECK(mTrack.mMeta->findCString(kKeyMIMEType, &mime));
114bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
115bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
116bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        mSplitter = new MP3Splitter;
117bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    } else {
118bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        mSplitter.clear();
119bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    }
120bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
121cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
122cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
123cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
124cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::AVISource::stop() {
125cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    CHECK(mBufferGroup);
126cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
127cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    delete mBufferGroup;
128cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mBufferGroup = NULL;
129cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
130bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    mSplitter.clear();
131bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
132cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
133cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
134cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
135cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MetaData> AVIExtractor::AVISource::getFormat() {
136cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return mTrack.mMeta;
137cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
138cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
139cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::AVISource::read(
140cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
141cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    CHECK(mBufferGroup);
142cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
143cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *buffer = NULL;
144cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
145cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    int64_t seekTimeUs;
146cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ReadOptions::SeekMode seekMode;
147cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
148cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        status_t err =
149cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            mExtractor->getSampleIndexAtTime(
150cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    mTrackIndex, seekTimeUs, seekMode, &mSampleIndex);
151cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
152cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (err != OK) {
153cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_END_OF_STREAM;
154cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
155bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
156bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        if (mSplitter != NULL) {
157bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            mSplitter->clear();
158bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        }
159cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
160cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
161bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    for (;;) {
162bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        if (mSplitter != NULL) {
163bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            status_t err = mSplitter->read(buffer);
164cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
165bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            if (err == OK) {
166bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                break;
167bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            } else if (err != -EAGAIN) {
168bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                return err;
169bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            }
170bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        }
171cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
172bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        off64_t offset;
173bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        size_t size;
174bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        bool isKey;
175bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        int64_t timeUs;
176bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        status_t err = mExtractor->getSampleInfo(
177bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs);
178bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
179bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        ++mSampleIndex;
180bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
181bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        if (err != OK) {
182bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            return ERROR_END_OF_STREAM;
183bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        }
184bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
185bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        MediaBuffer *out;
186bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK);
187bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
188bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size);
189bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
190bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        if (n < (ssize_t)size) {
191bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
192bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        }
193bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
194bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        out->set_range(0, size);
195bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
196bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        out->meta_data()->setInt64(kKeyTime, timeUs);
197bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
198bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        if (isKey) {
199bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            out->meta_data()->setInt32(kKeyIsSyncFrame, 1);
200bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        }
201bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
202bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        if (mSplitter == NULL) {
203bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            *buffer = out;
204bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            break;
205bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        }
206bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
207bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        mSplitter->append(out);
208bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        out->release();
209bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        out = NULL;
210cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
211cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
212bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    return OK;
213bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber}
214cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
215bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber////////////////////////////////////////////////////////////////////////////////
216cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
217bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas HuberAVIExtractor::MP3Splitter::MP3Splitter()
218bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    : mFindSync(true),
219bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber      mBaseTimeUs(-1ll),
220bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber      mNumSamplesRead(0) {
221bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber}
222bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
223bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas HuberAVIExtractor::MP3Splitter::~MP3Splitter() {
224bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber}
225bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
226bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Hubervoid AVIExtractor::MP3Splitter::clear() {
227bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    mFindSync = true;
228bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    mBaseTimeUs = -1ll;
229bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    mNumSamplesRead = 0;
230bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
231bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    if (mBuffer != NULL) {
232bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        mBuffer->setRange(0, 0);
233cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
234bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber}
235cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
236bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Hubervoid AVIExtractor::MP3Splitter::append(MediaBuffer *buffer) {
237bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    size_t prevCapacity = (mBuffer != NULL) ? mBuffer->capacity() : 0;
238cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
239bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    if (mBaseTimeUs < 0) {
240bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        CHECK(mBuffer == NULL || mBuffer->size() == 0);
241bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        CHECK(buffer->meta_data()->findInt64(kKeyTime, &mBaseTimeUs));
242bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        mNumSamplesRead = 0;
243bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    }
244cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
245bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    if (mBuffer != NULL && mBuffer->offset() > 0) {
246bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        memmove(mBuffer->base(), mBuffer->data(), mBuffer->size());
247bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        mBuffer->setRange(0, mBuffer->size());
248cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
249cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
250bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    if (mBuffer == NULL
251bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            || mBuffer->size() + buffer->range_length() > prevCapacity) {
252bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        size_t newCapacity =
253bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            (prevCapacity + buffer->range_length() + 1023) & ~1023;
254bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
255bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        sp<ABuffer> newBuffer = new ABuffer(newCapacity);
256bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        if (mBuffer != NULL) {
257bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
258bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            newBuffer->setRange(0, mBuffer->size());
259bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        } else {
260bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            newBuffer->setRange(0, 0);
261bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        }
262bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        mBuffer = newBuffer;
263bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    }
264bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
265bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    memcpy(mBuffer->data() + mBuffer->size(),
266bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber           (const uint8_t *)buffer->data() + buffer->range_offset(),
267bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber           buffer->range_length());
268bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
269bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    mBuffer->setRange(0, mBuffer->size() + buffer->range_length());
270bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber}
271bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
272bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huberbool AVIExtractor::MP3Splitter::resync() {
273bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    if (mBuffer == NULL) {
274bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        return false;
275bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    }
276bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
277bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    bool foundSync = false;
278bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    for (size_t offset = 0; offset + 3 < mBuffer->size(); ++offset) {
279bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        uint32_t firstHeader = U32_AT(mBuffer->data() + offset);
280bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
281bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        size_t frameSize;
282bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        if (!GetMPEGAudioFrameSize(firstHeader, &frameSize)) {
283bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            continue;
284bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        }
285bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
286bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        size_t subsequentOffset = offset + frameSize;
287bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        size_t i = 3;
288bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        while (i > 0) {
289bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            if (subsequentOffset + 3 >= mBuffer->size()) {
290bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                break;
291bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            }
292bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
293bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            static const uint32_t kMask = 0xfffe0c00;
294bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
295bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            uint32_t header = U32_AT(mBuffer->data() + subsequentOffset);
296bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            if ((header & kMask) != (firstHeader & kMask)) {
297bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                break;
298bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            }
299bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
300bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            if (!GetMPEGAudioFrameSize(header, &frameSize)) {
301bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                break;
302bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            }
303bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
304bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            subsequentOffset += frameSize;
305bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            --i;
306bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        }
307bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
308bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        if (i == 0) {
309bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            foundSync = true;
310bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            memmove(mBuffer->data(),
311bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                    mBuffer->data() + offset,
312bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                    mBuffer->size() - offset);
313bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
314bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            mBuffer->setRange(0, mBuffer->size() - offset);
315bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            break;
316bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        }
317bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    }
318bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
319bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    return foundSync;
320bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber}
321bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
322bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huberstatus_t AVIExtractor::MP3Splitter::read(MediaBuffer **out) {
323bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    *out = NULL;
324bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
325bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    if (mFindSync) {
326bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        if (!resync()) {
327bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            return -EAGAIN;
328bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        }
329bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
330bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        mFindSync = false;
331bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    }
332bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
333bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    if (mBuffer->size() < 4) {
334bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        return -EAGAIN;
335bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    }
336bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
337bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    uint32_t header = U32_AT(mBuffer->data());
338bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    size_t frameSize;
339bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    int sampleRate;
340bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    int numSamples;
341bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    if (!GetMPEGAudioFrameSize(
342bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                header, &frameSize, &sampleRate, NULL, NULL, &numSamples)) {
343bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        return ERROR_MALFORMED;
344bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    }
345bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
346bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    if (mBuffer->size() < frameSize) {
347bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        return -EAGAIN;
348bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    }
349bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
350bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    MediaBuffer *mbuf = new MediaBuffer(frameSize);
351bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    memcpy(mbuf->data(), mBuffer->data(), frameSize);
352bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
353bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    int64_t timeUs = mBaseTimeUs + (mNumSamplesRead * 1000000ll) / sampleRate;
354bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    mNumSamplesRead += numSamples;
355bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
356bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    mbuf->meta_data()->setInt64(kKeyTime, timeUs);
357bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
358bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    mBuffer->setRange(
359bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            mBuffer->offset() + frameSize, mBuffer->size() - frameSize);
360bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
361bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    *out = mbuf;
362cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
363cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
364cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
365cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
366cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber////////////////////////////////////////////////////////////////////////////////
367cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
368cabb7da7125a80c55233bd23959327424e9646ccAndreas HuberAVIExtractor::AVIExtractor(const sp<DataSource> &dataSource)
369cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    : mDataSource(dataSource) {
370cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mInitCheck = parseHeaders();
371cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
372cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mInitCheck != OK) {
373cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        mTracks.clear();
374cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
375cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
376cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
377cabb7da7125a80c55233bd23959327424e9646ccAndreas HuberAVIExtractor::~AVIExtractor() {
378cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
379cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
380cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersize_t AVIExtractor::countTracks() {
381cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return mTracks.size();
382cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
383cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
384cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MediaSource> AVIExtractor::getTrack(size_t index) {
385cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return index < mTracks.size() ? new AVISource(this, index) : NULL;
386cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
387cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
388cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MetaData> AVIExtractor::getTrackMetaData(
389cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t index, uint32_t flags) {
390cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL;
391cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
392cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
393cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MetaData> AVIExtractor::getMetaData() {
394cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<MetaData> meta = new MetaData;
395cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
396cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mInitCheck == OK) {
397cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_AVI);
398cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
399cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
400cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return meta;
401cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
402cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
403cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseHeaders() {
404cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mTracks.clear();
405cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mMovieOffset = 0;
406cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mFoundIndex = false;
407cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mOffsetsAreAbsolute = false;
408cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
409cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t res = parseChunk(0ll, -1ll);
410cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
411cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (res < 0) {
412cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return (status_t)res;
413cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
414cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
415cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mMovieOffset == 0ll || !mFoundIndex) {
416cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
417cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
418cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
419cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
420cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
421cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
422cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberssize_t AVIExtractor::parseChunk(off64_t offset, off64_t size, int depth) {
423cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (size >= 0 && size < 8) {
424cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
425cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
426cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
427cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t tmp[12];
428cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, tmp, 8);
429cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
430cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < 8) {
431cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
432cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
433cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
434cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t fourcc = U32_AT(tmp);
435cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t chunkSize = U32LE_AT(&tmp[4]);
436cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
437cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (size >= 0 && chunkSize + 8 > size) {
438cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
439cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
440cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
441cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    static const char kPrefix[] = "                              ";
442cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const char *prefix = &kPrefix[strlen(kPrefix) - 2 * depth];
443cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
444cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (fourcc == FOURCC('L', 'I', 'S', 'T')
445cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            || fourcc == FOURCC('R', 'I', 'F', 'F')) {
446cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        // It's a list of chunks
447cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
448cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (size >= 0 && size < 12) {
449cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
450cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
451cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
452cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        n = mDataSource->readAt(offset + 8, &tmp[8], 4);
453cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
454cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (n < 4) {
455cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
456cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
457cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
458cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t subFourcc = U32_AT(&tmp[8]);
459cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
460cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        LOGV("%s offset 0x%08llx LIST of '%c%c%c%c', size %d",
461cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             prefix,
462cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             offset,
463cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)(subFourcc >> 24),
464cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)((subFourcc >> 16) & 0xff),
465cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)((subFourcc >> 8) & 0xff),
466cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)(subFourcc & 0xff),
467cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             chunkSize - 4);
468cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
469cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (subFourcc == FOURCC('m', 'o', 'v', 'i')) {
470cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            // We're not going to parse this, but will take note of the
471cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            // offset.
472cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
473cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            mMovieOffset = offset;
474cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        } else {
475cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            off64_t subOffset = offset + 12;
476cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            off64_t subOffsetLimit = subOffset + chunkSize - 4;
477cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            while (subOffset < subOffsetLimit) {
478cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                ssize_t res =
479cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    parseChunk(subOffset, subOffsetLimit - subOffset, depth + 1);
480cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
481cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                if (res < 0) {
482cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    return res;
483cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                }
484cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
485cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                subOffset += res;
486cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
487cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
488cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    } else {
489cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        LOGV("%s offset 0x%08llx CHUNK '%c%c%c%c'",
490cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             prefix,
491cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             offset,
492cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)(fourcc >> 24),
493cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)((fourcc >> 16) & 0xff),
494cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)((fourcc >> 8) & 0xff),
495cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             (char)(fourcc & 0xff));
496cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
497cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        status_t err = OK;
498cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
499cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        switch (fourcc) {
500cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            case FOURCC('s', 't', 'r', 'h'):
501cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            {
502cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                err = parseStreamHeader(offset + 8, chunkSize);
503cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                break;
504cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
505cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
506cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            case FOURCC('s', 't', 'r', 'f'):
507cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            {
508cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                err = parseStreamFormat(offset + 8, chunkSize);
509cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                break;
510cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
511cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
512cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            case FOURCC('i', 'd', 'x', '1'):
513cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            {
514cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                err = parseIndex(offset + 8, chunkSize);
515cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                break;
516cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
517cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
518cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            default:
519cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                break;
520cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
521cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
522cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (err != OK) {
523cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return err;
524cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
525cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
526cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
527cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (chunkSize & 1) {
528cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ++chunkSize;
529cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
530cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
531cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return chunkSize + 8;
532cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
533cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
534cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatic const char *GetMIMETypeForHandler(uint32_t handler) {
535cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    switch (handler) {
536cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        // Wow... shamelessly copied from
537cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        // http://wiki.multimedia.cx/index.php?title=ISO_MPEG-4
538cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
539cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('3', 'I', 'V', '2'):
540cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('3', 'i', 'v', '2'):
541cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('B', 'L', 'Z', '0'):
542cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'I', 'G', 'I'):
543cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'I', 'V', '1'):
544cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('d', 'i', 'v', '1'):
545cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'I', 'V', 'X'):
546cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('d', 'i', 'v', 'x'):
547cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'X', '5', '0'):
548cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('d', 'x', '5', '0'):
549cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('D', 'X', 'G', 'M'):
550cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('E', 'M', '4', 'A'):
551cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('E', 'P', 'H', 'V'):
552cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('F', 'M', 'P', '4'):
553cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('f', 'm', 'p', '4'):
554cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('F', 'V', 'F', 'W'):
555cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('H', 'D', 'X', '4'):
556cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('h', 'd', 'x', '4'):
557cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', '4', 'C', 'C'):
558cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', '4', 'S', '2'):
559cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('m', '4', 's', '2'):
560cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', 'P', '4', 'S'):
561cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('m', 'p', '4', 's'):
562cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', 'P', '4', 'V'):
563cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('m', 'p', '4', 'v'):
564cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('M', 'V', 'X', 'M'):
565cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('R', 'M', 'P', '4'):
566cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('S', 'E', 'D', 'G'):
567cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('S', 'M', 'P', '4'):
568cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('U', 'M', 'P', '4'):
569cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('W', 'V', '1', 'F'):
570cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('X', 'V', 'I', 'D'):
571cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('X', 'v', 'i', 'D'):
572cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('x', 'v', 'i', 'd'):
573cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case FOURCC('X', 'V', 'I', 'X'):
574cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
575cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
5763001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        // from http://wiki.multimedia.cx/index.php?title=H264
5773001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        case FOURCC('a', 'v', 'c', '1'):
5783001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        case FOURCC('d', 'a', 'v', 'c'):
5793001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        case FOURCC('x', '2', '6', '4'):
5803001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        case FOURCC('v', 's', 's', 'h'):
5813001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
5823001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
583cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        default:
584cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return NULL;
585cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
586cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
587cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
588cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) {
589cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (size != 56) {
590cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
591cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
592cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
593cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mTracks.size() > 99) {
594cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return -ERANGE;
595cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
596cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
597cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> buffer = new ABuffer(size);
598cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
599cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
600cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < (ssize_t)size) {
601cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
602cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
603cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
604cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const uint8_t *data = buffer->data();
605cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
606cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t type = U32_AT(data);
607cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t handler = U32_AT(&data[4]);
608cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t flags = U32LE_AT(&data[8]);
609cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
610cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<MetaData> meta = new MetaData;
611cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
612cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t rate = U32LE_AT(&data[20]);
613cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t scale = U32LE_AT(&data[24]);
614cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
61563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    uint32_t sampleSize = U32LE_AT(&data[44]);
61663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber
617cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const char *mime = NULL;
618cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    Track::Kind kind = Track::OTHER;
619cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
620cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (type == FOURCC('v', 'i', 'd', 's')) {
621cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        mime = GetMIMETypeForHandler(handler);
622cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
623cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (mime && strncasecmp(mime, "video/", 6)) {
624cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
625cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
626cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
6273001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        if (mime == NULL) {
6283001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            LOGW("Unsupported video format '%c%c%c%c'",
6293001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                 (char)(handler >> 24),
6303001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                 (char)((handler >> 16) & 0xff),
6313001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                 (char)((handler >> 8) & 0xff),
6323001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                 (char)(handler & 0xff));
6333001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        }
6343001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
635cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        kind = Track::VIDEO;
636cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    } else if (type == FOURCC('a', 'u', 'd', 's')) {
637cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (mime && strncasecmp(mime, "audio/", 6)) {
638cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
639cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
640cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
641cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        kind = Track::AUDIO;
642cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
643cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
644cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!mime) {
645cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        mime = "application/octet-stream";
646cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
647cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
648cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    meta->setCString(kKeyMIMEType, mime);
649cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
650cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mTracks.push();
651cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
652cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
653cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mMeta = meta;
654cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mRate = rate;
655cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mScale = scale;
65663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    track->mBytesPerSample = sampleSize;
657cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mKind = kind;
658cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mNumSyncSamples = 0;
659cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mThumbnailSampleSize = 0;
660cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mThumbnailSampleIndex = -1;
661cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mMaxSampleSize = 0;
662bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    track->mAvgChunkSize = 1.0;
663bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    track->mFirstChunkSize = 0;
664cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
665cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
666cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
667cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
668cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) {
669cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mTracks.isEmpty()) {
670cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
671cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
672cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
673cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
674cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
675cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (track->mKind == Track::OTHER) {
676cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        // We don't support this content, but that's not a parsing error.
677cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return OK;
678cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
679cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
680cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    bool isVideo = (track->mKind == Track::VIDEO);
681cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
682bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    if ((isVideo && size < 40) || (!isVideo && size < 16)) {
683bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        // Expected a BITMAPINFO or WAVEFORMAT(EX) structure, respectively.
684cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
685cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
686cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
687cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> buffer = new ABuffer(size);
688cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
689cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
690cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < (ssize_t)size) {
691cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
692cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
693cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
694cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const uint8_t *data = buffer->data();
695cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
696cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (isVideo) {
697cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t width = U32LE_AT(&data[4]);
698cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t height = U32LE_AT(&data[8]);
699cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
700cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeyWidth, width);
701cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeyHeight, height);
702cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    } else {
703cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t format = U16LE_AT(data);
7043001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
705cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (format == 0x55) {
706cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
7073001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        } else {
7083001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            LOGW("Unsupported audio format = 0x%04x", format);
709cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
710cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
711cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t numChannels = U16LE_AT(&data[2]);
712cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t sampleRate = U32LE_AT(&data[4]);
713cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
714cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeyChannelCount, numChannels);
715cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeySampleRate, sampleRate);
716cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
717cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
718cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
719cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
720cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
721cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber// static
722cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberbool AVIExtractor::IsCorrectChunkType(
723cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) {
724cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t chunkBase = chunkType & 0xffff;
725cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
726cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    switch (kind) {
727cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case Track::VIDEO:
728cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
729cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (chunkBase != FOURCC(0, 0, 'd', 'c')
730cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    && chunkBase != FOURCC(0, 0, 'd', 'b')) {
731cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return false;
732cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
733cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
734cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
735cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
736cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case Track::AUDIO:
737cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
738cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (chunkBase != FOURCC(0, 0, 'w', 'b')) {
739cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return false;
740cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
741cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
742cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
743cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
744cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        default:
745cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
746cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
747cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
748cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (trackIndex < 0) {
749cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return true;
750cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
751cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
752cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t hi = chunkType >> 24;
753cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t lo = (chunkType >> 16) & 0xff;
754cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
755cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
756cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return false;
757cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
758cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
759cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (trackIndex != (10 * (hi - '0') + (lo - '0'))) {
760cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return false;
761cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
762cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
763cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return true;
764cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
765cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
766cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
767cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if ((size % 16) != 0) {
768cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
769cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
770cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
771cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> buffer = new ABuffer(size);
772cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
773cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
774cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < (ssize_t)size) {
775cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
776cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
777cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
778cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const uint8_t *data = buffer->data();
779cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
780cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (size > 0) {
781cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t chunkType = U32_AT(data);
782cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
783cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint8_t hi = chunkType >> 24;
784cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint8_t lo = (chunkType >> 16) & 0xff;
785cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
786cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
787cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
788cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
789cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
790cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t trackIndex = 10 * (hi - '0') + (lo - '0');
791cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
792cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (trackIndex >= mTracks.size()) {
793cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
794cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
795cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
796cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        Track *track = &mTracks.editItemAt(trackIndex);
797cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
798cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (!IsCorrectChunkType(-1, track->mKind, chunkType)) {
799cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return ERROR_MALFORMED;
800cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
801cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
802cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (track->mKind == Track::OTHER) {
803cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            data += 16;
804cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            size -= 16;
805cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            continue;
806cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
807cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
808cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t flags = U32LE_AT(&data[4]);
809cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t offset = U32LE_AT(&data[8]);
810cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        uint32_t chunkSize = U32LE_AT(&data[12]);
811cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
812cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (chunkSize > track->mMaxSampleSize) {
813cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            track->mMaxSampleSize = chunkSize;
814cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
815cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
816cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mSamples.push();
817cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
818cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        SampleInfo *info =
819cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            &track->mSamples.editItemAt(track->mSamples.size() - 1);
820cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
821cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        info->mOffset = offset;
822cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        info->mIsKey = (flags & 0x10) != 0;
823cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
824cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (info->mIsKey) {
825cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            static const size_t kMaxNumSyncSamplesToScan = 20;
826cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
827cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) {
828cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                if (chunkSize > track->mThumbnailSampleSize) {
829cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    track->mThumbnailSampleSize = chunkSize;
830cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
831cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                    track->mThumbnailSampleIndex =
832cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                        track->mSamples.size() - 1;
833cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                }
834cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
835cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
836cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            ++track->mNumSyncSamples;
837cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
838cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
839cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        data += 16;
840cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size -= 16;
841cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
842cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
843cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!mTracks.isEmpty()) {
844cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        off64_t offset;
845cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t size;
846cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        bool isKey;
84763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        int64_t timeUs;
84863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        status_t err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
849cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
850cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (err != OK) {
851cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            mOffsetsAreAbsolute = !mOffsetsAreAbsolute;
85263749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
853cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
854cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (err != OK) {
855cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return err;
856cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
857cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
858cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
859cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        LOGV("Chunk offsets are %s",
860cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber             mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative");
861cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
862cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
863cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
864cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        Track *track = &mTracks.editItemAt(i);
865cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
866bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        if (track->mBytesPerSample > 0) {
867bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            // Assume all chunks are roughly the same size for now.
868bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
869bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            // Compute the avg. size of the first 128 chunks (if there are
870bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            // that many), but exclude the size of the first one, since
871bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            // it may be an outlier.
872bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            size_t numSamplesToAverage = track->mSamples.size();
873bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            if (numSamplesToAverage > 256) {
874bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                numSamplesToAverage = 256;
875bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            }
876bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
877bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            double avgChunkSize = 0;
878bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            size_t j;
879bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            for (j = 0; j <= numSamplesToAverage; ++j) {
880bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                off64_t offset;
881bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                size_t size;
882bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                bool isKey;
883bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                int64_t dummy;
884bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
885bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                status_t err =
886bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                    getSampleInfo(
887bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                            i, j,
888bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                            &offset, &size, &isKey, &dummy);
889bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
890bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                if (err != OK) {
891bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                    return err;
892bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                }
893bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
894bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                if (j == 0) {
895bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                    track->mFirstChunkSize = size;
896bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                    continue;
897bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                }
898bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
899bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                avgChunkSize += size;
900bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            }
901bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
902bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            avgChunkSize /= numSamplesToAverage;
903bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
904bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            track->mAvgChunkSize = avgChunkSize;
905bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        }
906bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
90763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        int64_t durationUs;
90863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        CHECK_EQ((status_t)OK,
90963749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber                 getSampleTime(i, track->mSamples.size() - 1, &durationUs));
910cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
911cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        LOGV("track %d duration = %.2f secs", i, durationUs / 1E6);
912cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
913cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt64(kKeyDuration, durationUs);
914cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize);
915cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
916cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        const char *tmp;
917cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp));
918cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
919cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        AString mime = tmp;
920cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
9213001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        if (!strncasecmp("video/", mime.c_str(), 6)) {
9223001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            if (track->mThumbnailSampleIndex >= 0) {
9233001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                int64_t thumbnailTimeUs;
9243001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                CHECK_EQ((status_t)OK,
9253001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                         getSampleTime(i, track->mThumbnailSampleIndex,
9263001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                                       &thumbnailTimeUs));
927cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
9283001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
9293001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            }
9303001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
9313001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            status_t err = OK;
932cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
933cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
9343001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                err = addMPEG4CodecSpecificData(i);
9353001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
9363001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                err = addH264CodecSpecificData(i);
9373001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            }
938cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
9393001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            if (err != OK) {
9403001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                return err;
941cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
942cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
943cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
944cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
945cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    mFoundIndex = true;
946cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
947cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
948cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
949cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
950cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatic size_t GetSizeWidth(size_t x) {
951cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t n = 1;
952cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (x > 127) {
953cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ++n;
954cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        x >>= 7;
955cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
956cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return n;
957cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
958cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
959cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatic uint8_t *EncodeSize(uint8_t *dst, size_t x) {
960cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (x > 127) {
961cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *dst++ = (x & 0x7f) | 0x80;
962cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        x >>= 7;
963cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
964cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = x;
965cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return dst;
966cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
967cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
968cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) {
969cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
970cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
971cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
972cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
973cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> csd = new ABuffer(len3);
974cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t *dst = csd->data();
975cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x03;
976cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    dst = EncodeSize(dst, len2 + 3);
977cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x00;  // ES_ID
978cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x00;
979cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
980cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
981cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x04;
982cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    dst = EncodeSize(dst, len1 + 13);
983cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x01;  // Video ISO/IEC 14496-2 Simple Profile
984cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    for (size_t i = 0; i < 12; ++i) {
985cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *dst++ = 0x00;
986cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
987cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
988cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *dst++ = 0x05;
989cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    dst = EncodeSize(dst, config->size());
990cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    memcpy(dst, config->data(), config->size());
991cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    dst += config->size();
992cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
993cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    // hexdump(csd->data(), csd->size());
994cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
995cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return csd;
996cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
997cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
998cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) {
999cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    Track *track = &mTracks.editItemAt(trackIndex);
1000cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1001cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    off64_t offset;
1002cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t size;
1003cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    bool isKey;
100463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    int64_t timeUs;
100563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    status_t err =
100663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        getSampleInfo(trackIndex, 0, &offset, &size, &isKey, &timeUs);
1007cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1008cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (err != OK) {
1009cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return err;
1010cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1011cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1012cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> buffer = new ABuffer(size);
1013cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
1014cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1015cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < (ssize_t)size) {
1016cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
1017cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1018cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1019cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    // Extract everything up to the first VOP start code from the first
1020cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    // frame's encoded data and use it to construct an ESDS with the
1021cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    // codec specific data.
1022cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1023cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    size_t i = 0;
1024cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    bool found = false;
1025cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (i + 3 < buffer->size()) {
1026cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) {
1027cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            found = true;
1028cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
1029cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
1030cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1031cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ++i;
1032cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1033cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1034cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!found) {
1035cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
1036cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1037cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1038cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    buffer->setRange(0, i);
1039cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1040cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer);
1041cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size());
1042cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1043cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
1044cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
1045cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
10463001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huberstatus_t AVIExtractor::addH264CodecSpecificData(size_t trackIndex) {
10473001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    Track *track = &mTracks.editItemAt(trackIndex);
10483001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
10493001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    off64_t offset;
10503001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    size_t size;
10513001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    bool isKey;
10523001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    int64_t timeUs;
10533001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
10543001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    // Extract codec specific data from the first non-empty sample.
10553001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
10563001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    size_t sampleIndex = 0;
10573001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    for (;;) {
10583001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        status_t err =
10593001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            getSampleInfo(
10603001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber                    trackIndex, sampleIndex, &offset, &size, &isKey, &timeUs);
10613001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
10623001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        if (err != OK) {
10633001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            return err;
10643001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        }
10653001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
10663001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        if (size > 0) {
10673001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber            break;
10683001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        }
10693001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
10703001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        ++sampleIndex;
10713001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    }
10723001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
10733001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    sp<ABuffer> buffer = new ABuffer(size);
10743001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
10753001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
10763001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    if (n < (ssize_t)size) {
10773001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
10783001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    }
10793001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
10803001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    sp<MetaData> meta = MakeAVCCodecSpecificData(buffer);
10813001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
10823001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    if (meta == NULL) {
10833001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        LOGE("Unable to extract AVC codec specific data");
10843001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber        return ERROR_MALFORMED;
10853001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    }
10863001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
10873001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    int32_t width, height;
10883001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    CHECK(meta->findInt32(kKeyWidth, &width));
10893001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    CHECK(meta->findInt32(kKeyHeight, &height));
10903001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
10913001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    uint32_t type;
10923001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    const void *csd;
10933001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    size_t csdSize;
10943001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize));
10953001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
10963001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    track->mMeta->setInt32(kKeyWidth, width);
10971fc2e60d59abfe1c4d7f9611c685c894ad1a383fAndreas Huber    track->mMeta->setInt32(kKeyHeight, height);
10983001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    track->mMeta->setData(kKeyAVCC, type, csd, csdSize);
10993001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
11003001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber    return OK;
11013001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber}
11023001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber
1103cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::getSampleInfo(
1104cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t trackIndex, size_t sampleIndex,
110563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        off64_t *offset, size_t *size, bool *isKey,
110663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        int64_t *sampleTimeUs) {
1107cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (trackIndex >= mTracks.size()) {
1108cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return -ERANGE;
1109cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1110cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1111cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const Track &track = mTracks.itemAt(trackIndex);
1112cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1113cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (sampleIndex >= track.mSamples.size()) {
1114cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return -ERANGE;
1115cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1116cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1117cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const SampleInfo &info = track.mSamples.itemAt(sampleIndex);
1118cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1119cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!mOffsetsAreAbsolute) {
1120cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *offset = info.mOffset + mMovieOffset + 8;
1121cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    } else {
1122cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *offset = info.mOffset;
1123cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1124cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1125cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *size = 0;
1126cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1127cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint8_t tmp[8];
1128cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t n = mDataSource->readAt(*offset, tmp, 8);
1129cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1130cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (n < 8) {
1131cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
1132cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1133cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1134cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    uint32_t chunkType = U32_AT(tmp);
1135cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1136cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) {
1137cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return ERROR_MALFORMED;
1138cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1139cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1140cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *offset += 8;
1141cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *size = U32LE_AT(&tmp[4]);
1142cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1143cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    *isKey = info.mIsKey;
1144cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1145bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    if (track.mBytesPerSample > 0) {
1146bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        size_t sampleStartInBytes;
1147bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        if (sampleIndex == 0) {
1148bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            sampleStartInBytes = 0;
1149bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        } else {
1150bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            sampleStartInBytes =
1151bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                track.mFirstChunkSize + track.mAvgChunkSize * (sampleIndex - 1);
1152bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        }
1153bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
1154bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        sampleIndex = sampleStartInBytes / track.mBytesPerSample;
1155bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    }
1156bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
115763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale;
115863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber
1159cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return OK;
1160cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
1161cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
116263749954aa828b3f73b4738659eaea5eaeeca874Andreas Huberstatus_t AVIExtractor::getSampleTime(
116363749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber        size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs) {
116463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    off64_t offset;
116563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    size_t size;
116663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    bool isKey;
116763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber    return getSampleInfo(
116863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber            trackIndex, sampleIndex, &offset, &size, &isKey, sampleTimeUs);
116963749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber}
117063749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber
1171cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::getSampleIndexAtTime(
1172cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t trackIndex,
1173cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
1174cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        size_t *sampleIndex) const {
1175cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (trackIndex >= mTracks.size()) {
1176cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return -ERANGE;
1177cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1178cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1179cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    const Track &track = mTracks.itemAt(trackIndex);
1180cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1181bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    ssize_t closestSampleIndex;
1182bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
1183bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    if (track.mBytesPerSample > 0) {
1184bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        size_t closestByteOffset =
1185bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            (timeUs * track.mBytesPerSample)
1186bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                / track.mRate * track.mScale / 1000000ll;
1187bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber
1188bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        if (closestByteOffset <= track.mFirstChunkSize) {
1189bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            closestSampleIndex = 0;
1190bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        } else {
1191bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber            closestSampleIndex =
1192bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                (closestByteOffset - track.mFirstChunkSize)
1193bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber                    / track.mAvgChunkSize;
1194bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        }
1195bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    } else {
1196bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        // Each chunk contains a single sample.
1197bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber        closestSampleIndex = timeUs / track.mRate * track.mScale / 1000000ll;
1198bea34b942d1727934e4cd69c5e7b69679b4e8891Andreas Huber    }
1199cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1200cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t numSamples = track.mSamples.size();
1201cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1202cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (closestSampleIndex < 0) {
1203cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        closestSampleIndex = 0;
1204cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    } else if (closestSampleIndex >= numSamples) {
1205cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        closestSampleIndex = numSamples - 1;
1206cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1207cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1208cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) {
1209cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        *sampleIndex = closestSampleIndex;
1210cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1211cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return OK;
1212cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1213cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1214cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t prevSyncSampleIndex = closestSampleIndex;
1215cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (prevSyncSampleIndex >= 0) {
1216cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        const SampleInfo &info =
1217cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            track.mSamples.itemAt(prevSyncSampleIndex);
1218cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1219cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (info.mIsKey) {
1220cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
1221cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
1222cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1223cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        --prevSyncSampleIndex;
1224cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1225cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1226cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    ssize_t nextSyncSampleIndex = closestSampleIndex;
1227cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    while (nextSyncSampleIndex < numSamples) {
1228cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        const SampleInfo &info =
1229cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            track.mSamples.itemAt(nextSyncSampleIndex);
1230cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1231cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        if (info.mIsKey) {
1232cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
1233cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
1234cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1235cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        ++nextSyncSampleIndex;
1236cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1237cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1238cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    switch (mode) {
1239cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC:
1240cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
1241cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            *sampleIndex = prevSyncSampleIndex;
1242cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1243cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR;
1244cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
1245cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1246cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case MediaSource::ReadOptions::SEEK_NEXT_SYNC:
1247cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
1248cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            *sampleIndex = nextSyncSampleIndex;
1249cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1250cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR;
1251cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
1252cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1253cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC:
1254cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        {
1255cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) {
1256cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return UNKNOWN_ERROR;
1257cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
1258cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1259cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (prevSyncSampleIndex < 0) {
1260cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                *sampleIndex = nextSyncSampleIndex;
1261cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return OK;
1262cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
1263cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1264cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            if (nextSyncSampleIndex >= numSamples) {
1265cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                *sampleIndex = prevSyncSampleIndex;
1266cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                return OK;
1267cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            }
1268cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1269cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            size_t dist1 = closestSampleIndex - prevSyncSampleIndex;
1270cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            size_t dist2 = nextSyncSampleIndex - closestSampleIndex;
1271cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1272cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            *sampleIndex =
1273cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber                (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex;
1274cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1275cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            return OK;
1276cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        }
1277cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1278cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        default:
1279cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            TRESPASS();
1280cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber            break;
1281cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1282cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
1283cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1284cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberbool SniffAVI(
1285cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
1286cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        sp<AMessage> *) {
1287cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    char tmp[12];
1288cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (source->readAt(0, tmp, 12) < 12) {
1289cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return false;
1290cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1291cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1292cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) {
1293cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI);
1294f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber
1295f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber        // Just a tad over the mp3 extractor's confidence, since
1296f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber        // these .avi files may contain .mp3 content that otherwise would
1297f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber        // mistakenly lead to us identifying the entire file as a .mp3 file.
1298f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber        *confidence = 0.21;
1299cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1300cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber        return true;
1301cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    }
1302cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1303cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber    return false;
1304cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}
1305cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber
1306cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}  // namespace android
1307