MatroskaExtractor.cpp revision 5279d1d8c19e5fdbb177805db0da8e8aadac3079
1093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber/*
2093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * Copyright (C) 2010 The Android Open Source Project
3093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *
4093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * you may not use this file except in compliance with the License.
6093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * You may obtain a copy of the License at
7093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *
8093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *
10093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * Unless required by applicable law or agreed to in writing, software
11093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * See the License for the specific language governing permissions and
14093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * limitations under the License.
15093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber */
16093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
17093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber//#define LOG_NDEBUG 0
18093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#define LOG_TAG "MatroskaExtractor"
19093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <utils/Log.h>
20093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
21093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include "MatroskaExtractor.h"
22093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
23093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include "mkvparser.hpp"
24093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
25093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/DataSource.h>
26093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaBuffer.h>
27093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaDebug.h>
28093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaDefs.h>
29093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaErrors.h>
30093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaSource.h>
31093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MetaData.h>
32093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <utils/String8.h>
33093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
34093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubernamespace android {
35093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
36093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstruct DataSourceReader : public mkvparser::IMkvReader {
37093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    DataSourceReader(const sp<DataSource> &source)
38093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        : mSource(source) {
39093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
40093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
41093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    virtual int Read(long long position, long length, unsigned char* buffer) {
42093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        CHECK(position >= 0);
43093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        CHECK(length >= 0);
44093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
45093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        if (length == 0) {
46093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            return 0;
47093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
48093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
49093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        ssize_t n = mSource->readAt(position, buffer, length);
50093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
51093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        if (n <= 0) {
52093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            return -1;
53093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
54093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
55093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return 0;
56093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
57093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
58093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    virtual int Length(long long* total, long long* available) {
59093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        off_t size;
60093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        if (mSource->getSize(&size) != OK) {
61093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            return -1;
62093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
63093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
64093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        if (total) {
65093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            *total = size;
66093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
67093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
68093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        if (available) {
69093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            *available = size;
70093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
71093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
72093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return 0;
73093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
74093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
75093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberprivate:
76093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    sp<DataSource> mSource;
77093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
78093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    DataSourceReader(const DataSourceReader &);
79093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    DataSourceReader &operator=(const DataSourceReader &);
80093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber};
81093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
82093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber////////////////////////////////////////////////////////////////////////////////
83093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
84093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <ctype.h>
85093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstatic void hexdump(const void *_data, size_t size) {
86093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    const uint8_t *data = (const uint8_t *)_data;
87093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    size_t offset = 0;
88093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    while (offset < size) {
89093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        printf("0x%04x  ", offset);
90093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
91093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        size_t n = size - offset;
92093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        if (n > 16) {
93093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            n = 16;
94093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
95093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
96093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        for (size_t i = 0; i < 16; ++i) {
97093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            if (i == 8) {
98093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                printf(" ");
99093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            }
100093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
101093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            if (offset + i < size) {
102093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                printf("%02x ", data[offset + i]);
103093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            } else {
104093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                printf("   ");
105093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            }
106093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
107093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
108093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        printf(" ");
109093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
110093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        for (size_t i = 0; i < n; ++i) {
111093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            if (isprint(data[offset + i])) {
112093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                printf("%c", data[offset + i]);
113093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            } else {
114093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                printf(".");
115093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            }
116093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
117093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
118093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        printf("\n");
119093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
120093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        offset += 16;
121093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
122093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
123093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1245279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberstruct BlockIterator {
1255279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    BlockIterator(mkvparser::Segment *segment, unsigned long trackNum);
1265279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
1275279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    bool eos() const;
1285279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
1295279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    void advance();
1305279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    void reset();
1315279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    void seek(int64_t seekTimeUs);
1325279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
1335279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    const mkvparser::Block *block() const;
1345279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    int64_t blockTimeUs() const;
1355279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
1365279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberprivate:
1375279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    mkvparser::Segment *mSegment;
1385279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    unsigned long mTrackNum;
1395279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
1405279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    mkvparser::Cluster *mCluster;
1415279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    const mkvparser::BlockEntry *mBlockEntry;
1425279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
1435279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    BlockIterator(const BlockIterator &);
1445279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    BlockIterator &operator=(const BlockIterator &);
1455279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber};
1465279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
147093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstruct MatroskaSource : public MediaSource {
148093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    MatroskaSource(
149093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            const sp<MatroskaExtractor> &extractor, size_t index);
150093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
151093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    virtual status_t start(MetaData *params);
152093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    virtual status_t stop();
153093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
154093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    virtual sp<MetaData> getFormat();
155093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
156093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    virtual status_t read(
157093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            MediaBuffer **buffer, const ReadOptions *options);
158093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
159093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberprivate:
160093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    enum Type {
161093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        AVC,
162093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        AAC,
163093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        OTHER
164093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    };
165093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
166093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    sp<MatroskaExtractor> mExtractor;
167093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    size_t mTrackIndex;
168093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    Type mType;
1695279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    BlockIterator mBlockIter;
170093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
171093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    status_t advance();
172093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
173093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    MatroskaSource(const MatroskaSource &);
174093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    MatroskaSource &operator=(const MatroskaSource &);
175093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber};
176093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
177093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaSource::MatroskaSource(
178093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        const sp<MatroskaExtractor> &extractor, size_t index)
179093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    : mExtractor(extractor),
180093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber      mTrackIndex(index),
181093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber      mType(OTHER),
1825279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber      mBlockIter(mExtractor->mSegment,
1835279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber                 mExtractor->mTracks.itemAt(index).mTrackNum) {
184093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    const char *mime;
185093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    CHECK(mExtractor->mTracks.itemAt(index).mMeta->
186093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            findCString(kKeyMIMEType, &mime));
187093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
188093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
189093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        mType = AVC;
190093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
191093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        mType = AAC;
192093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
193093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
194093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
195093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstatus_t MatroskaSource::start(MetaData *params) {
1965279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    mBlockIter.reset();
197093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
198093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return OK;
199093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
200093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
201093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstatus_t MatroskaSource::stop() {
202093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return OK;
203093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
204093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
205093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaSource::getFormat() {
206093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
207093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
208093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
2095279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber////////////////////////////////////////////////////////////////////////////////
2105279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
2115279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas HuberBlockIterator::BlockIterator(
2125279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        mkvparser::Segment *segment, unsigned long trackNum)
2135279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    : mSegment(segment),
2145279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber      mTrackNum(trackNum),
2155279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber      mCluster(NULL),
2165279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber      mBlockEntry(NULL) {
2175279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    reset();
2185279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}
2195279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
2205279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberbool BlockIterator::eos() const {
2215279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    return mCluster == NULL || mCluster->EOS();
2225279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}
2235279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
2245279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::advance() {
2255279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    while (!eos()) {
2265279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        if (mBlockEntry != NULL) {
2275279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber            mBlockEntry = mCluster->GetNext(mBlockEntry);
2285279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        } else if (mCluster != NULL) {
2295279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber            mCluster = mSegment->GetNext(mCluster);
2305279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
2315279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber            if (eos()) {
2325279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber                break;
233093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            }
2345279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
235093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            mBlockEntry = mCluster->GetFirst();
236093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
237093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
2385279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        if (mBlockEntry != NULL
2395279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber                && mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
2405279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber            break;
241093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
2425279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    }
2435279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}
2445279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
2455279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::reset() {
2465279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    mCluster = mSegment->GetFirst();
2475279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    mBlockEntry = mCluster->GetFirst();
248093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
2495279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    while (!eos() && block()->GetTrackNumber() != mTrackNum) {
2505279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        advance();
251093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
2525279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}
253093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
2545279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::seek(int64_t seekTimeUs) {
2555279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    mCluster = mSegment->GetCluster(seekTimeUs * 1000ll);
2565279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    mBlockEntry = mCluster != NULL ? mCluster->GetFirst() : NULL;
2575279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
2585279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    while (!eos() && block()->GetTrackNumber() != mTrackNum) {
2595279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        advance();
2605279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    }
2615279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
2625279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    while (!eos() && !mBlockEntry->GetBlock()->IsKey()) {
2635279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        advance();
2645279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    }
265093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
266093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
2675279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberconst mkvparser::Block *BlockIterator::block() const {
2685279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    CHECK(!eos());
2695279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
2705279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    return mBlockEntry->GetBlock();
2715279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}
2725279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
2735279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberint64_t BlockIterator::blockTimeUs() const {
2745279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
2755279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}
2765279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
2775279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber////////////////////////////////////////////////////////////////////////////////
2785279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
279093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstatus_t MatroskaSource::read(
280093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        MediaBuffer **out, const ReadOptions *options) {
281093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    *out = NULL;
282093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
283093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    int64_t seekTimeUs;
284093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (options && options->getSeekTo(&seekTimeUs)) {
2855279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        mBlockIter.seek(seekTimeUs);
286093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
287093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
2885279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    if (mBlockIter.eos()) {
289093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return ERROR_END_OF_STREAM;
290093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
291093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
2925279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    const mkvparser::Block *block = mBlockIter.block();
293093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    size_t size = block->GetSize();
2945279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    int64_t timeUs = mBlockIter.blockTimeUs();
295093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
296093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    MediaBuffer *buffer = new MediaBuffer(size + 2);
2975279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    buffer->meta_data()->setInt64(kKeyTime, timeUs);
298093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
299093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    long res = block->Read(
300093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            mExtractor->mReader, (unsigned char *)buffer->data() + 2);
301093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
302093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (res != 0) {
303093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return ERROR_END_OF_STREAM;
304093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
305093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
306093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    buffer->set_range(2, size);
307093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
308093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (mType == AVC) {
309093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        CHECK(size >= 2);
310093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
311093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        uint8_t *data = (uint8_t *)buffer->data();
312093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
313093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        unsigned NALsize = data[2] << 8 | data[3];
314093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        CHECK_EQ(size, NALsize + 2);
315093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
316093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        memcpy(data, "\x00\x00\x00\x01", 4);
317093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        buffer->set_range(0, size + 2);
318093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    } else if (mType == AAC) {
319093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        // There's strange junk at the beginning...
320093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
321093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        const uint8_t *data = (const uint8_t *)buffer->data() + 2;
322093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        size_t offset = 0;
323093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        while (offset < size && data[offset] != 0x21) {
324093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            ++offset;
325093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
326093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        buffer->set_range(2 + offset, size - offset);
327093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
328093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
329093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    *out = buffer;
330093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
331093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#if 0
332093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    hexdump((const uint8_t *)buffer->data() + buffer->range_offset(),
333093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            buffer->range_length());
334093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#endif
335093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
3365279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    mBlockIter.advance();
337093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
338093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return OK;
339093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
340093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
341093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber////////////////////////////////////////////////////////////////////////////////
342093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
343093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
344093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    : mDataSource(source),
345093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber      mReader(new DataSourceReader(mDataSource)),
3465279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber      mSegment(NULL),
3475279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber      mExtractedThumbnails(false) {
348093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    mkvparser::EBMLHeader ebmlHeader;
349093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    long long pos;
350093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (ebmlHeader.Parse(mReader, pos) < 0) {
351093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return;
352093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
353093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
354093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    long long ret =
355093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        mkvparser::Segment::CreateInstance(mReader, pos, mSegment);
356093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
357093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (ret) {
358093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        CHECK(mSegment == NULL);
359093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return;
360093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
361093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
362093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    ret = mSegment->Load();
363093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
364093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (ret < 0) {
365093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        delete mSegment;
366093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        mSegment = NULL;
367093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return;
368093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
369093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
370093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    addTracks();
371093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
372093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
373093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::~MatroskaExtractor() {
374093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    delete mSegment;
375093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    mSegment = NULL;
376093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
377093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    delete mReader;
378093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    mReader = NULL;
379093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
380093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
381093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersize_t MatroskaExtractor::countTracks() {
382093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return mTracks.size();
383093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
384093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
385093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MediaSource> MatroskaExtractor::getTrack(size_t index) {
386093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (index >= mTracks.size()) {
387093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return NULL;
388093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
389093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
390093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return new MatroskaSource(this, index);
391093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
392093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
393093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaExtractor::getTrackMetaData(
394093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        size_t index, uint32_t flags) {
395093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (index >= mTracks.size()) {
396093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return NULL;
397093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
398093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
3995279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails) {
4005279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        findThumbnails();
4015279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        mExtractedThumbnails = true;
4025279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    }
4035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
404093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return mTracks.itemAt(index).mMeta;
405093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
406093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
407093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstatic void addESDSFromAudioSpecificInfo(
408093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        const sp<MetaData> &meta, const void *asi, size_t asiSize) {
409093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    static const uint8_t kStaticESDS[] = {
410093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        0x03, 22,
411093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        0x00, 0x00,     // ES_ID
412093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        0x00,           // streamDependenceFlag, URL_Flag, OCRstreamFlag
413093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
414093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        0x04, 17,
415093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        0x40,                       // Audio ISO/IEC 14496-3
416093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        0x00, 0x00, 0x00, 0x00,
417093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        0x00, 0x00, 0x00, 0x00,
418093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        0x00, 0x00, 0x00, 0x00,
419093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
420093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        0x05,
421093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        // AudioSpecificInfo (with size prefix) follows
422093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    };
423093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
424093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    CHECK(asiSize < 128);
425093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    size_t esdsSize = sizeof(kStaticESDS) + asiSize + 1;
426093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    uint8_t *esds = new uint8_t[esdsSize];
427093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    memcpy(esds, kStaticESDS, sizeof(kStaticESDS));
428093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    uint8_t *ptr = esds + sizeof(kStaticESDS);
429093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    *ptr++ = asiSize;
430093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    memcpy(ptr, asi, asiSize);
431093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
432093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    meta->setData(kKeyESDS, 0, esds, esdsSize);
433093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
434093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    delete[] esds;
435093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    esds = NULL;
436093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
437093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
438093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubervoid addVorbisCodecInfo(
439093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        const sp<MetaData> &meta,
440093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        const void *_codecPrivate, size_t codecPrivateSize) {
441093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    // printf("vorbis private data follows:\n");
442093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    // hexdump(_codecPrivate, codecPrivateSize);
443093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
444093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    CHECK(codecPrivateSize >= 3);
445093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
446093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate;
447093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    CHECK(codecPrivate[0] == 0x02);
448093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
449093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    size_t len1 = codecPrivate[1];
450093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    size_t len2 = codecPrivate[2];
451093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
452093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    CHECK(codecPrivateSize > 3 + len1 + len2);
453093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
454093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    CHECK(codecPrivate[3] == 0x01);
455093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    meta->setData(kKeyVorbisInfo, 0, &codecPrivate[3], len1);
456093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
457093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    CHECK(codecPrivate[len1 + 3] == 0x03);
458093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
459093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    CHECK(codecPrivate[len1 + len2 + 3] == 0x05);
460093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    meta->setData(
461093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            kKeyVorbisBooks, 0, &codecPrivate[len1 + len2 + 3],
462093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            codecPrivateSize - len1 - len2 - 3);
463093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
464093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
465093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubervoid MatroskaExtractor::addTracks() {
466093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    const mkvparser::Tracks *tracks = mSegment->GetTracks();
467093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
468093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    for (size_t index = 0; index < tracks->GetTracksCount(); ++index) {
469093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        const mkvparser::Track *track = tracks->GetTrackByIndex(index);
470093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
471093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        const char *const codecID = track->GetCodecId();
472093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        LOGV("codec id = %s", codecID);
473093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        LOGV("codec name = %s", track->GetCodecNameAsUTF8());
474093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
475093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        size_t codecPrivateSize;
476093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        const unsigned char *codecPrivate =
477093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            track->GetCodecPrivate(&codecPrivateSize);
478093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
479093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
480093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
481093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        sp<MetaData> meta = new MetaData;
482093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
483093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        switch (track->GetType()) {
484093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            case VIDEO_TRACK:
485093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            {
486093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                const mkvparser::VideoTrack *vtrack =
487093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    static_cast<const mkvparser::VideoTrack *>(track);
488093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
489093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
490093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
491093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
492093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                } else if (!strcmp("V_VP8", codecID)) {
493093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VPX);
494093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                } else {
495093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    continue;
496093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                }
497093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
498093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                meta->setInt32(kKeyWidth, vtrack->GetWidth());
499093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                meta->setInt32(kKeyHeight, vtrack->GetHeight());
500093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                break;
501093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            }
502093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
503093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            case AUDIO_TRACK:
504093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            {
505093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                const mkvparser::AudioTrack *atrack =
506093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    static_cast<const mkvparser::AudioTrack *>(track);
507093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
508093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                if (!strcmp("A_AAC", codecID)) {
509093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
510093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    CHECK(codecPrivateSize >= 2);
511093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
512093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    addESDSFromAudioSpecificInfo(
513093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                            meta, codecPrivate, codecPrivateSize);
514093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                } else if (!strcmp("A_VORBIS", codecID)) {
515093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
516093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
517093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    addVorbisCodecInfo(meta, codecPrivate, codecPrivateSize);
518093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                } else {
519093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    continue;
520093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                }
521093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
522093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                meta->setInt32(kKeySampleRate, atrack->GetSamplingRate());
523093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                meta->setInt32(kKeyChannelCount, atrack->GetChannels());
524093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                break;
525093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            }
526093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
527093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            default:
528093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                continue;
529093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
530093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
531093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        long long durationNs = mSegment->GetDuration();
532093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        meta->setInt64(kKeyDuration, (durationNs + 500) / 1000);
533093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
534093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        mTracks.push();
535093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1);
536093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        trackInfo->mTrackNum = track->GetNumber();
537093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        trackInfo->mMeta = meta;
538093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
539093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
540093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
5415279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid MatroskaExtractor::findThumbnails() {
5425279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
5435279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        TrackInfo *info = &mTracks.editItemAt(i);
5445279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
5455279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        const char *mime;
5465279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        CHECK(info->mMeta->findCString(kKeyMIMEType, &mime));
5475279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
5485279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        if (strncasecmp(mime, "video/", 6)) {
5495279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber            continue;
5505279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        }
5515279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
5525279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        BlockIterator iter(mSegment, info->mTrackNum);
5535279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        int32_t i = 0;
5545279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        int64_t thumbnailTimeUs = 0;
5555279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        size_t maxBlockSize = 0;
5565279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        while (!iter.eos() && i < 20) {
5575279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber            if (iter.block()->IsKey()) {
5585279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber                ++i;
5595279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
5605279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber                size_t blockSize = iter.block()->GetSize();
5615279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber                if (blockSize > maxBlockSize) {
5625279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber                    maxBlockSize = blockSize;
5635279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber                    thumbnailTimeUs = iter.blockTimeUs();
5645279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber                }
5655279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber            }
5665279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber            iter.advance();
5675279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        }
5685279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
5695279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    }
5705279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}
5715279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
572093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaExtractor::getMetaData() {
573093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    sp<MetaData> meta = new MetaData;
574093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MATROSKA);
575093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
576093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return meta;
577093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
578093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
579093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberbool SniffMatroska(
580093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
581093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    DataSourceReader reader(source);
582093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    mkvparser::EBMLHeader ebmlHeader;
583093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    long long pos;
584093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (ebmlHeader.Parse(&reader, pos) < 0) {
585093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return false;
586093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
587093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
588093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA);
589093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    *confidence = 0.6;
590093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
591093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return true;
592093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
593093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
594093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}  // namespace android
595