AVIExtractor.cpp revision ec2e74b538b899aac54f55ed1aa60286624f8895
1f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber/*
2f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * Copyright (C) 2011 The Android Open Source Project
3f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *
4f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * you may not use this file except in compliance with the License.
6f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * You may obtain a copy of the License at
7f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *
8f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *
10f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * Unless required by applicable law or agreed to in writing, software
11f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * See the License for the specific language governing permissions and
14f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * limitations under the License.
15f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber */
16f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
17f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber//#define LOG_NDEBUG 0
18f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#define LOG_TAG "AVIExtractor"
19f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <utils/Log.h>
20f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
21c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber#include "include/avc_utils.h"
22f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include "include/AVIExtractor.h"
23f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
24f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <binder/ProcessState.h>
25f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/foundation/hexdump.h>
26f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
27f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/foundation/ADebug.h>
28f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/DataSource.h>
29f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaBuffer.h>
30f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
31f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaDefs.h>
32f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaErrors.h>
33f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MetaData.h>
34f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/Utils.h>
35f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
36f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubernamespace android {
37f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
38f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstruct AVIExtractor::AVISource : public MediaSource {
39f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    AVISource(const sp<AVIExtractor> &extractor, size_t trackIndex);
40f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
41f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual status_t start(MetaData *params);
42f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual status_t stop();
43f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
44f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual sp<MetaData> getFormat();
45f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
46f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual status_t read(
47f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            MediaBuffer **buffer, const ReadOptions *options);
48f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
49f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberprotected:
50f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    virtual ~AVISource();
51f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
52f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberprivate:
53f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<AVIExtractor> mExtractor;
54f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t mTrackIndex;
55f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const AVIExtractor::Track &mTrack;
56f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    MediaBufferGroup *mBufferGroup;
57f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t mSampleIndex;
58f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
5932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    sp<MP3Splitter> mSplitter;
6032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
61f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(AVISource);
62f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber};
63f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
64f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber////////////////////////////////////////////////////////////////////////////////
65f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
6632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huberstruct AVIExtractor::MP3Splitter : public RefBase {
6732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    MP3Splitter();
6832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
6932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    void clear();
7032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    void append(MediaBuffer *buffer);
7132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    status_t read(MediaBuffer **buffer);
7232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
7332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huberprotected:
7432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    virtual ~MP3Splitter();
7532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
7632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huberprivate:
7732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    bool mFindSync;
7832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    int64_t mBaseTimeUs;
7932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    int64_t mNumSamplesRead;
8032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    sp<ABuffer> mBuffer;
8132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
8232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    bool resync();
8332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
8432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    DISALLOW_EVIL_CONSTRUCTORS(MP3Splitter);
8532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber};
8632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
8732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber////////////////////////////////////////////////////////////////////////////////
8832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
89f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::AVISource::AVISource(
90f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const sp<AVIExtractor> &extractor, size_t trackIndex)
91f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    : mExtractor(extractor),
92f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber      mTrackIndex(trackIndex),
93f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber      mTrack(mExtractor->mTracks.itemAt(trackIndex)),
94f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber      mBufferGroup(NULL) {
95f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
96f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
97f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::AVISource::~AVISource() {
98f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mBufferGroup) {
99f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        stop();
100f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
101f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
102f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
103f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::AVISource::start(MetaData *params) {
104f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    CHECK(!mBufferGroup);
105f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
106f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mBufferGroup = new MediaBufferGroup;
107f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
108f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
109f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
110f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mSampleIndex = 0;
111f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
11232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    const char *mime;
11332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    CHECK(mTrack.mMeta->findCString(kKeyMIMEType, &mime));
11432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
11532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
11632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        mSplitter = new MP3Splitter;
11732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    } else {
11832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        mSplitter.clear();
11932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    }
12032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
121f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
122f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
123f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
124f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::AVISource::stop() {
125f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    CHECK(mBufferGroup);
126f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
127f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    delete mBufferGroup;
128f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mBufferGroup = NULL;
129f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
13032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    mSplitter.clear();
13132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
132f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
133f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
134f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
135f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MetaData> AVIExtractor::AVISource::getFormat() {
136f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return mTrack.mMeta;
137f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
138f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
139f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::AVISource::read(
140f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
141f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    CHECK(mBufferGroup);
142f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
143f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *buffer = NULL;
144f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
145f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    int64_t seekTimeUs;
146f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ReadOptions::SeekMode seekMode;
147f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
148f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        status_t err =
149f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            mExtractor->getSampleIndexAtTime(
150f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    mTrackIndex, seekTimeUs, seekMode, &mSampleIndex);
151f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
152f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (err != OK) {
153f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_END_OF_STREAM;
154f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
15532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
15632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        if (mSplitter != NULL) {
15732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            mSplitter->clear();
15832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        }
159f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
160f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
16132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    for (;;) {
16232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        if (mSplitter != NULL) {
16332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            status_t err = mSplitter->read(buffer);
164f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
16532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            if (err == OK) {
16632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                break;
16732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            } else if (err != -EAGAIN) {
16832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                return err;
16932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            }
17032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        }
171f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
17232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        off64_t offset;
17332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        size_t size;
17432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        bool isKey;
17532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        int64_t timeUs;
17632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        status_t err = mExtractor->getSampleInfo(
17732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs);
17832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
17932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        ++mSampleIndex;
18032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
18132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        if (err != OK) {
18232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            return ERROR_END_OF_STREAM;
18332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        }
18432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
18532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        MediaBuffer *out;
18632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK);
18732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
18832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size);
18932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
19032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        if (n < (ssize_t)size) {
19132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
19232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        }
19332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
19432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        out->set_range(0, size);
19532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
19632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        out->meta_data()->setInt64(kKeyTime, timeUs);
19732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
19832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        if (isKey) {
19932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            out->meta_data()->setInt32(kKeyIsSyncFrame, 1);
20032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        }
20132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
20232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        if (mSplitter == NULL) {
20332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            *buffer = out;
20432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            break;
20532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        }
20632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
20732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        mSplitter->append(out);
20832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        out->release();
20932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        out = NULL;
210f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
211f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
21232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    return OK;
21332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber}
214f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
21532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber////////////////////////////////////////////////////////////////////////////////
216f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
21732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas HuberAVIExtractor::MP3Splitter::MP3Splitter()
21832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    : mFindSync(true),
21932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber      mBaseTimeUs(-1ll),
22032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber      mNumSamplesRead(0) {
22132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber}
22232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
22332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas HuberAVIExtractor::MP3Splitter::~MP3Splitter() {
22432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber}
22532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
22632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Hubervoid AVIExtractor::MP3Splitter::clear() {
22732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    mFindSync = true;
22832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    mBaseTimeUs = -1ll;
22932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    mNumSamplesRead = 0;
23032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
23132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    if (mBuffer != NULL) {
23232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        mBuffer->setRange(0, 0);
233f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
23432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber}
235f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
23632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Hubervoid AVIExtractor::MP3Splitter::append(MediaBuffer *buffer) {
23732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    size_t prevCapacity = (mBuffer != NULL) ? mBuffer->capacity() : 0;
238f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
23932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    if (mBaseTimeUs < 0) {
24032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        CHECK(mBuffer == NULL || mBuffer->size() == 0);
24132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        CHECK(buffer->meta_data()->findInt64(kKeyTime, &mBaseTimeUs));
24232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        mNumSamplesRead = 0;
24332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    }
244f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
24532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    if (mBuffer != NULL && mBuffer->offset() > 0) {
24632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        memmove(mBuffer->base(), mBuffer->data(), mBuffer->size());
24732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        mBuffer->setRange(0, mBuffer->size());
248f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
249f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
25032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    if (mBuffer == NULL
25132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            || mBuffer->size() + buffer->range_length() > prevCapacity) {
25232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        size_t newCapacity =
25332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            (prevCapacity + buffer->range_length() + 1023) & ~1023;
25432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
25532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        sp<ABuffer> newBuffer = new ABuffer(newCapacity);
25632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        if (mBuffer != NULL) {
25732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
25832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            newBuffer->setRange(0, mBuffer->size());
25932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        } else {
26032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            newBuffer->setRange(0, 0);
26132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        }
26232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        mBuffer = newBuffer;
26332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    }
26432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
26532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    memcpy(mBuffer->data() + mBuffer->size(),
26632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber           (const uint8_t *)buffer->data() + buffer->range_offset(),
26732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber           buffer->range_length());
26832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
26932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    mBuffer->setRange(0, mBuffer->size() + buffer->range_length());
27032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber}
27132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
27232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huberbool AVIExtractor::MP3Splitter::resync() {
27332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    if (mBuffer == NULL) {
27432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        return false;
27532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    }
27632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
27732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    bool foundSync = false;
27832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    for (size_t offset = 0; offset + 3 < mBuffer->size(); ++offset) {
27932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        uint32_t firstHeader = U32_AT(mBuffer->data() + offset);
28032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
28132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        size_t frameSize;
28232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        if (!GetMPEGAudioFrameSize(firstHeader, &frameSize)) {
28332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            continue;
28432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        }
28532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
28632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        size_t subsequentOffset = offset + frameSize;
28732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        size_t i = 3;
28832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        while (i > 0) {
28932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            if (subsequentOffset + 3 >= mBuffer->size()) {
29032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                break;
29132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            }
29232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
29332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            static const uint32_t kMask = 0xfffe0c00;
29432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
29532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            uint32_t header = U32_AT(mBuffer->data() + subsequentOffset);
29632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            if ((header & kMask) != (firstHeader & kMask)) {
29732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                break;
29832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            }
29932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
30032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            if (!GetMPEGAudioFrameSize(header, &frameSize)) {
30132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                break;
30232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            }
30332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
30432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            subsequentOffset += frameSize;
30532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            --i;
30632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        }
30732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
30832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        if (i == 0) {
30932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            foundSync = true;
31032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            memmove(mBuffer->data(),
31132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                    mBuffer->data() + offset,
31232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                    mBuffer->size() - offset);
31332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
31432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            mBuffer->setRange(0, mBuffer->size() - offset);
31532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            break;
31632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        }
31732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    }
31832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
31932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    return foundSync;
32032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber}
32132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
32232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huberstatus_t AVIExtractor::MP3Splitter::read(MediaBuffer **out) {
32332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    *out = NULL;
32432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
32532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    if (mFindSync) {
32632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        if (!resync()) {
32732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            return -EAGAIN;
32832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        }
32932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
33032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        mFindSync = false;
33132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    }
33232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
33332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    if (mBuffer->size() < 4) {
33432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        return -EAGAIN;
33532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    }
33632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
33732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    uint32_t header = U32_AT(mBuffer->data());
33832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    size_t frameSize;
33932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    int sampleRate;
34032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    int numSamples;
34132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    if (!GetMPEGAudioFrameSize(
34232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                header, &frameSize, &sampleRate, NULL, NULL, &numSamples)) {
34332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        return ERROR_MALFORMED;
34432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    }
34532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
34632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    if (mBuffer->size() < frameSize) {
34732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        return -EAGAIN;
34832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    }
34932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
35032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    MediaBuffer *mbuf = new MediaBuffer(frameSize);
35132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    memcpy(mbuf->data(), mBuffer->data(), frameSize);
35232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
35332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    int64_t timeUs = mBaseTimeUs + (mNumSamplesRead * 1000000ll) / sampleRate;
35432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    mNumSamplesRead += numSamples;
35532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
35632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    mbuf->meta_data()->setInt64(kKeyTime, timeUs);
35732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
35832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    mBuffer->setRange(
35932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            mBuffer->offset() + frameSize, mBuffer->size() - frameSize);
36032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
36132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    *out = mbuf;
362f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
363f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
364f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
365f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
366f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber////////////////////////////////////////////////////////////////////////////////
367f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
368f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::AVIExtractor(const sp<DataSource> &dataSource)
369f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    : mDataSource(dataSource) {
370f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mInitCheck = parseHeaders();
371f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
372f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mInitCheck != OK) {
373f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        mTracks.clear();
374f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
375f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
376f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
377f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::~AVIExtractor() {
378f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
379f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
380f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersize_t AVIExtractor::countTracks() {
381f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return mTracks.size();
382f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
383f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
384f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MediaSource> AVIExtractor::getTrack(size_t index) {
385f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return index < mTracks.size() ? new AVISource(this, index) : NULL;
386f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
387f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
388f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MetaData> AVIExtractor::getTrackMetaData(
389f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t index, uint32_t flags) {
390f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL;
391f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
392f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
393f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MetaData> AVIExtractor::getMetaData() {
394f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<MetaData> meta = new MetaData;
395f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
396f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mInitCheck == OK) {
397f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_AVI);
398f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
399f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
400f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return meta;
401f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
402f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
403f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseHeaders() {
404f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mTracks.clear();
405f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mMovieOffset = 0;
406f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mFoundIndex = false;
407f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mOffsetsAreAbsolute = false;
408f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
409f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t res = parseChunk(0ll, -1ll);
410f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
411f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (res < 0) {
412f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return (status_t)res;
413f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
414f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
415f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mMovieOffset == 0ll || !mFoundIndex) {
416f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
417f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
418f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
419f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
420f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
421f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
422f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberssize_t AVIExtractor::parseChunk(off64_t offset, off64_t size, int depth) {
423f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (size >= 0 && size < 8) {
424f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
425f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
426f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
427f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t tmp[12];
428f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, tmp, 8);
429f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
430f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < 8) {
431f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
432f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
433f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
434f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t fourcc = U32_AT(tmp);
435f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t chunkSize = U32LE_AT(&tmp[4]);
436f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
437f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (size >= 0 && chunkSize + 8 > size) {
438f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
439f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
440f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
441f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    static const char kPrefix[] = "                              ";
442f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const char *prefix = &kPrefix[strlen(kPrefix) - 2 * depth];
443f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
444f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (fourcc == FOURCC('L', 'I', 'S', 'T')
445f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            || fourcc == FOURCC('R', 'I', 'F', 'F')) {
446f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        // It's a list of chunks
447f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
448f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (size >= 0 && size < 12) {
449f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
450f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
451f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
452f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        n = mDataSource->readAt(offset + 8, &tmp[8], 4);
453f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
454f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (n < 4) {
455f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
456f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
457f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
458f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t subFourcc = U32_AT(&tmp[8]);
459f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
4603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("%s offset 0x%08llx LIST of '%c%c%c%c', size %d",
461f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             prefix,
462f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             offset,
463f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)(subFourcc >> 24),
464f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)((subFourcc >> 16) & 0xff),
465f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)((subFourcc >> 8) & 0xff),
466f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)(subFourcc & 0xff),
467f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             chunkSize - 4);
468f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
469f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (subFourcc == FOURCC('m', 'o', 'v', 'i')) {
470f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            // We're not going to parse this, but will take note of the
471f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            // offset.
472f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
473f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            mMovieOffset = offset;
474f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        } else {
475f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            off64_t subOffset = offset + 12;
476f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            off64_t subOffsetLimit = subOffset + chunkSize - 4;
477f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            while (subOffset < subOffsetLimit) {
478f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                ssize_t res =
479f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    parseChunk(subOffset, subOffsetLimit - subOffset, depth + 1);
480f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
481f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                if (res < 0) {
482f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    return res;
483f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                }
484f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
485f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                subOffset += res;
486f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
487f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
488f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else {
4893856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("%s offset 0x%08llx CHUNK '%c%c%c%c'",
490f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             prefix,
491f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             offset,
492f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)(fourcc >> 24),
493f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)((fourcc >> 16) & 0xff),
494f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)((fourcc >> 8) & 0xff),
495f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             (char)(fourcc & 0xff));
496f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
497f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        status_t err = OK;
498f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
499f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        switch (fourcc) {
500f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            case FOURCC('s', 't', 'r', 'h'):
501f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            {
502f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                err = parseStreamHeader(offset + 8, chunkSize);
503f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                break;
504f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
505f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
506f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            case FOURCC('s', 't', 'r', 'f'):
507f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            {
508f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                err = parseStreamFormat(offset + 8, chunkSize);
509f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                break;
510f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
511f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
512f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            case FOURCC('i', 'd', 'x', '1'):
513f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            {
514f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                err = parseIndex(offset + 8, chunkSize);
515f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                break;
516f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
517f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
518f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            default:
519f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                break;
520f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
521f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
522f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (err != OK) {
523f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return err;
524f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
525f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
526f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
527f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (chunkSize & 1) {
528f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ++chunkSize;
529f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
530f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
531f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return chunkSize + 8;
532f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
533f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
534f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatic const char *GetMIMETypeForHandler(uint32_t handler) {
535f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    switch (handler) {
536f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        // Wow... shamelessly copied from
537f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        // http://wiki.multimedia.cx/index.php?title=ISO_MPEG-4
538f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
539f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('3', 'I', 'V', '2'):
540f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('3', 'i', 'v', '2'):
541f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('B', 'L', 'Z', '0'):
542f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'I', 'G', 'I'):
543f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'I', 'V', '1'):
544f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('d', 'i', 'v', '1'):
545f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'I', 'V', 'X'):
546f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('d', 'i', 'v', 'x'):
547f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'X', '5', '0'):
548f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('d', 'x', '5', '0'):
549f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('D', 'X', 'G', 'M'):
550f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('E', 'M', '4', 'A'):
551f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('E', 'P', 'H', 'V'):
552f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('F', 'M', 'P', '4'):
553f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('f', 'm', 'p', '4'):
554f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('F', 'V', 'F', 'W'):
555f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('H', 'D', 'X', '4'):
556f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('h', 'd', 'x', '4'):
557f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', '4', 'C', 'C'):
558f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', '4', 'S', '2'):
559f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('m', '4', 's', '2'):
560f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', 'P', '4', 'S'):
561f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('m', 'p', '4', 's'):
562f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', 'P', '4', 'V'):
563f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
564f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('M', 'V', 'X', 'M'):
565f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('R', 'M', 'P', '4'):
566f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('S', 'E', 'D', 'G'):
567f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('S', 'M', 'P', '4'):
568f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('U', 'M', 'P', '4'):
569f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('W', 'V', '1', 'F'):
570f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('X', 'V', 'I', 'D'):
571f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('X', 'v', 'i', 'D'):
572f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('x', 'v', 'i', 'd'):
573f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case FOURCC('X', 'V', 'I', 'X'):
574f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
575f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
576c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        // from http://wiki.multimedia.cx/index.php?title=H264
577c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
578c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        case FOURCC('d', 'a', 'v', 'c'):
579c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        case FOURCC('x', '2', '6', '4'):
580ec2e74b538b899aac54f55ed1aa60286624f8895Dongwon Kang        case FOURCC('H', '2', '6', '4'):
581c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        case FOURCC('v', 's', 's', 'h'):
582c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
583c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
584f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        default:
585f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return NULL;
586f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
587f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
588f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
589f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) {
590f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (size != 56) {
591f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
592f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
593f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
594f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mTracks.size() > 99) {
595f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return -ERANGE;
596f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
597f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
598f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
599f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
600f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
601f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < (ssize_t)size) {
602f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
603f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
604f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
605f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const uint8_t *data = buffer->data();
606f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
607f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t type = U32_AT(data);
608f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t handler = U32_AT(&data[4]);
609f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t flags = U32LE_AT(&data[8]);
610f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
611f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<MetaData> meta = new MetaData;
612f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
613f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t rate = U32LE_AT(&data[20]);
614f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t scale = U32LE_AT(&data[24]);
615f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
6167de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    uint32_t sampleSize = U32LE_AT(&data[44]);
6177de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber
618f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const char *mime = NULL;
619f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    Track::Kind kind = Track::OTHER;
620f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
621f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (type == FOURCC('v', 'i', 'd', 's')) {
622f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        mime = GetMIMETypeForHandler(handler);
623f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
624f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (mime && strncasecmp(mime, "video/", 6)) {
625f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
626f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
627f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
628c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        if (mime == NULL) {
6295ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Unsupported video format '%c%c%c%c'",
630c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                 (char)(handler >> 24),
631c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                 (char)((handler >> 16) & 0xff),
632c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                 (char)((handler >> 8) & 0xff),
633c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                 (char)(handler & 0xff));
634c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        }
635c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
636f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        kind = Track::VIDEO;
637f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else if (type == FOURCC('a', 'u', 'd', 's')) {
638f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (mime && strncasecmp(mime, "audio/", 6)) {
639f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
640f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
641f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
642f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        kind = Track::AUDIO;
643f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
644f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
645f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!mime) {
646f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        mime = "application/octet-stream";
647f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
648f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
649f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    meta->setCString(kKeyMIMEType, mime);
650f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
651f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mTracks.push();
652f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
653f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
654f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mMeta = meta;
655f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mRate = rate;
656f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mScale = scale;
6577de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    track->mBytesPerSample = sampleSize;
658f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mKind = kind;
659f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mNumSyncSamples = 0;
660f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mThumbnailSampleSize = 0;
661f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mThumbnailSampleIndex = -1;
662f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mMaxSampleSize = 0;
66332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    track->mAvgChunkSize = 1.0;
66432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    track->mFirstChunkSize = 0;
665f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
666f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
667f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
668f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
669f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) {
670f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mTracks.isEmpty()) {
671f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
672f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
673f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
674f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
675f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
676f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (track->mKind == Track::OTHER) {
677f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        // We don't support this content, but that's not a parsing error.
678f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return OK;
679f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
680f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
681f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    bool isVideo = (track->mKind == Track::VIDEO);
682f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
68332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    if ((isVideo && size < 40) || (!isVideo && size < 16)) {
68432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        // Expected a BITMAPINFO or WAVEFORMAT(EX) structure, respectively.
685f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
686f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
687f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
688f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
689f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
690f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
691f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < (ssize_t)size) {
692f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
693f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
694f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
695f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const uint8_t *data = buffer->data();
696f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
697f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (isVideo) {
698f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t width = U32LE_AT(&data[4]);
699f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t height = U32LE_AT(&data[8]);
700f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
701f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeyWidth, width);
702f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeyHeight, height);
703f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else {
704f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t format = U16LE_AT(data);
705c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
706f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (format == 0x55) {
707f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
708c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        } else {
7095ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Unsupported audio format = 0x%04x", format);
710f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
711f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
712f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t numChannels = U16LE_AT(&data[2]);
713f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t sampleRate = U32LE_AT(&data[4]);
714f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
715f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeyChannelCount, numChannels);
716f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeySampleRate, sampleRate);
717f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
718f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
719f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
720f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
721f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
722f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber// static
723f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberbool AVIExtractor::IsCorrectChunkType(
724f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) {
725f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t chunkBase = chunkType & 0xffff;
726f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
727f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    switch (kind) {
728f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case Track::VIDEO:
729f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
730f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (chunkBase != FOURCC(0, 0, 'd', 'c')
731f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    && chunkBase != FOURCC(0, 0, 'd', 'b')) {
732f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return false;
733f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
734f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
735f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
736f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
737f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case Track::AUDIO:
738f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
739f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (chunkBase != FOURCC(0, 0, 'w', 'b')) {
740f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return false;
741f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
742f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
743f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
744f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
745f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        default:
746f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
747f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
748f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
749f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (trackIndex < 0) {
750f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return true;
751f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
752f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
753f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t hi = chunkType >> 24;
754f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t lo = (chunkType >> 16) & 0xff;
755f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
756f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
757f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return false;
758f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
759f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
760f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (trackIndex != (10 * (hi - '0') + (lo - '0'))) {
761f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return false;
762f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
763f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
764f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return true;
765f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
766f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
767f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
768f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if ((size % 16) != 0) {
769f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
770f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
771f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
772f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
773f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
774f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
775f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < (ssize_t)size) {
776f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
777f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
778f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
779f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const uint8_t *data = buffer->data();
780f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
781f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (size > 0) {
782f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t chunkType = U32_AT(data);
783f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
784f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint8_t hi = chunkType >> 24;
785f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint8_t lo = (chunkType >> 16) & 0xff;
786f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
787f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
788f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
789f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
790f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
791f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t trackIndex = 10 * (hi - '0') + (lo - '0');
792f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
793f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (trackIndex >= mTracks.size()) {
794f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
795f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
796f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
797f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        Track *track = &mTracks.editItemAt(trackIndex);
798f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
799f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (!IsCorrectChunkType(-1, track->mKind, chunkType)) {
800f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return ERROR_MALFORMED;
801f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
802f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
803f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (track->mKind == Track::OTHER) {
804f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            data += 16;
805f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            size -= 16;
806f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            continue;
807f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
808f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
809f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t flags = U32LE_AT(&data[4]);
810f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t offset = U32LE_AT(&data[8]);
811f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        uint32_t chunkSize = U32LE_AT(&data[12]);
812f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
813f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (chunkSize > track->mMaxSampleSize) {
814f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            track->mMaxSampleSize = chunkSize;
815f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
816f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
817f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mSamples.push();
818f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
819f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        SampleInfo *info =
820f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            &track->mSamples.editItemAt(track->mSamples.size() - 1);
821f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
822f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        info->mOffset = offset;
823f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        info->mIsKey = (flags & 0x10) != 0;
824f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
825f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (info->mIsKey) {
826f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            static const size_t kMaxNumSyncSamplesToScan = 20;
827f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
828f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) {
829f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                if (chunkSize > track->mThumbnailSampleSize) {
830f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    track->mThumbnailSampleSize = chunkSize;
831f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
832f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                    track->mThumbnailSampleIndex =
833f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                        track->mSamples.size() - 1;
834f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                }
835f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
836f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
837f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            ++track->mNumSyncSamples;
838f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
839f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
840f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        data += 16;
841f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size -= 16;
842f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
843f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
844f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!mTracks.isEmpty()) {
845f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        off64_t offset;
846f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t size;
847f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        bool isKey;
8487de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        int64_t timeUs;
8497de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        status_t err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
850f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
851f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (err != OK) {
852f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            mOffsetsAreAbsolute = !mOffsetsAreAbsolute;
8537de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber            err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
854f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
855f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (err != OK) {
856f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return err;
857f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
858f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
859f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
8603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Chunk offsets are %s",
861f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber             mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative");
862f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
863f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
864f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
865f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        Track *track = &mTracks.editItemAt(i);
866f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
86732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        if (track->mBytesPerSample > 0) {
86832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            // Assume all chunks are roughly the same size for now.
86932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
87032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            // Compute the avg. size of the first 128 chunks (if there are
87132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            // that many), but exclude the size of the first one, since
87232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            // it may be an outlier.
87332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            size_t numSamplesToAverage = track->mSamples.size();
87432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            if (numSamplesToAverage > 256) {
87532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                numSamplesToAverage = 256;
87632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            }
87732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
87832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            double avgChunkSize = 0;
87932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            size_t j;
88032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            for (j = 0; j <= numSamplesToAverage; ++j) {
88132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                off64_t offset;
88232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                size_t size;
88332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                bool isKey;
88432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                int64_t dummy;
88532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
88632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                status_t err =
88732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                    getSampleInfo(
88832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                            i, j,
88932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                            &offset, &size, &isKey, &dummy);
89032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
89132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                if (err != OK) {
89232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                    return err;
89332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                }
89432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
89532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                if (j == 0) {
89632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                    track->mFirstChunkSize = size;
89732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                    continue;
89832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                }
89932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
90032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                avgChunkSize += size;
90132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            }
90232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
90332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            avgChunkSize /= numSamplesToAverage;
90432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
90532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            track->mAvgChunkSize = avgChunkSize;
90632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        }
90732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
9087de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        int64_t durationUs;
9097de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        CHECK_EQ((status_t)OK,
9107de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber                 getSampleTime(i, track->mSamples.size() - 1, &durationUs));
911f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
9123856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("track %d duration = %.2f secs", i, durationUs / 1E6);
913f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
914f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt64(kKeyDuration, durationUs);
915f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize);
916f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
917f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const char *tmp;
918f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp));
919f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
920f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        AString mime = tmp;
921f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
922c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        if (!strncasecmp("video/", mime.c_str(), 6)) {
923c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            if (track->mThumbnailSampleIndex >= 0) {
924c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                int64_t thumbnailTimeUs;
925c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                CHECK_EQ((status_t)OK,
926c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                         getSampleTime(i, track->mThumbnailSampleIndex,
927c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                                       &thumbnailTimeUs));
928f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
929c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
930c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            }
931c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
932c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            status_t err = OK;
933f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
934f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
935c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                err = addMPEG4CodecSpecificData(i);
936c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
937c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                err = addH264CodecSpecificData(i);
938c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            }
939f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
940c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            if (err != OK) {
941c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                return err;
942f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
943f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
944f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
945f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
946f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    mFoundIndex = true;
947f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
948f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
949f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
950f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
951f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatic size_t GetSizeWidth(size_t x) {
952f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t n = 1;
953f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (x > 127) {
954f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ++n;
955f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        x >>= 7;
956f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
957f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return n;
958f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
959f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
960f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatic uint8_t *EncodeSize(uint8_t *dst, size_t x) {
961f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (x > 127) {
962f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *dst++ = (x & 0x7f) | 0x80;
963f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        x >>= 7;
964f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
965f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = x;
966f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return dst;
967f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
968f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
969f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) {
970f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
971f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
972f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
973f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
974f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> csd = new ABuffer(len3);
975f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t *dst = csd->data();
976f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x03;
977f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    dst = EncodeSize(dst, len2 + 3);
978f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x00;  // ES_ID
979f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x00;
980f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
981f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
982f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x04;
983f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    dst = EncodeSize(dst, len1 + 13);
984f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x01;  // Video ISO/IEC 14496-2 Simple Profile
985f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    for (size_t i = 0; i < 12; ++i) {
986f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *dst++ = 0x00;
987f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
988f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
989f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *dst++ = 0x05;
990f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    dst = EncodeSize(dst, config->size());
991f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    memcpy(dst, config->data(), config->size());
992f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    dst += config->size();
993f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
994f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    // hexdump(csd->data(), csd->size());
995f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
996f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return csd;
997f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
998f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
999f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) {
1000f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    Track *track = &mTracks.editItemAt(trackIndex);
1001f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1002f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    off64_t offset;
1003f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t size;
1004f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    bool isKey;
10057de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    int64_t timeUs;
10067de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    status_t err =
10077de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        getSampleInfo(trackIndex, 0, &offset, &size, &isKey, &timeUs);
1008f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1009f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (err != OK) {
1010f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return err;
1011f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1012f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1013f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
1014f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
1015f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1016f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < (ssize_t)size) {
1017f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
1018f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1019f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1020f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    // Extract everything up to the first VOP start code from the first
1021f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    // frame's encoded data and use it to construct an ESDS with the
1022f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    // codec specific data.
1023f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1024f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    size_t i = 0;
1025f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    bool found = false;
1026f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (i + 3 < buffer->size()) {
1027f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) {
1028f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            found = true;
1029f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
1030f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
1031f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1032f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ++i;
1033f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1034f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1035f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!found) {
1036f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
1037f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1038f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1039f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    buffer->setRange(0, i);
1040f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1041f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer);
1042f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size());
1043f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1044f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
1045f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
1046f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1047c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huberstatus_t AVIExtractor::addH264CodecSpecificData(size_t trackIndex) {
1048c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    Track *track = &mTracks.editItemAt(trackIndex);
1049c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1050c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    off64_t offset;
1051c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    size_t size;
1052c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    bool isKey;
1053c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    int64_t timeUs;
1054c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1055c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    // Extract codec specific data from the first non-empty sample.
1056c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1057c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    size_t sampleIndex = 0;
1058c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    for (;;) {
1059c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        status_t err =
1060c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            getSampleInfo(
1061c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber                    trackIndex, sampleIndex, &offset, &size, &isKey, &timeUs);
1062c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1063c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        if (err != OK) {
1064c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            return err;
1065c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        }
1066c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1067c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        if (size > 0) {
1068c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber            break;
1069c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        }
1070c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1071c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        ++sampleIndex;
1072c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    }
1073c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1074c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
1075c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
1076c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1077c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    if (n < (ssize_t)size) {
1078c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        return n < 0 ? (status_t)n : ERROR_MALFORMED;
1079c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    }
1080c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1081c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    sp<MetaData> meta = MakeAVCCodecSpecificData(buffer);
1082c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1083c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    if (meta == NULL) {
108429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unable to extract AVC codec specific data");
1085c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber        return ERROR_MALFORMED;
1086c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    }
1087c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1088c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    int32_t width, height;
1089c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    CHECK(meta->findInt32(kKeyWidth, &width));
1090c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    CHECK(meta->findInt32(kKeyHeight, &height));
1091c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1092c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    uint32_t type;
1093c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    const void *csd;
1094c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    size_t csdSize;
1095c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize));
1096c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1097c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    track->mMeta->setInt32(kKeyWidth, width);
10984fe1c6c3988f79fd67c14a1f91e4b1df8a7e806fAndreas Huber    track->mMeta->setInt32(kKeyHeight, height);
1099c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    track->mMeta->setData(kKeyAVCC, type, csd, csdSize);
1100c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1101c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber    return OK;
1102c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber}
1103c639aad6d8894f57c02e620f52ccf49e51b64866Andreas Huber
1104f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::getSampleInfo(
1105f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t trackIndex, size_t sampleIndex,
11067de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        off64_t *offset, size_t *size, bool *isKey,
11077de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        int64_t *sampleTimeUs) {
1108f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (trackIndex >= mTracks.size()) {
1109f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return -ERANGE;
1110f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1111f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1112f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const Track &track = mTracks.itemAt(trackIndex);
1113f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1114f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (sampleIndex >= track.mSamples.size()) {
1115f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return -ERANGE;
1116f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1117f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1118f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const SampleInfo &info = track.mSamples.itemAt(sampleIndex);
1119f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1120f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!mOffsetsAreAbsolute) {
1121f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *offset = info.mOffset + mMovieOffset + 8;
1122f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else {
1123f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *offset = info.mOffset;
1124f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1125f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1126f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *size = 0;
1127f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1128f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint8_t tmp[8];
1129f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t n = mDataSource->readAt(*offset, tmp, 8);
1130f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1131f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (n < 8) {
1132f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
1133f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1134f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1135f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    uint32_t chunkType = U32_AT(tmp);
1136f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1137f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) {
1138f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return ERROR_MALFORMED;
1139f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1140f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1141f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *offset += 8;
1142f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *size = U32LE_AT(&tmp[4]);
1143f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1144f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    *isKey = info.mIsKey;
1145f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
114632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    if (track.mBytesPerSample > 0) {
114732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        size_t sampleStartInBytes;
114832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        if (sampleIndex == 0) {
114932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            sampleStartInBytes = 0;
115032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        } else {
115132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            sampleStartInBytes =
115232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                track.mFirstChunkSize + track.mAvgChunkSize * (sampleIndex - 1);
115332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        }
115432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
115532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        sampleIndex = sampleStartInBytes / track.mBytesPerSample;
115632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    }
115732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
11587de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale;
11597de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber
1160f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return OK;
1161f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
1162f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
11637de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huberstatus_t AVIExtractor::getSampleTime(
11647de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber        size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs) {
11657de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    off64_t offset;
11667de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    size_t size;
11677de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    bool isKey;
11687de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber    return getSampleInfo(
11697de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber            trackIndex, sampleIndex, &offset, &size, &isKey, sampleTimeUs);
11707de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber}
11717de73f4eb68f3aa478e19ba05a13bc84296f9894Andreas Huber
1172f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::getSampleIndexAtTime(
1173f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t trackIndex,
1174f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
1175f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        size_t *sampleIndex) const {
1176f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (trackIndex >= mTracks.size()) {
1177f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return -ERANGE;
1178f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1179f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1180f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    const Track &track = mTracks.itemAt(trackIndex);
1181f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
118232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    ssize_t closestSampleIndex;
118332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
118432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    if (track.mBytesPerSample > 0) {
118532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        size_t closestByteOffset =
118632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            (timeUs * track.mBytesPerSample)
118732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                / track.mRate * track.mScale / 1000000ll;
118832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber
118932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        if (closestByteOffset <= track.mFirstChunkSize) {
119032e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            closestSampleIndex = 0;
119132e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        } else {
119232e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber            closestSampleIndex =
119332e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                (closestByteOffset - track.mFirstChunkSize)
119432e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber                    / track.mAvgChunkSize;
119532e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        }
119632e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    } else {
119732e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        // Each chunk contains a single sample.
119832e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber        closestSampleIndex = timeUs / track.mRate * track.mScale / 1000000ll;
119932e1832dfac3a6bbcc5c0973ccd0e22de4d1a1acAndreas Huber    }
1200f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1201f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t numSamples = track.mSamples.size();
1202f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1203f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (closestSampleIndex < 0) {
1204f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        closestSampleIndex = 0;
1205f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    } else if (closestSampleIndex >= numSamples) {
1206f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        closestSampleIndex = numSamples - 1;
1207f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1208f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1209f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) {
1210f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        *sampleIndex = closestSampleIndex;
1211f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1212f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return OK;
1213f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1214f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1215f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t prevSyncSampleIndex = closestSampleIndex;
1216f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (prevSyncSampleIndex >= 0) {
1217f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const SampleInfo &info =
1218f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            track.mSamples.itemAt(prevSyncSampleIndex);
1219f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1220f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (info.mIsKey) {
1221f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
1222f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
1223f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1224f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        --prevSyncSampleIndex;
1225f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1226f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1227f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    ssize_t nextSyncSampleIndex = closestSampleIndex;
1228f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    while (nextSyncSampleIndex < numSamples) {
1229f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const SampleInfo &info =
1230f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            track.mSamples.itemAt(nextSyncSampleIndex);
1231f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1232f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        if (info.mIsKey) {
1233f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
1234f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
1235f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1236f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        ++nextSyncSampleIndex;
1237f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1238f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1239f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    switch (mode) {
1240f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC:
1241f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
1242f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            *sampleIndex = prevSyncSampleIndex;
1243f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1244f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR;
1245f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
1246f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1247f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case MediaSource::ReadOptions::SEEK_NEXT_SYNC:
1248f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
1249f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            *sampleIndex = nextSyncSampleIndex;
1250f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1251f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR;
1252f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
1253f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1254f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC:
1255f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        {
1256f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) {
1257f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return UNKNOWN_ERROR;
1258f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
1259f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1260f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (prevSyncSampleIndex < 0) {
1261f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                *sampleIndex = nextSyncSampleIndex;
1262f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return OK;
1263f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
1264f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1265f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            if (nextSyncSampleIndex >= numSamples) {
1266f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                *sampleIndex = prevSyncSampleIndex;
1267f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                return OK;
1268f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            }
1269f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1270f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            size_t dist1 = closestSampleIndex - prevSyncSampleIndex;
1271f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            size_t dist2 = nextSyncSampleIndex - closestSampleIndex;
1272f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1273f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            *sampleIndex =
1274f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber                (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex;
1275f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1276f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            return OK;
1277f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        }
1278f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1279f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        default:
1280f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            TRESPASS();
1281f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber            break;
1282f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1283f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
1284f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1285f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberbool SniffAVI(
1286f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
1287f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        sp<AMessage> *) {
1288f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    char tmp[12];
1289f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (source->readAt(0, tmp, 12) < 12) {
1290f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return false;
1291f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1292f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1293f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) {
1294f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI);
1295c6c4572cd35f739bfac2aa439b3664032e03dcd8Andreas Huber
1296c6c4572cd35f739bfac2aa439b3664032e03dcd8Andreas Huber        // Just a tad over the mp3 extractor's confidence, since
1297c6c4572cd35f739bfac2aa439b3664032e03dcd8Andreas Huber        // these .avi files may contain .mp3 content that otherwise would
1298c6c4572cd35f739bfac2aa439b3664032e03dcd8Andreas Huber        // mistakenly lead to us identifying the entire file as a .mp3 file.
1299c6c4572cd35f739bfac2aa439b3664032e03dcd8Andreas Huber        *confidence = 0.21;
1300f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1301f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber        return true;
1302f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    }
1303f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1304f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber    return false;
1305f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}
1306f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber
1307f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}  // namespace android
1308