MatroskaExtractor.cpp revision 84333e0475bc911adc16417f4ca327c975cf6c36
1e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/*
2e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * Copyright (C) 2010 The Android Open Source Project
3e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard *
4e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * Licensed under the Apache License, Version 2.0 (the "License");
5e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * you may not use this file except in compliance with the License.
6e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * You may obtain a copy of the License at
7e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard *
8e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard *      http://www.apache.org/licenses/LICENSE-2.0
9e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard *
10e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * Unless required by applicable law or agreed to in writing, software
11e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * distributed under the License is distributed on an "AS IS" BASIS,
12e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * See the License for the specific language governing permissions and
14e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * limitations under the License.
15e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard */
16e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
17e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard//#define LOG_NDEBUG 0
18e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define LOG_TAG "MatroskaExtractor"
19e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <utils/Log.h>
20e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
21956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "MatroskaExtractor.h"
22956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
23e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "mkvparser.hpp"
24956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
25956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include <media/stagefright/foundation/ADebug.h>
26956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include <media/stagefright/foundation/hexdump.h>
27e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <media/stagefright/DataSource.h>
28e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <media/stagefright/MediaBuffer.h>
29e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <media/stagefright/MediaDefs.h>
30e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <media/stagefright/MediaErrors.h>
31e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <media/stagefright/MediaSource.h>
32e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <media/stagefright/MetaData.h>
33e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <media/stagefright/Utils.h>
34b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard#include <utils/String8.h>
35956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
36956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongnamespace android {
37956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
38956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstruct DataSourceReader : public mkvparser::IMkvReader {
39956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    DataSourceReader(const sp<DataSource> &source)
40956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        : mSource(source) {
41956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
42e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
43e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    virtual int Read(long long position, long length, unsigned char* buffer) {
44e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        CHECK(position >= 0);
45e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        CHECK(length >= 0);
46e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
47e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        if (length == 0) {
48e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            return 0;
49e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        }
50b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
51e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        ssize_t n = mSource->readAt(position, buffer, length);
52e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
53e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        if (n <= 0) {
54b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard            return -1;
55b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        }
56b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
57b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        return 0;
58e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    }
59e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
60e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    virtual int Length(long long* total, long long* available) {
61b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        off64_t size;
62e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        if (mSource->getSize(&size) != OK) {
63e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            *total = -1;
64e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            *available = (long long)((1ull << 63) - 1);
65e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
66956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            return 0;
67956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
68956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
69956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if (total) {
70956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            *total = size;
71956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
72e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
73e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        if (available) {
74e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            *available = size;
75e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        }
76e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
77b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        return 0;
78b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    }
79e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
80e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardprivate:
81e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    sp<DataSource> mSource;
82e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
83e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    DataSourceReader(const DataSourceReader &);
84e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    DataSourceReader &operator=(const DataSourceReader &);
85e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard};
86e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
87e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard////////////////////////////////////////////////////////////////////////////////
88e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
89e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstruct BlockIterator {
90e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum);
91e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
92e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    bool eos() const;
93e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
94e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    void advance();
95e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    void reset();
96e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
97e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    void seek(
98e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            int64_t seekTimeUs, bool isAudio,
99e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            int64_t *actualFrameTimeUs);
100e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
101e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    const mkvparser::Block *block() const;
102956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t blockTimeUs() const;
103956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
104956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongprivate:
105956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    MatroskaExtractor *mExtractor;
106956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    unsigned long mTrackNum;
107e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
108e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    const mkvparser::Cluster *mCluster;
109e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    const mkvparser::BlockEntry *mBlockEntry;
110e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    long mBlockEntryIndex;
111e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
112e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    void advance_l();
113e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
114e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    BlockIterator(const BlockIterator &);
115e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    BlockIterator &operator=(const BlockIterator &);
116b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard};
117e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
118e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstruct MatroskaSource : public MediaSource {
119e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    MatroskaSource(
120e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            const sp<MatroskaExtractor> &extractor, size_t index);
121e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
122e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    virtual status_t start(MetaData *params);
123e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    virtual status_t stop();
124e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
125e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    virtual sp<MetaData> getFormat();
126e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
127e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    virtual status_t read(
128e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            MediaBuffer **buffer, const ReadOptions *options);
129e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
130e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardprotected:
131e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    virtual ~MatroskaSource();
132e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
133e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardprivate:
134e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    enum Type {
135e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        AVC,
136e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        AAC,
137e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        OTHER
138e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    };
139e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
140e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    sp<MatroskaExtractor> mExtractor;
141e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    size_t mTrackIndex;
142e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    Type mType;
143e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    bool mIsAudio;
144e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    BlockIterator mBlockIter;
145e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    size_t mNALSizeLen;  // for type AVC
146e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
147e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    List<MediaBuffer *> mPendingFrames;
148e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
149e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    status_t advance();
150e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
151e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    status_t readBlock();
152e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    void clearPendingFrames();
153e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
154e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    MatroskaSource(const MatroskaSource &);
155e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    MatroskaSource &operator=(const MatroskaSource &);
156e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard};
157e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
158e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardMatroskaSource::MatroskaSource(
159e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        const sp<MatroskaExtractor> &extractor, size_t index)
160e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    : mExtractor(extractor),
161e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      mTrackIndex(index),
162e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      mType(OTHER),
163e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      mIsAudio(false),
164e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      mBlockIter(mExtractor.get(),
165e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                 mExtractor->mTracks.itemAt(index).mTrackNum),
166e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      mNALSizeLen(0) {
167e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta;
168e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
169e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    const char *mime;
170e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    CHECK(meta->findCString(kKeyMIMEType, &mime));
171e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
172e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    mIsAudio = !strncasecmp("audio/", mime, 6);
173e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
174e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
175e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        mType = AVC;
176e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
177e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        uint32_t dummy;
178e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        const uint8_t *avcc;
179e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        size_t avccSize;
180e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        CHECK(meta->findData(
181e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                    kKeyAVCC, &dummy, (const void **)&avcc, &avccSize));
182956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
183956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        CHECK_GE(avccSize, 5u);
184956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
185956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        mNALSizeLen = 1 + (avcc[4] & 3);
186956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        ALOGV("mNALSizeLen = %d", mNALSizeLen);
187e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
188e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        mType = AAC;
189e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    }
190e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
191e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
192e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardMatroskaSource::~MatroskaSource() {
193e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    clearPendingFrames();
194e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
195e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
196e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatus_t MatroskaSource::start(MetaData * /* params */) {
197b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    mBlockIter.reset();
198e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
199e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    return OK;
200e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
201e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
202b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgardstatus_t MatroskaSource::stop() {
203e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    clearPendingFrames();
204e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
205e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    return OK;
206b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard}
207e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
208e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardsp<MetaData> MatroskaSource::getFormat() {
209e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    return mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
210e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
211b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
212e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard////////////////////////////////////////////////////////////////////////////////
213b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
214e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardBlockIterator::BlockIterator(
215e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        MatroskaExtractor *extractor, unsigned long trackNum)
216e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    : mExtractor(extractor),
217e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      mTrackNum(trackNum),
218e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      mCluster(NULL),
219e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      mBlockEntry(NULL),
220e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard      mBlockEntryIndex(0) {
221e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    reset();
222e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
223e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
224e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardbool BlockIterator::eos() const {
225e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    return mCluster == NULL || mCluster->EOS();
226b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard}
227e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
228e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid BlockIterator::advance() {
229e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    Mutex::Autolock autoLock(mExtractor->mLock);
230e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    advance_l();
231e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
232e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
233e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid BlockIterator::advance_l() {
234b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    for (;;) {
235e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry);
236e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        ALOGV("GetEntry returned %ld", res);
237e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
238e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        long long pos;
239e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        long len;
240e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        if (res < 0) {
241e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            // Need to parse this cluster some more
242e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
243e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL);
244e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
245e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            res = mCluster->Parse(pos, len);
246e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            ALOGV("Parse returned %ld", res);
247e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
248e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            if (res < 0) {
249e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                // I/O error
250e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
251e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                ALOGE("Cluster::Parse returned result %ld", res);
252e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
253e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                mCluster = NULL;
254e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                break;
255e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            }
256e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
257e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            continue;
258e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        } else if (res == 0) {
259e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            // We're done with this cluster
260e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
261e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            const mkvparser::Cluster *nextCluster;
262e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            res = mExtractor->mSegment->ParseNext(
263e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                    mCluster, nextCluster, pos, len);
264e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            ALOGV("ParseNext returned %ld", res);
265e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
266e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            if (res != 0) {
267e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                // EOF or error
268e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
269e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                mCluster = NULL;
270e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                break;
271e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            }
272e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
273956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            CHECK_EQ(res, 0);
274956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            CHECK(nextCluster != NULL);
275956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            CHECK(!nextCluster->EOS());
276956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
277956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            mCluster = nextCluster;
278e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
279e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            res = mCluster->Parse(pos, len);
280e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            ALOGV("Parse (2) returned %ld", res);
281e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            CHECK_GE(res, 0);
282e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
283e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            mBlockEntryIndex = 0;
284e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            continue;
285b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        }
286e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
287e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        CHECK(mBlockEntry != NULL);
288e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        CHECK(mBlockEntry->GetBlock() != NULL);
289e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        ++mBlockEntryIndex;
290b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
291b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
292b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard            break;
293b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        }
294e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    }
295e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
296e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
297e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid BlockIterator::reset() {
298e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    Mutex::Autolock autoLock(mExtractor->mLock);
299b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
300e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    mCluster = mExtractor->mSegment->GetFirst();
301b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    mBlockEntry = NULL;
302b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    mBlockEntryIndex = 0;
303b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
304e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    do {
305e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        advance_l();
306e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    } while (!eos() && block()->GetTrackNumber() != mTrackNum);
307e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
308956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
309956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid BlockIterator::seek(
310956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        int64_t seekTimeUs, bool isAudio,
311956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        int64_t *actualFrameTimeUs) {
312956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    Mutex::Autolock autoLock(mExtractor->mLock);
313e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
314e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    *actualFrameTimeUs = -1ll;
315e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
316e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    const int64_t seekTimeNs = seekTimeUs * 1000ll;
317e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
318e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    mkvparser::Segment* const pSegment = mExtractor->mSegment;
319e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
320e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    // Special case the 0 seek to avoid loading Cues when the application
321e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    // extraneously seeks to 0 before playing.
322b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    if (seekTimeNs <= 0) {
323e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        ALOGV("Seek to beginning: %lld", seekTimeUs);
324e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        mCluster = pSegment->GetFirst();
325b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        mBlockEntryIndex = 0;
326b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        do {
327b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard            advance_l();
328e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        } while (!eos() && block()->GetTrackNumber() != mTrackNum);
329e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        return;
330e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    }
331e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
332e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    ALOGV("Seeking to: %lld", seekTimeUs);
333e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
334e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    // If the Cues have not been located then find them.
335e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    const mkvparser::Cues* pCues = pSegment->GetCues();
336b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    const mkvparser::SeekHead* pSH = pSegment->GetSeekHead();
337b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    if (!pCues && pSH) {
338e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        const size_t count = pSH->GetCount();
339b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        const mkvparser::SeekHead::Entry* pEntry;
340e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        ALOGV("No Cues yet");
341e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
3428a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo        for (size_t index = 0; index < count; index++) {
3438a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo            pEntry = pSH->GetEntry(index);
3448a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo
3458a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo            if (pEntry->id == 0x0C53BB6B) { // Cues ID
3468a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo                long len; long long pos;
3478a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo                pSegment->ParseCues(pEntry->pos, pos, len);
348e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                pCues = pSegment->GetCues();
349e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                ALOGV("Cues found");
350e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard                break;
351956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            }
352956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
353956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
354956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if (!pCues) {
355956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            ALOGE("No Cues in file");
356e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            return;
357e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        }
358e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    }
359e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    else if (!pSH) {
360e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        ALOGE("No SeekHead");
361e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        return;
362b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    }
363e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
364e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    const mkvparser::CuePoint* pCP;
365b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    while (!pCues->DoneParsing()) {
366e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        pCues->LoadCuePoint();
367e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        pCP = pCues->GetLast();
368e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
369956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if (pCP->GetTime(pSegment) >= seekTimeNs) {
370956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            ALOGV("Parsed past relevant Cue");
371956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            break;
372b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        }
373956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
374e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
375e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    // The Cue index is built around video keyframes
376e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    mkvparser::Tracks const *pTracks = pSegment->GetTracks();
377e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    const mkvparser::Track *pTrack = NULL;
378e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    for (size_t index = 0; index < pTracks->GetTracksCount(); ++index) {
379e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        pTrack = pTracks->GetTrackByIndex(index);
380b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        if (pTrack && pTrack->GetType() == 1) { // VIDEO_TRACK
381b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard            ALOGV("Video track located at %d", index);
382e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard            break;
383b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        }
384e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    }
385956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
386956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    // Always *search* based on the video track, but finalize based on mTrackNum
387956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    const mkvparser::CuePoint::TrackPosition* pTP;
388956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (pTrack && pTrack->GetType() == 1) {
389956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        pCues->Find(seekTimeNs, pTrack, pCP, pTP);
390956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    } else {
391b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        ALOGE("Did not locate the video track for seeking");
392956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        return;
393956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
394956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
395956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos);
396956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
397956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    CHECK(mCluster);
398956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    CHECK(!mCluster->EOS());
399956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
400956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    // mBlockEntryIndex starts at 0 but m_block starts at 1
401956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    CHECK_GT(pTP->m_block, 0);
402956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mBlockEntryIndex = pTP->m_block - 1;
403956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
404956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for (;;) {
405956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        advance_l();
406956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
407956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if (eos()) break;
408956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
409956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if (isAudio || block()->IsKey()) {
410956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            // Accept the first key frame
411956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            *actualFrameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL;
412956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            ALOGV("Requested seek point: %lld actual: %lld",
413956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                  seekTimeUs, *actualFrameTimeUs);
414956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            break;
415956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
416956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
417956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
418b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
419956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongconst mkvparser::Block *BlockIterator::block() const {
420956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    CHECK(!eos());
421956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
422956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    return mBlockEntry->GetBlock();
423956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
424956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
425956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongint64_t BlockIterator::blockTimeUs() const {
426956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
427956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
428e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
429e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard////////////////////////////////////////////////////////////////////////////////
430e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
431956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic unsigned U24_AT(const uint8_t *ptr) {
432956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
433956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
434956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
435956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic size_t clz(uint8_t x) {
436956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    size_t numLeadingZeroes = 0;
437e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
438e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    while (!(x & 0x80)) {
439e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        ++numLeadingZeroes;
440e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        x = x << 1;
441e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    }
442e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
443e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    return numLeadingZeroes;
444e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}
445e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
446e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid MatroskaSource::clearPendingFrames() {
447e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    while (!mPendingFrames.empty()) {
448e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        MediaBuffer *frame = *mPendingFrames.begin();
449e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        mPendingFrames.erase(mPendingFrames.begin());
450e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
451e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        frame->release();
452e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        frame = NULL;
453956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
454956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
455956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
456956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatus_t MatroskaSource::readBlock() {
457956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    CHECK(mPendingFrames.empty());
458956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
459956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (mBlockIter.eos()) {
460956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        return ERROR_END_OF_STREAM;
461956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
462956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
463956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    const mkvparser::Block *block = mBlockIter.block();
464956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
465956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t timeUs = mBlockIter.blockTimeUs();
466956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
467956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for (int i = 0; i < block->GetFrameCount(); ++i) {
468956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        const mkvparser::Block::Frame &frame = block->GetFrame(i);
469956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
470956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        MediaBuffer *mbuf = new MediaBuffer(frame.len);
471956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        mbuf->meta_data()->setInt64(kKeyTime, timeUs);
472956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
473e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
474e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data());
475956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if (n != 0) {
476956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            mPendingFrames.clear();
477956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
478b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard            mBlockIter.advance();
479956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            return ERROR_IO;
480b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        }
481b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
482956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        mPendingFrames.push_back(mbuf);
483956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
484956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
485956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mBlockIter.advance();
486956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
487956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    return OK;
488956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
489956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
490956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatus_t MatroskaSource::read(
491b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        MediaBuffer **out, const ReadOptions *options) {
492956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    *out = NULL;
493956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
494956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t targetSampleTimeUs = -1ll;
495b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
496956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    int64_t seekTimeUs;
497956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    ReadOptions::SeekMode mode;
498956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (options && options->getSeekTo(&seekTimeUs, &mode)
499b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard            && !mExtractor->isLiveStreaming()) {
500956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        clearPendingFrames();
501956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
502956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        // The audio we want is located by using the Cues to seek the video
503956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        // stream to find the target Cluster then iterating to finalize for
504956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        // audio.
505956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        int64_t actualFrameTimeUs;
506956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs);
507b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
508956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if (mode == ReadOptions::SEEK_CLOSEST) {
509b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard            targetSampleTimeUs = actualFrameTimeUs;
510956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
511956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
512956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
513b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    while (mPendingFrames.empty()) {
514956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        status_t err = readBlock();
515b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
516956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if (err != OK) {
517956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            clearPendingFrames();
518956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
519956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            return err;
520956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
521956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
522b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
523956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    MediaBuffer *frame = *mPendingFrames.begin();
524956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mPendingFrames.erase(mPendingFrames.begin());
525e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
526e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    if (mType != AVC) {
527956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if (targetSampleTimeUs >= 0ll) {
528b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard            frame->meta_data()->setInt64(
529956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    kKeyTargetTime, targetSampleTimeUs);
530b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        }
531956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
532956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        *out = frame;
533956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
534956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        return OK;
535956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
536956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
537956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    // Each input frame contains one or more NAL fragments, each fragment
538956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    // is prefixed by mNALSizeLen bytes giving the fragment length,
539956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    // followed by a corresponding number of bytes containing the fragment.
540956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    // We output all these fragments into a single large buffer separated
541b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    // by startcodes (0x00 0x00 0x00 0x01).
542956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
543956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    const uint8_t *srcPtr =
544956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        (const uint8_t *)frame->data() + frame->range_offset();
545956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
546956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    size_t srcSize = frame->range_length();
547956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
548956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    size_t dstSize = 0;
549956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    MediaBuffer *buffer = NULL;
550956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    uint8_t *dstPtr = NULL;
551e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
552956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    for (int32_t pass = 0; pass < 2; ++pass) {
553b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        size_t srcOffset = 0;
554956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        size_t dstOffset = 0;
555b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        while (srcOffset + mNALSizeLen <= srcSize) {
556b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard            size_t NALsize;
557956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            switch (mNALSizeLen) {
558b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard                case 1: NALsize = srcPtr[srcOffset]; break;
559956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                case 2: NALsize = U16_AT(srcPtr + srcOffset); break;
560b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard                case 3: NALsize = U24_AT(srcPtr + srcOffset); break;
561956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                case 4: NALsize = U32_AT(srcPtr + srcOffset); break;
562956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                default:
563956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                    TRESPASS();
564b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard            }
565956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
566956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            if (srcOffset + mNALSizeLen + NALsize > srcSize) {
567956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                break;
568956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            }
569956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
570956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            if (pass == 1) {
571956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4);
572e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
573956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                memcpy(&dstPtr[dstOffset + 4],
574956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                       &srcPtr[srcOffset + mNALSizeLen],
575956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong                       NALsize);
576956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            }
577956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
578956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            dstOffset += 4;  // 0x00 00 00 01
579956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            dstOffset += NALsize;
580b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
581956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            srcOffset += mNALSizeLen + NALsize;
582956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
583956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
584956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        if (srcOffset < srcSize) {
585956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            // There were trailing bytes or not enough data to complete
586956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            // a fragment.
587956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
588b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard            frame->release();
589956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            frame = NULL;
590b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
591956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            return ERROR_MALFORMED;
592956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        }
593956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
594b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        if (pass == 0) {
595956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            dstSize = dstOffset;
596b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
597956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            buffer = new MediaBuffer(dstSize);
598956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
599956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            int64_t timeUs;
600b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard            CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
601956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            int32_t isSync;
602956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));
603956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
604956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            buffer->meta_data()->setInt64(kKeyTime, timeUs);
605956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
606956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
607956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            dstPtr = (uint8_t *)buffer->data();
608e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        }
609956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
610b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
611956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    frame->release();
612b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    frame = NULL;
613956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
614956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (targetSampleTimeUs >= 0ll) {
615956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        buffer->meta_data()->setInt64(
616b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard                kKeyTargetTime, targetSampleTimeUs);
617956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
618956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
619956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    *out = buffer;
620956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
621956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    return OK;
622956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong}
623e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
624e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard////////////////////////////////////////////////////////////////////////////////
625956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
626b676a05348e4c516fa8b57e33b10548e6142c3f8Mans RullgardMatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
627956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    : mDataSource(source),
628956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mReader(new DataSourceReader(mDataSource)),
629956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mSegment(NULL),
630956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong      mExtractedThumbnails(false),
631b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard      mIsWebm(false) {
632956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    off64_t size;
633956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    mIsLiveStreaming =
634956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        (mDataSource->flags()
635956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong            & (DataSource::kWantsPrefetching
636b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard                | DataSource::kIsCachingDataSource))
637956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        && mDataSource->getSize(&size) != OK;
638956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
639b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    mkvparser::EBMLHeader ebmlHeader;
640b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    long long pos;
641956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (ebmlHeader.Parse(mReader, pos) < 0) {
642956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        return;
643956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
644b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
645b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) {
646956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        mIsWebm = true;
647956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
648956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
649956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    long long ret =
650956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        mkvparser::Segment::CreateInstance(mReader, pos, mSegment);
651956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
652956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (ret) {
653e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard        CHECK(mSegment == NULL);
654b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard        return;
655956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
656956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
657956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    ret = mSegment->ParseHeaders();
658956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    CHECK_EQ(ret, 0);
659e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
660e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    long len;
661e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    ret = mSegment->LoadCluster(pos, len);
662e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard    CHECK_EQ(ret, 0);
663e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard
664956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    if (ret < 0) {
665956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        delete mSegment;
666956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        mSegment = NULL;
667956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong        return;
668956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    }
669b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard
670956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#if 0
671956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    const mkvparser::SegmentInfo *info = mSegment->GetInfo();
672b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard    ALOGI("muxing app: %s, writing app: %s",
673956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong         info->GetMuxingAppAsUTF8(),
674956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong         info->GetWritingAppAsUTF8());
675956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#endif
676956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong
677956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong    addTracks();
678}
679
680MatroskaExtractor::~MatroskaExtractor() {
681    delete mSegment;
682    mSegment = NULL;
683
684    delete mReader;
685    mReader = NULL;
686}
687
688size_t MatroskaExtractor::countTracks() {
689    return mTracks.size();
690}
691
692sp<MediaSource> MatroskaExtractor::getTrack(size_t index) {
693    if (index >= mTracks.size()) {
694        return NULL;
695    }
696
697    return new MatroskaSource(this, index);
698}
699
700sp<MetaData> MatroskaExtractor::getTrackMetaData(
701        size_t index, uint32_t flags) {
702    if (index >= mTracks.size()) {
703        return NULL;
704    }
705
706    if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails
707            && !isLiveStreaming()) {
708        findThumbnails();
709        mExtractedThumbnails = true;
710    }
711
712    return mTracks.itemAt(index).mMeta;
713}
714
715bool MatroskaExtractor::isLiveStreaming() const {
716    return mIsLiveStreaming;
717}
718
719static int bytesForSize(size_t size) {
720    // use at most 28 bits (4 times 7)
721    CHECK(size <= 0xfffffff);
722
723    if (size > 0x1fffff) {
724        return 4;
725    } else if (size > 0x3fff) {
726        return 3;
727    } else if (size > 0x7f) {
728        return 2;
729    }
730    return 1;
731}
732
733static void storeSize(uint8_t *data, size_t &idx, size_t size) {
734    int numBytes = bytesForSize(size);
735    idx += numBytes;
736
737    data += idx;
738    size_t next = 0;
739    while (numBytes--) {
740        *--data = (size & 0x7f) | next;
741        size >>= 7;
742        next = 0x80;
743    }
744}
745
746static void addESDSFromCodecPrivate(
747        const sp<MetaData> &meta,
748        bool isAudio, const void *priv, size_t privSize) {
749
750    int privSizeBytesRequired = bytesForSize(privSize);
751    int esdsSize2 = 14 + privSizeBytesRequired + privSize;
752    int esdsSize2BytesRequired = bytesForSize(esdsSize2);
753    int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2;
754    int esdsSize1BytesRequired = bytesForSize(esdsSize1);
755    size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1;
756    uint8_t *esds = new uint8_t[esdsSize];
757
758    size_t idx = 0;
759    esds[idx++] = 0x03;
760    storeSize(esds, idx, esdsSize1);
761    esds[idx++] = 0x00; // ES_ID
762    esds[idx++] = 0x00; // ES_ID
763    esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
764    esds[idx++] = 0x04;
765    storeSize(esds, idx, esdsSize2);
766    esds[idx++] = isAudio ? 0x40   // Audio ISO/IEC 14496-3
767                          : 0x20;  // Visual ISO/IEC 14496-2
768    for (int i = 0; i < 12; i++) {
769        esds[idx++] = 0x00;
770    }
771    esds[idx++] = 0x05;
772    storeSize(esds, idx, privSize);
773    memcpy(esds + idx, priv, privSize);
774
775    meta->setData(kKeyESDS, 0, esds, esdsSize);
776
777    delete[] esds;
778    esds = NULL;
779}
780
781status_t addVorbisCodecInfo(
782        const sp<MetaData> &meta,
783        const void *_codecPrivate, size_t codecPrivateSize) {
784    // hexdump(_codecPrivate, codecPrivateSize);
785
786    if (codecPrivateSize < 1) {
787        return ERROR_MALFORMED;
788    }
789
790    const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate;
791
792    if (codecPrivate[0] != 0x02) {
793        return ERROR_MALFORMED;
794    }
795
796    // codecInfo starts with two lengths, len1 and len2, that are
797    // "Xiph-style-lacing encoded"...
798
799    size_t offset = 1;
800    size_t len1 = 0;
801    while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) {
802        len1 += 0xff;
803        ++offset;
804    }
805    if (offset >= codecPrivateSize) {
806        return ERROR_MALFORMED;
807    }
808    len1 += codecPrivate[offset++];
809
810    size_t len2 = 0;
811    while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) {
812        len2 += 0xff;
813        ++offset;
814    }
815    if (offset >= codecPrivateSize) {
816        return ERROR_MALFORMED;
817    }
818    len2 += codecPrivate[offset++];
819
820    if (codecPrivateSize < offset + len1 + len2) {
821        return ERROR_MALFORMED;
822    }
823
824    if (codecPrivate[offset] != 0x01) {
825        return ERROR_MALFORMED;
826    }
827    meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1);
828
829    offset += len1;
830    if (codecPrivate[offset] != 0x03) {
831        return ERROR_MALFORMED;
832    }
833
834    offset += len2;
835    if (codecPrivate[offset] != 0x05) {
836        return ERROR_MALFORMED;
837    }
838
839    meta->setData(
840            kKeyVorbisBooks, 0, &codecPrivate[offset],
841            codecPrivateSize - offset);
842
843    return OK;
844}
845
846void MatroskaExtractor::addTracks() {
847    const mkvparser::Tracks *tracks = mSegment->GetTracks();
848
849    for (size_t index = 0; index < tracks->GetTracksCount(); ++index) {
850        const mkvparser::Track *track = tracks->GetTrackByIndex(index);
851
852        if (track == NULL) {
853            // Apparently this is currently valid (if unexpected) behaviour
854            // of the mkv parser lib.
855            continue;
856        }
857
858        const char *const codecID = track->GetCodecId();
859        ALOGV("codec id = %s", codecID);
860        ALOGV("codec name = %s", track->GetCodecNameAsUTF8());
861
862        size_t codecPrivateSize;
863        const unsigned char *codecPrivate =
864            track->GetCodecPrivate(codecPrivateSize);
865
866        enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
867
868        sp<MetaData> meta = new MetaData;
869
870        status_t err = OK;
871
872        switch (track->GetType()) {
873            case VIDEO_TRACK:
874            {
875                const mkvparser::VideoTrack *vtrack =
876                    static_cast<const mkvparser::VideoTrack *>(track);
877
878                if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
879                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
880                    meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
881                } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) {
882                    if (codecPrivateSize > 0) {
883                        meta->setCString(
884                                kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
885                        addESDSFromCodecPrivate(
886                                meta, false, codecPrivate, codecPrivateSize);
887                    } else {
888                        ALOGW("%s is detected, but does not have configuration.",
889                                codecID);
890                        continue;
891                    }
892                } else if (!strcmp("V_VP8", codecID)) {
893                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
894                } else if (!strcmp("V_VP9", codecID)) {
895                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9);
896                } else {
897                    ALOGW("%s is not supported.", codecID);
898                    continue;
899                }
900
901                meta->setInt32(kKeyWidth, vtrack->GetWidth());
902                meta->setInt32(kKeyHeight, vtrack->GetHeight());
903                break;
904            }
905
906            case AUDIO_TRACK:
907            {
908                const mkvparser::AudioTrack *atrack =
909                    static_cast<const mkvparser::AudioTrack *>(track);
910
911                if (!strcmp("A_AAC", codecID)) {
912                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
913                    CHECK(codecPrivateSize >= 2);
914
915                    addESDSFromCodecPrivate(
916                            meta, true, codecPrivate, codecPrivateSize);
917                } else if (!strcmp("A_VORBIS", codecID)) {
918                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
919
920                    err = addVorbisCodecInfo(
921                            meta, codecPrivate, codecPrivateSize);
922                } else if (!strcmp("A_MPEG/L3", codecID)) {
923                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
924                } else {
925                    ALOGW("%s is not supported.", codecID);
926                    continue;
927                }
928
929                meta->setInt32(kKeySampleRate, atrack->GetSamplingRate());
930                meta->setInt32(kKeyChannelCount, atrack->GetChannels());
931                break;
932            }
933
934            default:
935                continue;
936        }
937
938        if (err != OK) {
939            ALOGE("skipping track, codec specific data was malformed.");
940            continue;
941        }
942
943        long long durationNs = mSegment->GetDuration();
944        meta->setInt64(kKeyDuration, (durationNs + 500) / 1000);
945
946        mTracks.push();
947        TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1);
948        trackInfo->mTrackNum = track->GetNumber();
949        trackInfo->mMeta = meta;
950    }
951}
952
953void MatroskaExtractor::findThumbnails() {
954    for (size_t i = 0; i < mTracks.size(); ++i) {
955        TrackInfo *info = &mTracks.editItemAt(i);
956
957        const char *mime;
958        CHECK(info->mMeta->findCString(kKeyMIMEType, &mime));
959
960        if (strncasecmp(mime, "video/", 6)) {
961            continue;
962        }
963
964        BlockIterator iter(this, info->mTrackNum);
965        int32_t j = 0;
966        int64_t thumbnailTimeUs = 0;
967        size_t maxBlockSize = 0;
968        while (!iter.eos() && j < 20) {
969            if (iter.block()->IsKey()) {
970                ++j;
971
972                size_t blockSize = 0;
973                for (int k = 0; k < iter.block()->GetFrameCount(); ++k) {
974                    blockSize += iter.block()->GetFrame(k).len;
975                }
976
977                if (blockSize > maxBlockSize) {
978                    maxBlockSize = blockSize;
979                    thumbnailTimeUs = iter.blockTimeUs();
980                }
981            }
982            iter.advance();
983        }
984        info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
985    }
986}
987
988sp<MetaData> MatroskaExtractor::getMetaData() {
989    sp<MetaData> meta = new MetaData;
990
991    meta->setCString(
992            kKeyMIMEType,
993            mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA);
994
995    return meta;
996}
997
998uint32_t MatroskaExtractor::flags() const {
999    uint32_t x = CAN_PAUSE;
1000    if (!isLiveStreaming()) {
1001        x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK;
1002    }
1003
1004    return x;
1005}
1006
1007bool SniffMatroska(
1008        const sp<DataSource> &source, String8 *mimeType, float *confidence,
1009        sp<AMessage> *) {
1010    DataSourceReader reader(source);
1011    mkvparser::EBMLHeader ebmlHeader;
1012    long long pos;
1013    if (ebmlHeader.Parse(&reader, pos) < 0) {
1014        return false;
1015    }
1016
1017    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA);
1018    *confidence = 0.6;
1019
1020    return true;
1021}
1022
1023}  // namespace android
1024