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
21f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia#include "FLACDecoder.h"
22093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include "MatroskaExtractor.h"
23093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
242a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen#include <media/DataSourceBase.h>
25a1a005fc01118685c92e723c8dcf7afeffc9d59cMarco Nelissen#include <media/ExtractorUtils.h>
263d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen#include <media/MediaTrack.h>
27b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber#include <media/stagefright/foundation/ADebug.h>
282dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih#include <media/stagefright/foundation/AUtils.h>
294f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih#include <media/stagefright/foundation/ABuffer.h>
30607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang#include <media/stagefright/foundation/ByteUtils.h>
31d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar#include <media/stagefright/foundation/ColorUtils.h>
32b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber#include <media/stagefright/foundation/hexdump.h>
331889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang#include <media/stagefright/MediaBufferBase.h>
34093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaDefs.h>
35093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaErrors.h>
36093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MetaData.h>
377dc218e17800cc3ac95551e3280820f407adf7b5Dongwon Kang#include <media/stagefright/MetaDataUtils.h>
38093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <utils/String8.h>
39093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
40a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih#include <arpa/inet.h>
41b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross#include <inttypes.h>
42a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih#include <vector>
43b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross
44093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubernamespace android {
45093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
462a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissenstruct DataSourceBaseReader : public mkvparser::IMkvReader {
472a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen    explicit DataSourceBaseReader(DataSourceBase *source)
48093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        : mSource(source) {
49093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
50093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
51093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    virtual int Read(long long position, long length, unsigned char* buffer) {
52093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        CHECK(position >= 0);
53093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        CHECK(length >= 0);
54093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
55093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        if (length == 0) {
56093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            return 0;
57093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
58093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
59093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        ssize_t n = mSource->readAt(position, buffer, length);
60093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
61093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        if (n <= 0) {
62093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            return -1;
63093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
64093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
65093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return 0;
66093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
67093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
68093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    virtual int Length(long long* total, long long* available) {
69c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t size;
70093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        if (mSource->getSize(&size) != OK) {
71d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            *total = -1;
72d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            *available = (long long)((1ull << 63) - 1);
73d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
74d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            return 0;
75093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
76093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
77093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        if (total) {
78093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            *total = size;
79093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
80093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
81093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        if (available) {
82093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            *available = size;
83093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
84093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
85093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return 0;
86093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
87093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
88093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberprivate:
892a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen    DataSourceBase *mSource;
90093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
912a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen    DataSourceBaseReader(const DataSourceBaseReader &);
922a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen    DataSourceBaseReader &operator=(const DataSourceBaseReader &);
93093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber};
94093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
95093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber////////////////////////////////////////////////////////////////////////////////
96093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
975279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberstruct BlockIterator {
982f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index);
995279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
1005279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    bool eos() const;
1015279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
1025279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    void advance();
1035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    void reset();
1045ec58d925520e6913fba3fc54413881af751c610Andreas Huber
1055ec58d925520e6913fba3fc54413881af751c610Andreas Huber    void seek(
106f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann            int64_t seekTimeUs, bool isAudio,
1075ec58d925520e6913fba3fc54413881af751c610Andreas Huber            int64_t *actualFrameTimeUs);
1085279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
1095279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    const mkvparser::Block *block() const;
1105279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    int64_t blockTimeUs() const;
1115279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
1125279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberprivate:
113d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    MatroskaExtractor *mExtractor;
114b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    long long mTrackNum;
1152f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    unsigned long mIndex;
1165279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
117d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    const mkvparser::Cluster *mCluster;
1185279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    const mkvparser::BlockEntry *mBlockEntry;
119d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    long mBlockEntryIndex;
120d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
121d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    void advance_l();
1225279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
1235279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    BlockIterator(const BlockIterator &);
1245279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    BlockIterator &operator=(const BlockIterator &);
1255279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber};
1265279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
1273d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstruct MatroskaSource : public MediaTrack {
1287d880c31d2079299000b036c6ae742dc695a5b19Marco Nelissen    MatroskaSource(MatroskaExtractor *extractor, size_t index);
129093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1303d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    virtual status_t start(MetaDataBase *params);
131093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    virtual status_t stop();
132093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1333d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    virtual status_t getFormat(MetaDataBase &);
134093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
135093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    virtual status_t read(
1361889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang            MediaBufferBase **buffer, const ReadOptions *options);
137093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
13850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberprotected:
13950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    virtual ~MatroskaSource();
14050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
141093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberprivate:
142093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    enum Type {
143093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        AVC,
144093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        AAC,
145f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik        HEVC,
146093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        OTHER
147093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    };
148093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1497d880c31d2079299000b036c6ae742dc695a5b19Marco Nelissen    MatroskaExtractor *mExtractor;
150093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    size_t mTrackIndex;
151093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    Type mType;
15274a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber    bool mIsAudio;
1535279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    BlockIterator mBlockIter;
154f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik    ssize_t mNALSizeLen;  // for type AVC or HEVC
155093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1561889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang    List<MediaBufferBase *> mPendingFrames;
15750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
158093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    status_t advance();
159093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1601889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang    status_t setWebmBlockCryptoInfo(MediaBufferBase *mbuf);
16150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    status_t readBlock();
16250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    void clearPendingFrames();
16350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
164093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    MatroskaSource(const MatroskaSource &);
165093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    MatroskaSource &operator=(const MatroskaSource &);
166093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber};
167093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1682f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shihconst mkvparser::Track* MatroskaExtractor::TrackInfo::getTrack() const {
1692f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    return mExtractor->mSegment->GetTracks()->GetTrackByNumber(mTrackNum);
1702f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih}
1712f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih
1722f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih// This function does exactly the same as mkvparser::Cues::Find, except that it
1732f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih// searches in our own track based vectors. We should not need this once mkvparser
1742f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih// adds the same functionality.
1752f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shihconst mkvparser::CuePoint::TrackPosition *MatroskaExtractor::TrackInfo::find(
1762f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        long long timeNs) const {
1772f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    ALOGV("mCuePoints.size %zu", mCuePoints.size());
1782f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    if (mCuePoints.empty()) {
1792f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        return NULL;
1802f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    }
1812f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih
1822f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    const mkvparser::CuePoint* cp = mCuePoints.itemAt(0);
1832f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    const mkvparser::Track* track = getTrack();
1842f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    if (timeNs <= cp->GetTime(mExtractor->mSegment)) {
1852f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        return cp->Find(track);
1862f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    }
1872f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih
1882f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    // Binary searches through relevant cues; assumes cues are ordered by timecode.
1892f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    // If we do detect out-of-order cues, return NULL.
1902f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    size_t lo = 0;
1912f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    size_t hi = mCuePoints.size();
1922f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    while (lo < hi) {
1932f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        const size_t mid = lo + (hi - lo) / 2;
1942f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        const mkvparser::CuePoint* const midCp = mCuePoints.itemAt(mid);
1952f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        const long long cueTimeNs = midCp->GetTime(mExtractor->mSegment);
1962f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        if (cueTimeNs <= timeNs) {
1972f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih            lo = mid + 1;
1982f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        } else {
1992f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih            hi = mid;
2002f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        }
2012f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    }
2022f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih
2032f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    if (lo == 0) {
2042f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        return NULL;
2052f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    }
2062f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih
2072f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    cp = mCuePoints.itemAt(lo - 1);
2082f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    if (cp->GetTime(mExtractor->mSegment) > timeNs) {
2092f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        return NULL;
2102f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    }
2112f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih
2122f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    return cp->Find(track);
2132f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih}
2142f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih
215093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaSource::MatroskaSource(
2167d880c31d2079299000b036c6ae742dc695a5b19Marco Nelissen        MatroskaExtractor *extractor, size_t index)
217093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    : mExtractor(extractor),
218093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber      mTrackIndex(index),
219093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber      mType(OTHER),
22074a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber      mIsAudio(false),
2217d880c31d2079299000b036c6ae742dc695a5b19Marco Nelissen      mBlockIter(mExtractor,
2222f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih                 mExtractor->mTracks.itemAt(index).mTrackNum,
2232f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih                 index),
2244f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih      mNALSizeLen(-1) {
2253d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    MetaDataBase &meta = mExtractor->mTracks.editItemAt(index).mMeta;
226b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber
227093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    const char *mime;
2283d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    CHECK(meta.findCString(kKeyMIMEType, &mime));
229093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
23074a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber    mIsAudio = !strncasecmp("audio/", mime, 6);
23174a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber
232093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
233093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        mType = AVC;
234b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber
235b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber        uint32_t dummy;
236b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber        const uint8_t *avcc;
237b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber        size_t avccSize;
2384f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih        int32_t nalSizeLen = 0;
2393d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        if (meta.findInt32(kKeyNalLengthSize, &nalSizeLen)) {
2404f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih            if (nalSizeLen >= 0 && nalSizeLen <= 4) {
2414f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih                mNALSizeLen = nalSizeLen;
2424f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih            }
2433d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        } else if (meta.findData(kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)
2444f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih                && avccSize >= 5u) {
2454f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih            mNALSizeLen = 1 + (avcc[4] & 3);
2464f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih            ALOGV("mNALSizeLen = %zd", mNALSizeLen);
2474f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih        } else {
2484f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih            ALOGE("No mNALSizeLen");
2494f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih        }
250f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
251f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik        mType = HEVC;
252f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik
253f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik        uint32_t dummy;
254f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik        const uint8_t *hvcc;
255f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik        size_t hvccSize;
2563d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        if (meta.findData(kKeyHVCC, &dummy, (const void **)&hvcc, &hvccSize)
257f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik                && hvccSize >= 22u) {
258f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik            mNALSizeLen = 1 + (hvcc[14+7] & 3);
259f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik            ALOGV("mNALSizeLen = %zu", mNALSizeLen);
260f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik        } else {
261f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik            ALOGE("No mNALSizeLen");
262f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik        }
263093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
264093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        mType = AAC;
265093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
266093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
267093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
26850c8bea8fba2fcafb14696399028bdbc094dc995Andreas HuberMatroskaSource::~MatroskaSource() {
26950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    clearPendingFrames();
27050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber}
27150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
2723d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t MatroskaSource::start(MetaDataBase * /* params */) {
2734f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    if (mType == AVC && mNALSizeLen < 0) {
2744f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih        return ERROR_MALFORMED;
2754f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    }
2764f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih
2775279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    mBlockIter.reset();
278093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
279093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return OK;
280093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
281093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
282093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstatus_t MatroskaSource::stop() {
28350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    clearPendingFrames();
28450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
285093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return OK;
286093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
287093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
2883d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t MatroskaSource::getFormat(MetaDataBase &meta) {
2893d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    meta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
2903d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    return OK;
291093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
292093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
2935279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber////////////////////////////////////////////////////////////////////////////////
2945279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
2955279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas HuberBlockIterator::BlockIterator(
2962f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index)
297d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    : mExtractor(extractor),
2985279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber      mTrackNum(trackNum),
2992f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih      mIndex(index),
3005279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber      mCluster(NULL),
301d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber      mBlockEntry(NULL),
302d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber      mBlockEntryIndex(0) {
3035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    reset();
3045279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}
3055279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
3065279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberbool BlockIterator::eos() const {
3075279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    return mCluster == NULL || mCluster->EOS();
3085279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}
3095279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
3105279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::advance() {
311d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    Mutex::Autolock autoLock(mExtractor->mLock);
312d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    advance_l();
313d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber}
314d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
315d42573cace9db2b5948e540c32beaef80f04153cAndreas Hubervoid BlockIterator::advance_l() {
316d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    for (;;) {
317d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry);
3183856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("GetEntry returned %ld", res);
319d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
320d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        long long pos;
321d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        long len;
322d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        if (res < 0) {
323d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            // Need to parse this cluster some more
324d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
325d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL);
326d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
327d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            res = mCluster->Parse(pos, len);
3283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("Parse returned %ld", res);
329d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
330d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            if (res < 0) {
331d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber                // I/O error
332d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
33329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Cluster::Parse returned result %ld", res);
3345279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
335d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber                mCluster = NULL;
3365279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber                break;
337093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            }
3385279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
339d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            continue;
340d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        } else if (res == 0) {
341d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            // We're done with this cluster
342d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
343d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            const mkvparser::Cluster *nextCluster;
344d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            res = mExtractor->mSegment->ParseNext(
345d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber                    mCluster, nextCluster, pos, len);
3463856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("ParseNext returned %ld", res);
347d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
348e467ef084b75b074d0081616080b54212a7024c8Lajos Molnar            if (res != 0) {
349e467ef084b75b074d0081616080b54212a7024c8Lajos Molnar                // EOF or error
350d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
351d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber                mCluster = NULL;
352d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber                break;
353d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            }
354d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
355d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            CHECK_EQ(res, 0);
356d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            CHECK(nextCluster != NULL);
357d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            CHECK(!nextCluster->EOS());
358d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
359d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            mCluster = nextCluster;
360d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
361d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            res = mCluster->Parse(pos, len);
3623856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("Parse (2) returned %ld", res);
363918ddcc97b5679ba2afd0bfeb6f79be111ad6166Dongwon Kang
364918ddcc97b5679ba2afd0bfeb6f79be111ad6166Dongwon Kang            if (res < 0) {
365918ddcc97b5679ba2afd0bfeb6f79be111ad6166Dongwon Kang                // I/O error
366918ddcc97b5679ba2afd0bfeb6f79be111ad6166Dongwon Kang
367918ddcc97b5679ba2afd0bfeb6f79be111ad6166Dongwon Kang                ALOGE("Cluster::Parse returned result %ld", res);
368918ddcc97b5679ba2afd0bfeb6f79be111ad6166Dongwon Kang
369918ddcc97b5679ba2afd0bfeb6f79be111ad6166Dongwon Kang                mCluster = NULL;
370918ddcc97b5679ba2afd0bfeb6f79be111ad6166Dongwon Kang                break;
371918ddcc97b5679ba2afd0bfeb6f79be111ad6166Dongwon Kang            }
372d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
373d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            mBlockEntryIndex = 0;
374d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            continue;
375093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
376093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
377d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        CHECK(mBlockEntry != NULL);
378d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        CHECK(mBlockEntry->GetBlock() != NULL);
379d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        ++mBlockEntryIndex;
380d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
381d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
3825279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber            break;
383093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
3845279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    }
3855279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}
3865279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
3875279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::reset() {
388d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    Mutex::Autolock autoLock(mExtractor->mLock);
389093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
390d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    mCluster = mExtractor->mSegment->GetFirst();
3912ba7ce928b0fa8917ee202836b0963ca58613453Andreas Huber    mBlockEntry = NULL;
392d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    mBlockEntryIndex = 0;
393d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
394d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    do {
395d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        advance_l();
396d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    } while (!eos() && block()->GetTrackNumber() != mTrackNum);
3975279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}
398093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
3995ec58d925520e6913fba3fc54413881af751c610Andreas Hubervoid BlockIterator::seek(
400f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann        int64_t seekTimeUs, bool isAudio,
4015ec58d925520e6913fba3fc54413881af751c610Andreas Huber        int64_t *actualFrameTimeUs) {
402d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    Mutex::Autolock autoLock(mExtractor->mLock);
403d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
4045ec58d925520e6913fba3fc54413881af751c610Andreas Huber    *actualFrameTimeUs = -1ll;
4055ec58d925520e6913fba3fc54413881af751c610Andreas Huber
4066b8937f4a81447968b22b75a6f1e450bbda1a18fMarco Nelissen    if (seekTimeUs > INT64_MAX / 1000ll ||
4076b8937f4a81447968b22b75a6f1e450bbda1a18fMarco Nelissen            seekTimeUs < INT64_MIN / 1000ll ||
4086b8937f4a81447968b22b75a6f1e450bbda1a18fMarco Nelissen            (mExtractor->mSeekPreRollNs > 0 &&
4096b8937f4a81447968b22b75a6f1e450bbda1a18fMarco Nelissen                    (seekTimeUs * 1000ll) < INT64_MIN + mExtractor->mSeekPreRollNs) ||
4106b8937f4a81447968b22b75a6f1e450bbda1a18fMarco Nelissen            (mExtractor->mSeekPreRollNs < 0 &&
4116b8937f4a81447968b22b75a6f1e450bbda1a18fMarco Nelissen                    (seekTimeUs * 1000ll) > INT64_MAX + mExtractor->mSeekPreRollNs)) {
4126b8937f4a81447968b22b75a6f1e450bbda1a18fMarco Nelissen        ALOGE("cannot seek to %lld", (long long) seekTimeUs);
4136b8937f4a81447968b22b75a6f1e450bbda1a18fMarco Nelissen        return;
4146b8937f4a81447968b22b75a6f1e450bbda1a18fMarco Nelissen    }
4156b8937f4a81447968b22b75a6f1e450bbda1a18fMarco Nelissen
416bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian    const int64_t seekTimeNs = seekTimeUs * 1000ll - mExtractor->mSeekPreRollNs;
41710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann
41810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    mkvparser::Segment* const pSegment = mExtractor->mSegment;
41910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann
42010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    // Special case the 0 seek to avoid loading Cues when the application
42110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    // extraneously seeks to 0 before playing.
42210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    if (seekTimeNs <= 0) {
423b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross        ALOGV("Seek to beginning: %" PRId64, seekTimeUs);
42410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        mCluster = pSegment->GetFirst();
42510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        mBlockEntryIndex = 0;
42610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        do {
42710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann            advance_l();
42810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        } while (!eos() && block()->GetTrackNumber() != mTrackNum);
42910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        return;
43010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    }
4315ec58d925520e6913fba3fc54413881af751c610Andreas Huber
432b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    ALOGV("Seeking to: %" PRId64, seekTimeUs);
43310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann
43410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    // If the Cues have not been located then find them.
43510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    const mkvparser::Cues* pCues = pSegment->GetCues();
43610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    const mkvparser::SeekHead* pSH = pSegment->GetSeekHead();
43710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    if (!pCues && pSH) {
43810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        const size_t count = pSH->GetCount();
43910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        const mkvparser::SeekHead::Entry* pEntry;
44010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        ALOGV("No Cues yet");
44110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann
44210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        for (size_t index = 0; index < count; index++) {
44310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann            pEntry = pSH->GetEntry(index);
44410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann
44510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann            if (pEntry->id == 0x0C53BB6B) { // Cues ID
44610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann                long len; long long pos;
44710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann                pSegment->ParseCues(pEntry->pos, pos, len);
44810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann                pCues = pSegment->GetCues();
449be7ac3d682729048af27871311808a76c618abdbJohann                ALOGV("Cues found");
45010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann                break;
45110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann            }
45210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        }
45310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann
45410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        if (!pCues) {
45510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann            ALOGE("No Cues in file");
45610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann            return;
45710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        }
45810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    }
45910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    else if (!pSH) {
46010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        ALOGE("No SeekHead");
46110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        return;
46210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    }
46310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann
46410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    const mkvparser::CuePoint* pCP;
4652f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    mkvparser::Tracks const *pTracks = pSegment->GetTracks();
46610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    while (!pCues->DoneParsing()) {
467be7ac3d682729048af27871311808a76c618abdbJohann        pCues->LoadCuePoint();
46810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        pCP = pCues->GetLast();
4692f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        CHECK(pCP);
4702f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih
4710644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih        size_t trackCount = mExtractor->mTracks.size();
4722f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        for (size_t index = 0; index < trackCount; ++index) {
4730644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih            MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(index);
4740644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih            const mkvparser::Track *pTrack = pTracks->GetTrackByNumber(track.mTrackNum);
4752f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih            if (pTrack && pTrack->GetType() == 1 && pCP->Find(pTrack)) { // VIDEO_TRACK
4762f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih                track.mCuePoints.push_back(pCP);
4772f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih            }
4782f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        }
479be7ac3d682729048af27871311808a76c618abdbJohann
48010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        if (pCP->GetTime(pSegment) >= seekTimeNs) {
481be7ac3d682729048af27871311808a76c618abdbJohann            ALOGV("Parsed past relevant Cue");
48210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann            break;
48310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        }
48410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    }
48510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann
4862f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    const mkvparser::CuePoint::TrackPosition *pTP = NULL;
4870644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih    const mkvparser::Track *thisTrack = pTracks->GetTrackByNumber(mTrackNum);
4882f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    if (thisTrack->GetType() == 1) { // video
4892f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(mIndex);
4902f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        pTP = track.find(seekTimeNs);
4912f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    } else {
4922f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        // The Cue index is built around video keyframes
4930644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih        unsigned long int trackCount = pTracks->GetTracksCount();
4942f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        for (size_t index = 0; index < trackCount; ++index) {
4952f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih            const mkvparser::Track *pTrack = pTracks->GetTrackByIndex(index);
4962f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih            if (pTrack && pTrack->GetType() == 1 && pCues->Find(seekTimeNs, pTrack, pCP, pTP)) {
4972f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih                ALOGV("Video track located at %zu", index);
4982f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih                break;
4992f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih            }
50010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        }
50110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    }
50210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann
5032f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih
504f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann    // Always *search* based on the video track, but finalize based on mTrackNum
5052f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih    if (!pTP) {
506f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann        ALOGE("Did not locate the video track for seeking");
50710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann        return;
50810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    }
50910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann
51010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos);
5115279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
512f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann    CHECK(mCluster);
513f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann    CHECK(!mCluster->EOS());
514f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann
515f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann    // mBlockEntryIndex starts at 0 but m_block starts at 1
516f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann    CHECK_GT(pTP->m_block, 0);
517f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann    mBlockEntryIndex = pTP->m_block - 1;
5185ec58d925520e6913fba3fc54413881af751c610Andreas Huber
5195ec58d925520e6913fba3fc54413881af751c610Andreas Huber    for (;;) {
520d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        advance_l();
5215279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
522f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann        if (eos()) break;
5235ec58d925520e6913fba3fc54413881af751c610Andreas Huber
524f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann        if (isAudio || block()->IsKey()) {
525f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann            // Accept the first key frame
5262f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih            int64_t frameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL;
5272f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih            if (thisTrack->GetType() == 1 || frameTimeUs >= seekTimeUs) {
5282f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih                *actualFrameTimeUs = frameTimeUs;
5292f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih                ALOGV("Requested seek point: %" PRId64 " actual: %" PRId64,
5302f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih                      seekTimeUs, *actualFrameTimeUs);
5312f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih                break;
5322f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih            }
53374a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber        }
5345279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    }
535093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
536093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
5375279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberconst mkvparser::Block *BlockIterator::block() const {
5385279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    CHECK(!eos());
5395279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
5405279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    return mBlockEntry->GetBlock();
5415279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}
5425279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
5435279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberint64_t BlockIterator::blockTimeUs() const {
5444f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    if (mCluster == NULL || mBlockEntry == NULL) {
5454f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih        return -1;
5464f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    }
5475279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
5485279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}
5495279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
5505279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber////////////////////////////////////////////////////////////////////////////////
5515279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
552b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huberstatic unsigned U24_AT(const uint8_t *ptr) {
553b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber    return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
554b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber}
555b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber
556b486b52b2b67961073677d583a02269cbdc9a3fcDongwon Kangstatic AString uriDebugString(const char *uri) {
557607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang    // find scheme
558607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang    AString scheme;
559b486b52b2b67961073677d583a02269cbdc9a3fcDongwon Kang    for (size_t i = 0; i < strlen(uri); i++) {
560b486b52b2b67961073677d583a02269cbdc9a3fcDongwon Kang        const char c = uri[i];
561607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang        if (!isascii(c)) {
562607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang            break;
563607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang        } else if (isalpha(c)) {
564607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang            continue;
565607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang        } else if (i == 0) {
566607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang            // first character must be a letter
567607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang            break;
568607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang        } else if (isdigit(c) || c == '+' || c == '.' || c =='-') {
569607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang            continue;
570607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang        } else if (c != ':') {
571607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang            break;
572607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang        }
573607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang        scheme = AString(uri, 0, i);
574607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang        scheme.append("://<suppressed>");
575607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang        return scheme;
576607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang    }
577607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang    return AString("<no-scheme URI suppressed>");
578607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang}
579607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang
58050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Hubervoid MatroskaSource::clearPendingFrames() {
58150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    while (!mPendingFrames.empty()) {
5821889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang        MediaBufferBase *frame = *mPendingFrames.begin();
58350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber        mPendingFrames.erase(mPendingFrames.begin());
58450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
58550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber        frame->release();
58650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber        frame = NULL;
58750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    }
58850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber}
58950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
5901889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kangstatus_t MatroskaSource::setWebmBlockCryptoInfo(MediaBufferBase *mbuf) {
591793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    if (mbuf->range_length() < 1 || mbuf->range_length() - 1 > INT32_MAX) {
592793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        // 1-byte signal
593793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        return ERROR_MALFORMED;
594793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    }
595793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih
596793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    const uint8_t *data = (const uint8_t *)mbuf->data() + mbuf->range_offset();
597a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih    bool encrypted = data[0] & 0x1;
598a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih    bool partitioned = data[0] & 0x2;
599a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih    if (encrypted && mbuf->range_length() < 9) {
600793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        // 1-byte signal + 8-byte IV
601793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        return ERROR_MALFORMED;
602793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    }
603793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih
6043d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    MetaDataBase &meta = mbuf->meta_data();
605a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih    if (encrypted) {
606793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        uint8_t ctrCounter[16] = { 0 };
607793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        uint32_t type;
608793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        const uint8_t *keyId;
609793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        size_t keyIdSize;
6103d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        const MetaDataBase &trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
6113d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        CHECK(trackMeta.findData(kKeyCryptoKey, &type, (const void **)&keyId, &keyIdSize));
6123d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        meta.setData(kKeyCryptoKey, 0, keyId, keyIdSize);
613793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        memcpy(ctrCounter, data + 1, 8);
6143d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        meta.setData(kKeyCryptoIV, 0, ctrCounter, 16);
615a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih        if (partitioned) {
616a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            /*  0                   1                   2                   3
617a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
618a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
619a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * |  Signal Byte  |                                               |
620a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * +-+-+-+-+-+-+-+-+             IV                                |
621a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * |                                                               |
622a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * |               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
623a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * |               | num_partition |     Partition 0 offset ->     |
624a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
625a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * |     -> Partition 0 offset     |              ...              |
626a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
627a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * |             ...               |     Partition n-1 offset ->   |
628a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * |-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
629a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * |     -> Partition n-1 offset   |                               |
630a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
631a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * |                    Clear/encrypted sample data                |
632a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * |                                                               |
633a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * |                                                               |
634a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
635a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             */
636a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            if (mbuf->range_length() < 10) {
637a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                return ERROR_MALFORMED;
638a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            }
639a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            uint8_t numPartitions = data[9];
640a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            if (mbuf->range_length() - 10 < numPartitions * sizeof(uint32_t)) {
641a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                return ERROR_MALFORMED;
642a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            }
643a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            std::vector<uint32_t> plainSizes, encryptedSizes;
644a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            uint32_t prev = 0;
645a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            uint32_t frameOffset = 10 + numPartitions * sizeof(uint32_t);
646a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            const uint32_t *partitions = reinterpret_cast<const uint32_t*>(data + 10);
647a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            for (uint32_t i = 0; i <= numPartitions; ++i) {
648a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                uint32_t p_i = i < numPartitions
649a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                        ? ntohl(partitions[i])
650a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                        : (mbuf->range_length() - frameOffset);
651a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                if (p_i < prev) {
652a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                    return ERROR_MALFORMED;
653a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                }
654a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                uint32_t size = p_i - prev;
655a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                prev = p_i;
656a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                if (i % 2) {
657a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                    encryptedSizes.push_back(size);
658a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                } else {
659a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                    plainSizes.push_back(size);
660a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                }
661a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            }
662a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            if (plainSizes.size() > encryptedSizes.size()) {
663a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih                encryptedSizes.push_back(0);
664a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            }
665a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            uint32_t sizeofPlainSizes = sizeof(uint32_t) * plainSizes.size();
666a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            uint32_t sizeofEncryptedSizes = sizeof(uint32_t) * encryptedSizes.size();
667a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            meta.setData(kKeyPlainSizes, 0, plainSizes.data(), sizeofPlainSizes);
668a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            meta.setData(kKeyEncryptedSizes, 0, encryptedSizes.data(), sizeofEncryptedSizes);
669a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            mbuf->set_range(frameOffset, mbuf->range_length() - frameOffset);
670a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih        } else {
671a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            /*
672a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             *  0                   1                   2                   3
673a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
674a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
675a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             *  |  Signal Byte  |                                               |
676a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             *  +-+-+-+-+-+-+-+-+             IV                                |
677a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             *  |                                                               |
678a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             *  |               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
679a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             *  |               |                                               |
680a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             *  |-+-+-+-+-+-+-+-+                                               |
681a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             *  :               Bytes 1..N of encrypted frame                   :
682a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             *  |                                                               |
683a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             *  |                                                               |
684a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
685a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih             */
686a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            int32_t plainSizes[] = { 0 };
687a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            int32_t encryptedSizes[] = { static_cast<int32_t>(mbuf->range_length() - 9) };
688a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            meta.setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
689a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            meta.setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
690a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih            mbuf->set_range(9, mbuf->range_length() - 9);
691a2c4181b9cc30703b0471831e2e5fa03253b5690Robert Shih        }
692793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    } else {
693793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        /*
694793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih         *  0                   1                   2                   3
695793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih         *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
696793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
697793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih         *  |  Signal Byte  |                                               |
698793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih         *  +-+-+-+-+-+-+-+-+                                               |
699793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih         *  :               Bytes 1..N of unencrypted frame                 :
700793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih         *  |                                                               |
701793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih         *  |                                                               |
702793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
703793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih         */
704793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        int32_t plainSizes[] = { static_cast<int32_t>(mbuf->range_length() - 1) };
705793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        int32_t encryptedSizes[] = { 0 };
7063d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        meta.setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
7073d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        meta.setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
708793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        mbuf->set_range(1, mbuf->range_length() - 1);
709793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    }
710793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih
711793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    return OK;
712793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih}
713793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih
71450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatus_t MatroskaSource::readBlock() {
71550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    CHECK(mPendingFrames.empty());
71650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
7175279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    if (mBlockIter.eos()) {
718093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return ERROR_END_OF_STREAM;
719093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
720093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
7215279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    const mkvparser::Block *block = mBlockIter.block();
72250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
7235279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    int64_t timeUs = mBlockIter.blockTimeUs();
724093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
725d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    for (int i = 0; i < block->GetFrameCount(); ++i) {
726580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        MatroskaExtractor::TrackInfo *trackInfo = &mExtractor->mTracks.editItemAt(mTrackIndex);
727d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        const mkvparser::Block::Frame &frame = block->GetFrame(i);
728580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        size_t len = frame.len;
729580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        if (SIZE_MAX - len < trackInfo->mHeaderLen) {
730580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih            return ERROR_MALFORMED;
731580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        }
732580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih
733580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        len += trackInfo->mHeaderLen;
7341889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang        MediaBufferBase *mbuf = MediaBufferBase::Create(len);
735580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        uint8_t *data = static_cast<uint8_t *>(mbuf->data());
736580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        if (trackInfo->mHeader) {
737580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih            memcpy(data, trackInfo->mHeader, trackInfo->mHeaderLen);
738580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        }
739b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber
7403d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        mbuf->meta_data().setInt64(kKeyTime, timeUs);
7413d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        mbuf->meta_data().setInt32(kKeyIsSyncFrame, block->IsKey());
742093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
743580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        status_t err = frame.Read(mExtractor->mReader, data + trackInfo->mHeaderLen);
744793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        if (err == OK
745793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih                && mExtractor->mIsWebm
746580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih                && trackInfo->mEncrypted) {
747793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih            err = setWebmBlockCryptoInfo(mbuf);
748793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        }
749793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih
750793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        if (err != OK) {
751d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            mPendingFrames.clear();
75250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
753d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            mBlockIter.advance();
754ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen            mbuf->release();
755793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih            return err;
75650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber        }
75750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
75850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber        mPendingFrames.push_back(mbuf);
75950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    }
76050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
761d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    mBlockIter.advance();
76250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
76350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    return OK;
76450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber}
76550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
76650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatus_t MatroskaSource::read(
7671889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang        MediaBufferBase **out, const ReadOptions *options) {
76850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    *out = NULL;
76950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
7705ec58d925520e6913fba3fc54413881af751c610Andreas Huber    int64_t targetSampleTimeUs = -1ll;
7715ec58d925520e6913fba3fc54413881af751c610Andreas Huber
77250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    int64_t seekTimeUs;
77350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    ReadOptions::SeekMode mode;
774d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
775d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang        if (mode == ReadOptions::SEEK_FRAME_INDEX) {
776d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang            return ERROR_UNSUPPORTED;
777d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang        }
778d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang
779d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang        if (!mExtractor->isLiveStreaming()) {
780d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang            clearPendingFrames();
781d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang
782d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang            // The audio we want is located by using the Cues to seek the video
783d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang            // stream to find the target Cluster then iterating to finalize for
784d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang            // audio.
785d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang            int64_t actualFrameTimeUs;
786d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang            mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs);
787d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang            if (mode == ReadOptions::SEEK_CLOSEST) {
788d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang                targetSampleTimeUs = actualFrameTimeUs;
789d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang            }
7905ec58d925520e6913fba3fc54413881af751c610Andreas Huber        }
79150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    }
79250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
79350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    while (mPendingFrames.empty()) {
79450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber        status_t err = readBlock();
79550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
79650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber        if (err != OK) {
79750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber            clearPendingFrames();
79850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
79950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber            return err;
80050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber        }
80150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    }
80250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
8031889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang    MediaBufferBase *frame = *mPendingFrames.begin();
80450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    mPendingFrames.erase(mPendingFrames.begin());
80550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
806f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik    if ((mType != AVC && mType != HEVC) || mNALSizeLen == 0) {
8075ec58d925520e6913fba3fc54413881af751c610Andreas Huber        if (targetSampleTimeUs >= 0ll) {
8083d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            frame->meta_data().setInt64(
8095ec58d925520e6913fba3fc54413881af751c610Andreas Huber                    kKeyTargetTime, targetSampleTimeUs);
8105ec58d925520e6913fba3fc54413881af751c610Andreas Huber        }
8115ec58d925520e6913fba3fc54413881af751c610Andreas Huber
81250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber        *out = frame;
81350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
81450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber        return OK;
81550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    }
81650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
817792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber    // Each input frame contains one or more NAL fragments, each fragment
818792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber    // is prefixed by mNALSizeLen bytes giving the fragment length,
819792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber    // followed by a corresponding number of bytes containing the fragment.
820792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber    // We output all these fragments into a single large buffer separated
821792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber    // by startcodes (0x00 0x00 0x00 0x01).
8224f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    //
8234f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    // When mNALSizeLen is 0, we assume the data is already in the format
8244f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    // desired.
825792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber
826792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber    const uint8_t *srcPtr =
827792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber        (const uint8_t *)frame->data() + frame->range_offset();
828792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber
829792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber    size_t srcSize = frame->range_length();
830792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber
831792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber    size_t dstSize = 0;
8321889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang    MediaBufferBase *buffer = NULL;
833792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber    uint8_t *dstPtr = NULL;
834792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber
835792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber    for (int32_t pass = 0; pass < 2; ++pass) {
836792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber        size_t srcOffset = 0;
837792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber        size_t dstOffset = 0;
838792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber        while (srcOffset + mNALSizeLen <= srcSize) {
839792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            size_t NALsize;
840792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            switch (mNALSizeLen) {
841792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber                case 1: NALsize = srcPtr[srcOffset]; break;
842792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber                case 2: NALsize = U16_AT(srcPtr + srcOffset); break;
843792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber                case 3: NALsize = U24_AT(srcPtr + srcOffset); break;
844792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber                case 4: NALsize = U32_AT(srcPtr + srcOffset); break;
845792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber                default:
846792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber                    TRESPASS();
847792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            }
84850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
8492dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih            if (srcOffset + mNALSizeLen + NALsize <= srcOffset + mNALSizeLen) {
8502dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih                frame->release();
8512dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih                frame = NULL;
8522dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih
8532dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih                return ERROR_MALFORMED;
8542dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih            } else if (srcOffset + mNALSizeLen + NALsize > srcSize) {
855792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber                break;
856792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            }
85750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
858792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            if (pass == 1) {
859792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber                memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4);
86050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
861ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen                if (frame != buffer) {
862ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen                    memcpy(&dstPtr[dstOffset + 4],
863ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen                           &srcPtr[srcOffset + mNALSizeLen],
864ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen                           NALsize);
865ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen                }
866792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            }
86750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
868792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            dstOffset += 4;  // 0x00 00 00 01
869792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            dstOffset += NALsize;
87050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
871792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            srcOffset += mNALSizeLen + NALsize;
872792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber        }
87350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
874792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber        if (srcOffset < srcSize) {
875792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            // There were trailing bytes or not enough data to complete
876792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            // a fragment.
87750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
878792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            frame->release();
879792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            frame = NULL;
88050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
881792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            return ERROR_MALFORMED;
882792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber        }
88350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
884792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber        if (pass == 0) {
885792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            dstSize = dstOffset;
88650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
887ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen            if (dstSize == srcSize && mNALSizeLen == 4) {
888ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen                // In this special case we can re-use the input buffer by substituting
889ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen                // each 4-byte nal size with a 4-byte start code
890ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen                buffer = frame;
891ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen            } else {
8921889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang                buffer = MediaBufferBase::Create(dstSize);
893ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen            }
89450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
895792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            int64_t timeUs;
8963d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            CHECK(frame->meta_data().findInt64(kKeyTime, &timeUs));
897792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            int32_t isSync;
8983d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            CHECK(frame->meta_data().findInt32(kKeyIsSyncFrame, &isSync));
89950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
9003d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            buffer->meta_data().setInt64(kKeyTime, timeUs);
9013d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            buffer->meta_data().setInt32(kKeyIsSyncFrame, isSync);
90250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
903792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber            dstPtr = (uint8_t *)buffer->data();
904792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber        }
90550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    }
90650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
907ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen    if (frame != buffer) {
908ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen        frame->release();
909ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen        frame = NULL;
910ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen    }
91150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber
9125ec58d925520e6913fba3fc54413881af751c610Andreas Huber    if (targetSampleTimeUs >= 0ll) {
9133d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        buffer->meta_data().setInt64(
9145ec58d925520e6913fba3fc54413881af751c610Andreas Huber                kKeyTargetTime, targetSampleTimeUs);
9155ec58d925520e6913fba3fc54413881af751c610Andreas Huber    }
9165ec58d925520e6913fba3fc54413881af751c610Andreas Huber
91750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber    *out = buffer;
918093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
919093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return OK;
920093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
921093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
922093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber////////////////////////////////////////////////////////////////////////////////
923093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
9242a243f08193fe9ff1afe018e9953f01c44ced9deMarco NelissenMatroskaExtractor::MatroskaExtractor(DataSourceBase *source)
925093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    : mDataSource(source),
9262a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen      mReader(new DataSourceBaseReader(mDataSource)),
9275279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber      mSegment(NULL),
9288c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber      mExtractedThumbnails(false),
929bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian      mIsWebm(false),
930bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian      mSeekPreRollNs(0) {
931d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    off64_t size;
932d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    mIsLiveStreaming =
933d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        (mDataSource->flags()
9342a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen            & (DataSourceBase::kWantsPrefetching
9352a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen                | DataSourceBase::kIsCachingDataSource))
936d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        && mDataSource->getSize(&size) != OK;
937d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
938093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    mkvparser::EBMLHeader ebmlHeader;
939093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    long long pos;
940093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (ebmlHeader.Parse(mReader, pos) < 0) {
941093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return;
942093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
943093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
9448c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber    if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) {
9458c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber        mIsWebm = true;
9468c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber    }
9478c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber
948093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    long long ret =
949093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        mkvparser::Segment::CreateInstance(mReader, pos, mSegment);
950093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
951093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (ret) {
952093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        CHECK(mSegment == NULL);
953093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return;
954093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
955093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
956c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar    // from mkvparser::Segment::Load(), but stop at first cluster
95710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann    ret = mSegment->ParseHeaders();
958c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar    if (ret == 0) {
959c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar        long len;
960c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar        ret = mSegment->LoadCluster(pos, len);
961c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar        if (ret >= 1) {
962c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar            // no more clusters
963c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar            ret = 0;
964c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar        }
965c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar    } else if (ret > 0) {
966c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar        ret = mkvparser::E_BUFFER_NOT_FULL;
967c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar    }
968093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
969093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (ret < 0) {
970b486b52b2b67961073677d583a02269cbdc9a3fcDongwon Kang        char uri[1024];
971b486b52b2b67961073677d583a02269cbdc9a3fcDongwon Kang        if(!mDataSource->getUri(uri, sizeof(uri))) {
972b486b52b2b67961073677d583a02269cbdc9a3fcDongwon Kang            uri[0] = '\0';
973b486b52b2b67961073677d583a02269cbdc9a3fcDongwon Kang        }
974c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar        ALOGW("Corrupt %s source: %s", mIsWebm ? "webm" : "matroska",
975b486b52b2b67961073677d583a02269cbdc9a3fcDongwon Kang                uriDebugString(uri).c_str());
976093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        delete mSegment;
977093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        mSegment = NULL;
978093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return;
979093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
980093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
98174a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber#if 0
98274a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber    const mkvparser::SegmentInfo *info = mSegment->GetInfo();
983df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("muxing app: %s, writing app: %s",
98474a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber         info->GetMuxingAppAsUTF8(),
98574a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber         info->GetWritingAppAsUTF8());
98674a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber#endif
98774a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber
988093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    addTracks();
989093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
990093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
991093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::~MatroskaExtractor() {
992093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    delete mSegment;
993093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    mSegment = NULL;
994093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
995093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    delete mReader;
996093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    mReader = NULL;
997093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
998093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
999093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersize_t MatroskaExtractor::countTracks() {
1000093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return mTracks.size();
1001093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
1002093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
10033d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco NelissenMediaTrack *MatroskaExtractor::getTrack(size_t index) {
1004093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (index >= mTracks.size()) {
1005093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return NULL;
1006093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
1007093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1008093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return new MatroskaSource(this, index);
1009093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
1010093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
10113d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t MatroskaExtractor::getTrackMetaData(
10123d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        MetaDataBase &meta,
1013093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        size_t index, uint32_t flags) {
1014093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (index >= mTracks.size()) {
10153d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        return UNKNOWN_ERROR;
1016093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
1017093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1018d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails
1019d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber            && !isLiveStreaming()) {
10205279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        findThumbnails();
10215279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        mExtractedThumbnails = true;
10225279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    }
10235279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
10243d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    meta = mTracks.itemAt(index).mMeta;
10253d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    return OK;
1026093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
1027093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1028d42573cace9db2b5948e540c32beaef80f04153cAndreas Huberbool MatroskaExtractor::isLiveStreaming() const {
1029d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    return mIsLiveStreaming;
1030d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber}
1031d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
1032403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissenstatic int bytesForSize(size_t size) {
1033403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    // use at most 28 bits (4 times 7)
1034403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    CHECK(size <= 0xfffffff);
1035403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen
1036403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    if (size > 0x1fffff) {
1037403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen        return 4;
1038403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    } else if (size > 0x3fff) {
1039403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen        return 3;
1040403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    } else if (size > 0x7f) {
1041403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen        return 2;
1042403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    }
1043403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    return 1;
1044403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen}
1045403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen
1046403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissenstatic void storeSize(uint8_t *data, size_t &idx, size_t size) {
1047403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    int numBytes = bytesForSize(size);
1048403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    idx += numBytes;
1049403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen
1050403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    data += idx;
1051403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    size_t next = 0;
1052403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    while (numBytes--) {
1053403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen        *--data = (size & 0x7f) | next;
1054403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen        size >>= 7;
1055403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen        next = 0x80;
1056403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    }
1057403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen}
1058403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen
1059132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kangstatic void addESDSFromCodecPrivate(
10603d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        MetaDataBase &meta,
1061132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang        bool isAudio, const void *priv, size_t privSize) {
1062093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1063403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    int privSizeBytesRequired = bytesForSize(privSize);
1064403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    int esdsSize2 = 14 + privSizeBytesRequired + privSize;
1065403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    int esdsSize2BytesRequired = bytesForSize(esdsSize2);
1066403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2;
1067403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    int esdsSize1BytesRequired = bytesForSize(esdsSize1);
1068403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1;
1069093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    uint8_t *esds = new uint8_t[esdsSize];
1070403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen
1071403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    size_t idx = 0;
1072403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    esds[idx++] = 0x03;
1073403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    storeSize(esds, idx, esdsSize1);
1074403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    esds[idx++] = 0x00; // ES_ID
1075403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    esds[idx++] = 0x00; // ES_ID
1076403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
1077403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    esds[idx++] = 0x04;
1078403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    storeSize(esds, idx, esdsSize2);
1079403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    esds[idx++] = isAudio ? 0x40   // Audio ISO/IEC 14496-3
1080403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen                          : 0x20;  // Visual ISO/IEC 14496-2
1081403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    for (int i = 0; i < 12; i++) {
1082403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen        esds[idx++] = 0x00;
1083403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    }
1084403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    esds[idx++] = 0x05;
1085403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    storeSize(esds, idx, privSize);
1086403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen    memcpy(esds + idx, priv, privSize);
108782ac8bf2da940c4439786c346f739f4a496864adAndreas Huber
10883d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    meta.setData(kKeyESDS, 0, esds, esdsSize);
1089093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1090093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    delete[] esds;
1091093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    esds = NULL;
1092093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
1093093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
10945ce181568da90c78ba7fad3e084c8479041545dfAndreas Huberstatus_t addVorbisCodecInfo(
10953d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        MetaDataBase &meta,
1096093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        const void *_codecPrivate, size_t codecPrivateSize) {
1097093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    // hexdump(_codecPrivate, codecPrivateSize);
1098093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
10995ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    if (codecPrivateSize < 1) {
11005ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        return ERROR_MALFORMED;
11015ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    }
1102093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1103093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate;
1104093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
11055ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    if (codecPrivate[0] != 0x02) {
11065ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        return ERROR_MALFORMED;
11075ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    }
1108093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
11095ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    // codecInfo starts with two lengths, len1 and len2, that are
11105ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    // "Xiph-style-lacing encoded"...
1111093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
11125ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    size_t offset = 1;
11135ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    size_t len1 = 0;
11145ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) {
11157d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen        if (len1 > (SIZE_MAX - 0xff)) {
11167d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen            return ERROR_MALFORMED; // would overflow
11177d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen        }
11185ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        len1 += 0xff;
11195ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        ++offset;
11205ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    }
11215ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    if (offset >= codecPrivateSize) {
11225ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        return ERROR_MALFORMED;
11235ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    }
11247d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen    if (len1 > (SIZE_MAX - codecPrivate[offset])) {
11257d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen        return ERROR_MALFORMED; // would overflow
11267d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen    }
11275ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    len1 += codecPrivate[offset++];
1128093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
11295ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    size_t len2 = 0;
11305ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) {
11317d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen        if (len2 > (SIZE_MAX - 0xff)) {
11327d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen            return ERROR_MALFORMED; // would overflow
11337d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen        }
11345ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        len2 += 0xff;
11355ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        ++offset;
11365ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    }
11375ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    if (offset >= codecPrivateSize) {
11385ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        return ERROR_MALFORMED;
11395ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    }
11407d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen    if (len2 > (SIZE_MAX - codecPrivate[offset])) {
11417d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen        return ERROR_MALFORMED; // would overflow
11427d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen    }
11435ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    len2 += codecPrivate[offset++];
11445ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber
11457d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen    if (len1 > SIZE_MAX - len2 || offset > SIZE_MAX - (len1 + len2) ||
11467d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen            codecPrivateSize < offset + len1 + len2) {
11475ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        return ERROR_MALFORMED;
11485ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    }
11495ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber
11505ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    if (codecPrivate[offset] != 0x01) {
11515ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        return ERROR_MALFORMED;
11525ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    }
11533d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    meta.setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1);
11545ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber
11555ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    offset += len1;
11565ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    if (codecPrivate[offset] != 0x03) {
11575ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        return ERROR_MALFORMED;
11585ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    }
11595ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber
11605ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    offset += len2;
11615ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    if (codecPrivate[offset] != 0x05) {
11625ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        return ERROR_MALFORMED;
11635ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    }
1164093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
11653d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    meta.setData(
11665ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber            kKeyVorbisBooks, 0, &codecPrivate[offset],
11675ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber            codecPrivateSize - offset);
11685ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber
11695ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber    return OK;
1170093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
1171093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1172f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jiastatic status_t addFlacMetadata(
11733d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        MetaDataBase &meta,
1174f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia        const void *codecPrivate, size_t codecPrivateSize) {
1175f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia    // hexdump(codecPrivate, codecPrivateSize);
1176f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia
11773d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    meta.setData(kKeyFlacMetadata, 0, codecPrivate, codecPrivateSize);
1178f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia
1179f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia    int32_t maxInputSize = 64 << 10;
1180a1a005fc01118685c92e723c8dcf7afeffc9d59cMarco Nelissen    FLACDecoder *flacDecoder = FLACDecoder::Create();
1181f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia    if (flacDecoder != NULL
1182f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia            && flacDecoder->parseMetadata((const uint8_t*)codecPrivate, codecPrivateSize) == OK) {
1183f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia        FLAC__StreamMetadata_StreamInfo streamInfo = flacDecoder->getStreamInfo();
1184f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia        maxInputSize = streamInfo.max_framesize;
1185f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia        if (maxInputSize == 0) {
1186f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia            // In case max framesize is not available, use raw data size as max framesize,
1187f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia            // assuming there is no expansion.
1188f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia            if (streamInfo.max_blocksize != 0
1189f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia                    && streamInfo.channels != 0
1190f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia                    && ((streamInfo.bits_per_sample + 7) / 8) >
1191f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia                        INT32_MAX / streamInfo.max_blocksize / streamInfo.channels) {
1192a1a005fc01118685c92e723c8dcf7afeffc9d59cMarco Nelissen                delete flacDecoder;
1193f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia                return ERROR_MALFORMED;
1194f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia            }
1195f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia            maxInputSize = ((streamInfo.bits_per_sample + 7) / 8)
1196f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia                * streamInfo.max_blocksize * streamInfo.channels;
1197f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia        }
1198f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia    }
11993d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    meta.setInt32(kKeyMaxInputSize, maxInputSize);
1200f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia
1201a1a005fc01118685c92e723c8dcf7afeffc9d59cMarco Nelissen    delete flacDecoder;
1202f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia    return OK;
1203f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia}
1204f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia
12054f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shihstatus_t MatroskaExtractor::synthesizeAVCC(TrackInfo *trackInfo, size_t index) {
12064f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    BlockIterator iter(this, trackInfo->mTrackNum, index);
12074f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    if (iter.eos()) {
12084f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih        return ERROR_MALFORMED;
12094f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    }
12104f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih
12114f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    const mkvparser::Block *block = iter.block();
12124f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    if (block->GetFrameCount() <= 0) {
12134f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih        return ERROR_MALFORMED;
12144f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    }
12154f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih
12164f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    const mkvparser::Block::Frame &frame = block->GetFrame(0);
1217a1a005fc01118685c92e723c8dcf7afeffc9d59cMarco Nelissen    auto tmpData = heapbuffer<unsigned char>(frame.len);
1218a1a005fc01118685c92e723c8dcf7afeffc9d59cMarco Nelissen    long n = frame.Read(mReader, tmpData.get());
12194f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    if (n != 0) {
12204f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih        return ERROR_MALFORMED;
12214f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    }
12224f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih
1223a1a005fc01118685c92e723c8dcf7afeffc9d59cMarco Nelissen    if (!MakeAVCCodecSpecificData(trackInfo->mMeta, tmpData.get(), frame.len)) {
12244f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih        return ERROR_MALFORMED;
12254f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    }
12264f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih
12274f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    // Override the synthesized nal length size, which is arbitrary
12283d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    trackInfo->mMeta.setInt32(kKeyNalLengthSize, 0);
12294f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih    return OK;
12304f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih}
12314f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih
1232d637d296bb0954756d3d231633fad73fadd70316Lajos Molnarstatic inline bool isValidInt32ColourValue(long long value) {
1233d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar    return value != mkvparser::Colour::kValueNotPresent
1234d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            && value >= INT32_MIN
1235d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            && value <= INT32_MAX;
1236d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar}
1237d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar
1238d637d296bb0954756d3d231633fad73fadd70316Lajos Molnarstatic inline bool isValidUint16ColourValue(long long value) {
1239d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar    return value != mkvparser::Colour::kValueNotPresent
1240d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            && value >= 0
1241d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            && value <= UINT16_MAX;
1242d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar}
1243d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar
1244d637d296bb0954756d3d231633fad73fadd70316Lajos Molnarstatic inline bool isValidPrimary(const mkvparser::PrimaryChromaticity *primary) {
1245d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar    return primary != NULL && primary->x >= 0 && primary->x <= 1
1246d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar             && primary->y >= 0 && primary->y <= 1;
1247d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar}
1248d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar
1249d637d296bb0954756d3d231633fad73fadd70316Lajos Molnarvoid MatroskaExtractor::getColorInformation(
12503d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        const mkvparser::VideoTrack *vtrack, MetaDataBase &meta) {
1251d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar    const mkvparser::Colour *color = vtrack->GetColour();
1252d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar    if (color == NULL) {
1253d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        return;
1254d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar    }
1255d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar
1256d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar    // Color Aspects
1257d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar    {
1258d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        int32_t primaries = 2; // ISO unspecified
1259d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        int32_t transfer = 2; // ISO unspecified
1260d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        int32_t coeffs = 2; // ISO unspecified
1261d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        bool fullRange = false; // default
1262d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        bool rangeSpecified = false;
1263d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar
1264d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        if (isValidInt32ColourValue(color->primaries)) {
1265d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            primaries = color->primaries;
1266d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        }
1267d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        if (isValidInt32ColourValue(color->transfer_characteristics)) {
1268d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            transfer = color->transfer_characteristics;
1269d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        }
1270d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        if (isValidInt32ColourValue(color->matrix_coefficients)) {
1271d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            coeffs = color->matrix_coefficients;
1272d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        }
1273d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        if (color->range != mkvparser::Colour::kValueNotPresent
1274d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                && color->range != 0 /* MKV unspecified */) {
1275d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            // We only support MKV broadcast range (== limited) and full range.
1276d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            // We treat all other value as the default limited range.
1277d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            fullRange = color->range == 2 /* MKV fullRange */;
1278d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            rangeSpecified = true;
1279d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        }
1280d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar
1281d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        ColorAspects aspects;
1282d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        ColorUtils::convertIsoColorAspectsToCodecAspects(
1283d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                primaries, transfer, coeffs, fullRange, aspects);
12843d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        meta.setInt32(kKeyColorPrimaries, aspects.mPrimaries);
12853d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        meta.setInt32(kKeyTransferFunction, aspects.mTransfer);
12863d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        meta.setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
12873d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        meta.setInt32(
1288d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                kKeyColorRange, rangeSpecified ? aspects.mRange : ColorAspects::RangeUnspecified);
1289d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar    }
1290d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar
1291d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar    // HDR Static Info
1292d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar    {
1293d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        HDRStaticInfo info, nullInfo; // nullInfo is a fully unspecified static info
1294d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        memset(&info, 0, sizeof(info));
1295d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        memset(&nullInfo, 0, sizeof(nullInfo));
1296d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        if (isValidUint16ColourValue(color->max_cll)) {
1297d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            info.sType1.mMaxContentLightLevel = color->max_cll;
1298d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        }
1299d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        if (isValidUint16ColourValue(color->max_fall)) {
1300d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            info.sType1.mMaxFrameAverageLightLevel = color->max_fall;
1301d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        }
1302d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        const mkvparser::MasteringMetadata *mastering = color->mastering_metadata;
1303d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        if (mastering != NULL) {
1304d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            // Convert matroska values to HDRStaticInfo equivalent values for each fully specified
1305d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            // group. See CTA-681.3 section 3.2.1 for more info.
1306d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            if (mastering->luminance_max >= 0.5 && mastering->luminance_max < 65535.5) {
1307d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                info.sType1.mMaxDisplayLuminance = (uint16_t)(mastering->luminance_max + 0.5);
1308d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            }
1309d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            if (mastering->luminance_min >= 0.00005 && mastering->luminance_min < 6.55355) {
131012c703291529dd19bb83579f1e3b33ecb444340dLajos Molnar                // HDRStaticInfo Type1 stores min luminance scaled 10000:1
1311d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                info.sType1.mMinDisplayLuminance =
1312d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                    (uint16_t)(10000 * mastering->luminance_min + 0.5);
1313d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            }
131412c703291529dd19bb83579f1e3b33ecb444340dLajos Molnar            // HDRStaticInfo Type1 stores primaries scaled 50000:1
1315d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            if (isValidPrimary(mastering->white_point)) {
1316d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                info.sType1.mW.x = (uint16_t)(50000 * mastering->white_point->x + 0.5);
1317d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                info.sType1.mW.y = (uint16_t)(50000 * mastering->white_point->y + 0.5);
1318d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            }
1319d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            if (isValidPrimary(mastering->r) && isValidPrimary(mastering->g)
1320d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                    && isValidPrimary(mastering->b)) {
1321d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                info.sType1.mR.x = (uint16_t)(50000 * mastering->r->x + 0.5);
1322d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                info.sType1.mR.y = (uint16_t)(50000 * mastering->r->y + 0.5);
1323d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                info.sType1.mG.x = (uint16_t)(50000 * mastering->g->x + 0.5);
1324d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                info.sType1.mG.y = (uint16_t)(50000 * mastering->g->y + 0.5);
1325d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                info.sType1.mB.x = (uint16_t)(50000 * mastering->b->x + 0.5);
1326d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                info.sType1.mB.y = (uint16_t)(50000 * mastering->b->y + 0.5);
1327d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            }
1328d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        }
1329d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        // Only advertise static info if at least one of the groups have been specified.
1330d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        if (memcmp(&info, &nullInfo, sizeof(info)) != 0) {
1331d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar            info.mID = HDRStaticInfo::kType1;
13323d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            meta.setData(kKeyHdrStaticInfo, 'hdrS', &info, sizeof(info));
1333d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar        }
1334d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar    }
1335d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar}
1336d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar
1337580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shihstatus_t MatroskaExtractor::initTrackInfo(
13383d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        const mkvparser::Track *track, MetaDataBase &meta, TrackInfo *trackInfo) {
1339580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih    trackInfo->mTrackNum = track->GetNumber();
1340580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih    trackInfo->mMeta = meta;
1341580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih    trackInfo->mExtractor = this;
1342580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih    trackInfo->mEncrypted = false;
1343580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih    trackInfo->mHeader = NULL;
1344580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih    trackInfo->mHeaderLen = 0;
1345580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih
1346580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih    for(size_t i = 0; i < track->GetContentEncodingCount(); i++) {
1347580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        const mkvparser::ContentEncoding *encoding = track->GetContentEncodingByIndex(i);
1348580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        for(size_t j = 0; j < encoding->GetEncryptionCount(); j++) {
1349580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih            const mkvparser::ContentEncoding::ContentEncryption *encryption;
1350580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih            encryption = encoding->GetEncryptionByIndex(j);
13513d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            trackInfo->mMeta.setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len);
1352580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih            trackInfo->mEncrypted = true;
1353580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih            break;
1354580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        }
1355580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih
1356580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        for(size_t j = 0; j < encoding->GetCompressionCount(); j++) {
1357580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih            const mkvparser::ContentEncoding::ContentCompression *compression;
1358580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih            compression = encoding->GetCompressionByIndex(j);
1359580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih            ALOGV("compression algo %llu settings_len %lld",
1360580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih                compression->algo, compression->settings_len);
1361580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih            if (compression->algo == 3
1362580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih                    && compression->settings
1363580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih                    && compression->settings_len > 0) {
1364580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih                trackInfo->mHeader = compression->settings;
1365580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih                trackInfo->mHeaderLen = compression->settings_len;
1366580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih            }
1367580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        }
1368580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih    }
1369580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih
1370580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih    return OK;
1371580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih}
1372580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih
1373093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubervoid MatroskaExtractor::addTracks() {
1374093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    const mkvparser::Tracks *tracks = mSegment->GetTracks();
1375093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1376093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    for (size_t index = 0; index < tracks->GetTracksCount(); ++index) {
1377093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        const mkvparser::Track *track = tracks->GetTrackByIndex(index);
1378093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
137930ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber        if (track == NULL) {
138030ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber            // Apparently this is currently valid (if unexpected) behaviour
138130ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber            // of the mkv parser lib.
138230ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber            continue;
138330ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber        }
138430ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber
1385093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        const char *const codecID = track->GetCodecId();
13863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("codec id = %s", codecID);
13873856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("codec name = %s", track->GetCodecNameAsUTF8());
1388093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
13891e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih        if (codecID == NULL) {
13901e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih            ALOGW("unknown codecID is not supported.");
13911e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih            continue;
13921e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih        }
13931e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih
1394093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        size_t codecPrivateSize;
1395093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        const unsigned char *codecPrivate =
1396ff1df9951d09f1a1a8ae2dbc42b82b0f9c164e5eAndreas Huber            track->GetCodecPrivate(codecPrivateSize);
1397093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1398093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
1399093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
14003d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        MetaDataBase meta;
1401093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
14025ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        status_t err = OK;
14035ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber
1404093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        switch (track->GetType()) {
1405093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            case VIDEO_TRACK:
1406093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            {
1407093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                const mkvparser::VideoTrack *vtrack =
1408093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    static_cast<const mkvparser::VideoTrack *>(track);
1409093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
14101e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih                if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
14113d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
14123d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    meta.setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
1413f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik                } else if (!strcmp("V_MPEGH/ISO/HEVC", codecID)) {
14143d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
1415f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik                    if (codecPrivateSize > 0) {
14163d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                        meta.setData(kKeyHVCC, kTypeHVCC, codecPrivate, codecPrivateSize);
1417f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik                    } else {
1418f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik                        ALOGW("HEVC is detected, but does not have configuration.");
1419f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik                        continue;
1420f69544accbbe7cade5d9a63f632fdb460ade3e19Patrik                    }
1421132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) {
1422132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                    if (codecPrivateSize > 0) {
14233d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                        meta.setCString(
1424132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                                kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
1425132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                        addESDSFromCodecPrivate(
1426132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                                meta, false, codecPrivate, codecPrivateSize);
1427132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                    } else {
1428132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                        ALOGW("%s is detected, but does not have configuration.",
1429132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                                codecID);
1430132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                        continue;
1431132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                    }
1432093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                } else if (!strcmp("V_VP8", codecID)) {
14333d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
143494705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang                } else if (!strcmp("V_VP9", codecID)) {
14353d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9);
1436d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian                    if (codecPrivateSize > 0) {
1437d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian                      // 'csd-0' for VP9 is the Blob of Codec Private data as
1438d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian                      // specified in http://www.webmproject.org/vp9/profiles/.
14393d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                        meta.setData(
1440d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian                              kKeyVp9CodecPrivate, 0, codecPrivate,
1441d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian                              codecPrivateSize);
1442d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian                    }
1443093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                } else {
1444132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                    ALOGW("%s is not supported.", codecID);
1445093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    continue;
1446093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                }
1447093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1448917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                const long long width = vtrack->GetWidth();
1449917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                const long long height = vtrack->GetHeight();
1450917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                if (width <= 0 || width > INT32_MAX) {
1451917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                    ALOGW("track width exceeds int32_t, %lld", width);
1452917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                    continue;
1453917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                }
1454917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                if (height <= 0 || height > INT32_MAX) {
1455917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                    ALOGW("track height exceeds int32_t, %lld", height);
1456917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                    continue;
1457917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                }
14583d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                meta.setInt32(kKeyWidth, (int32_t)width);
14593d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                meta.setInt32(kKeyHeight, (int32_t)height);
1460917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung
1461917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                // setting display width/height is optional
1462917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                const long long displayUnit = vtrack->GetDisplayUnit();
1463917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                const long long displayWidth = vtrack->GetDisplayWidth();
1464917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                const long long displayHeight = vtrack->GetDisplayHeight();
1465917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                if (displayWidth > 0 && displayWidth <= INT32_MAX
1466917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                        && displayHeight > 0 && displayHeight <= INT32_MAX) {
1467917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                    switch (displayUnit) {
1468917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                    case 0: // pixels
14693d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                        meta.setInt32(kKeyDisplayWidth, (int32_t)displayWidth);
14703d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                        meta.setInt32(kKeyDisplayHeight, (int32_t)displayHeight);
1471917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                        break;
1472917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                    case 1: // centimeters
1473917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                    case 2: // inches
1474917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                    case 3: // aspect ratio
1475917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                    {
1476917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                        // Physical layout size is treated the same as aspect ratio.
1477917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                        // Note: displayWidth and displayHeight are never zero as they are
1478917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                        // checked in the if above.
1479917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                        const long long computedWidth =
1480917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                                std::max(width, height * displayWidth / displayHeight);
1481917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                        const long long computedHeight =
1482917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                                std::max(height, width * displayHeight / displayWidth);
1483917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                        if (computedWidth <= INT32_MAX && computedHeight <= INT32_MAX) {
14843d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                            meta.setInt32(kKeyDisplayWidth, (int32_t)computedWidth);
14853d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                            meta.setInt32(kKeyDisplayHeight, (int32_t)computedHeight);
1486917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                        }
1487917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                        break;
1488917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                    }
1489917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                    default: // unknown display units, perhaps future version of spec.
1490917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                        break;
1491917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                    }
1492917da0898ee9b501b656d90f11c5eecc3d78b5c7Andy Hung                }
1493d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar
1494d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar                getColorInformation(vtrack, meta);
1495d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar
1496093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                break;
1497093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            }
1498093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1499093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            case AUDIO_TRACK:
1500093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            {
1501093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                const mkvparser::AudioTrack *atrack =
1502093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    static_cast<const mkvparser::AudioTrack *>(track);
1503093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1504093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                if (!strcmp("A_AAC", codecID)) {
15053d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
1506093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    CHECK(codecPrivateSize >= 2);
1507093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1508132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                    addESDSFromCodecPrivate(
1509132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                            meta, true, codecPrivate, codecPrivateSize);
1510093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                } else if (!strcmp("A_VORBIS", codecID)) {
15113d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
1512093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
15135ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber                    err = addVorbisCodecInfo(
15145ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber                            meta, codecPrivate, codecPrivateSize);
1515bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian                } else if (!strcmp("A_OPUS", codecID)) {
15163d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
15173d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    meta.setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize);
15183d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    meta.setInt64(kKeyOpusCodecDelay, track->GetCodecDelay());
15193d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    meta.setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll());
1520bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian                    mSeekPreRollNs = track->GetSeekPreRoll();
1521132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                } else if (!strcmp("A_MPEG/L3", codecID)) {
15223d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
1523f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia                } else if (!strcmp("A_FLAC", codecID)) {
15243d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FLAC);
1525f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia                    err = addFlacMetadata(meta, codecPrivate, codecPrivateSize);
1526093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                } else {
1527132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang                    ALOGW("%s is not supported.", codecID);
1528093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                    continue;
1529093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                }
1530093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
15313d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                meta.setInt32(kKeySampleRate, atrack->GetSamplingRate());
15323d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                meta.setInt32(kKeyChannelCount, atrack->GetChannels());
1533093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                break;
1534093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            }
1535093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1536093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            default:
1537093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                continue;
1538093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
1539093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
15400c411418d01d477b60f087f7bc685cf176ae197cPatrik        const char *language = track->GetLanguage();
15410c411418d01d477b60f087f7bc685cf176ae197cPatrik        if (language != NULL) {
15420c411418d01d477b60f087f7bc685cf176ae197cPatrik           char lang[4];
15430c411418d01d477b60f087f7bc685cf176ae197cPatrik           strncpy(lang, language, 3);
15440c411418d01d477b60f087f7bc685cf176ae197cPatrik           lang[3] = '\0';
15453d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen           meta.setCString(kKeyMediaLanguage, lang);
15460c411418d01d477b60f087f7bc685cf176ae197cPatrik        }
15470c411418d01d477b60f087f7bc685cf176ae197cPatrik
15485ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        if (err != OK) {
15495ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber            ALOGE("skipping track, codec specific data was malformed.");
15505ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber            continue;
15515ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber        }
15525ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber
1553093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        long long durationNs = mSegment->GetDuration();
15543d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        meta.setInt64(kKeyDuration, (durationNs + 500) / 1000);
1555093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1556093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        mTracks.push();
15574f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih        size_t n = mTracks.size() - 1;
15584f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih        TrackInfo *trackInfo = &mTracks.editItemAt(n);
1559580baf5c24f47e95eb3aeef94c51a920f1f426b1Robert Shih        initTrackInfo(track, meta, trackInfo);
15604f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih
15614f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih        if (!strcmp("V_MPEG4/ISO/AVC", codecID) && codecPrivateSize == 0) {
15624f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih            // Attempt to recover from AVC track without codec private data
15634f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih            err = synthesizeAVCC(trackInfo, n);
15644f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih            if (err != OK) {
15654f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih                mTracks.pop();
15664f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih            }
15674f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih        }
1568093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
1569093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
1570093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
15715279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid MatroskaExtractor::findThumbnails() {
15725279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    for (size_t i = 0; i < mTracks.size(); ++i) {
15735279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        TrackInfo *info = &mTracks.editItemAt(i);
15745279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
15755279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        const char *mime;
15763d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        CHECK(info->mMeta.findCString(kKeyMIMEType, &mime));
15775279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
15785279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        if (strncasecmp(mime, "video/", 6)) {
15795279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber            continue;
15805279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        }
15815279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
15822f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih        BlockIterator iter(this, info->mTrackNum, i);
15834719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer        int32_t j = 0;
15845279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        int64_t thumbnailTimeUs = 0;
15855279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        size_t maxBlockSize = 0;
15864719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer        while (!iter.eos() && j < 20) {
15875279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber            if (iter.block()->IsKey()) {
15884719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer                ++j;
15895279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
1590d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber                size_t blockSize = 0;
1591cba4ed0039c8b8fac01b3193d19fc2364f934506Tareq A. Siraj                for (int k = 0; k < iter.block()->GetFrameCount(); ++k) {
1592cba4ed0039c8b8fac01b3193d19fc2364f934506Tareq A. Siraj                    blockSize += iter.block()->GetFrame(k).len;
1593d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber                }
1594d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
15955279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber                if (blockSize > maxBlockSize) {
15965279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber                    maxBlockSize = blockSize;
15975279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber                    thumbnailTimeUs = iter.blockTimeUs();
15985279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber                }
15995279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber            }
16005279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber            iter.advance();
16015279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber        }
16023d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen        info->mMeta.setInt64(kKeyThumbnailTime, thumbnailTimeUs);
16035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber    }
16045279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}
16055279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber
16063d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t MatroskaExtractor::getMetaData(MetaDataBase &meta) {
16073d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    meta.setCString(
16088c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber            kKeyMIMEType,
16098c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber            mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA);
1610093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
16113d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    return OK;
1612093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
1613093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1614d42573cace9db2b5948e540c32beaef80f04153cAndreas Huberuint32_t MatroskaExtractor::flags() const {
1615d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    uint32_t x = CAN_PAUSE;
1616d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    if (!isLiveStreaming()) {
1617d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber        x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK;
1618d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    }
1619d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
1620d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber    return x;
1621d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber}
1622d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber
1623093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberbool SniffMatroska(
162417e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang        DataSourceBase *source, float *confidence) {
16252a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen    DataSourceBaseReader reader(source);
1626093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    mkvparser::EBMLHeader ebmlHeader;
1627093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    long long pos;
1628093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (ebmlHeader.Parse(&reader, pos) < 0) {
1629093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        return false;
1630093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
1631093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1632093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    *confidence = 0.6;
1633093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
1634093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    return true;
1635093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}
1636093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
163775226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen
163875226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissenextern "C" {
163975226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen// This is the only symbol that needs to be exported
164075226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen__attribute__ ((visibility ("default")))
164175226177f20a176d50e3e53bbb34067cb49112c3Marco NelissenMediaExtractor::ExtractorDef GETEXTRACTORDEF() {
164275226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen    return {
164375226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen        MediaExtractor::EXTRACTORDEF_VERSION,
164475226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen        UUID("abbedd92-38c4-4904-a4c1-b3f45f899980"),
164575226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen        1,
164675226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen        "Matroska Extractor",
164775226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen        [](
16482a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen                DataSourceBase *source,
164975226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen                float *confidence,
165017e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang                void **,
165117e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang                MediaExtractor::FreeMetaFunc *) -> MediaExtractor::CreatorFunc {
165217e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang            if (SniffMatroska(source, confidence)) {
165375226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen                return [](
16542a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen                        DataSourceBase *source,
165517e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang                        void *) -> MediaExtractor* {
165675226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen                    return new MatroskaExtractor(source);};
165775226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen            }
165875226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen            return NULL;
165975226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen        }
166075226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen    };
166175226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen}
166275226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen
166375226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen} // extern "C"
166475226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen
1665093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}  // namespace android
1666