MatroskaExtractor.cpp revision ba29bb20a18aa98813ce42f99cff4910a153e87c
1093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber/* 2093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * Copyright (C) 2010 The Android Open Source Project 3093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * 4093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * you may not use this file except in compliance with the License. 6093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * You may obtain a copy of the License at 7093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * 8093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * 10093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * Unless required by applicable law or agreed to in writing, software 11093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * See the License for the specific language governing permissions and 14093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * limitations under the License. 15093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber */ 16093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 17093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber//#define LOG_NDEBUG 0 18093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#define LOG_TAG "MatroskaExtractor" 19093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <utils/Log.h> 20093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 21093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include "MatroskaExtractor.h" 22093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 23b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber#include <media/stagefright/foundation/ADebug.h> 242dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih#include <media/stagefright/foundation/AUtils.h> 25b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber#include <media/stagefright/foundation/hexdump.h> 26093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/DataSource.h> 27093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaBuffer.h> 28093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaDefs.h> 29093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaErrors.h> 30093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaSource.h> 31093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MetaData.h> 32b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber#include <media/stagefright/Utils.h> 33093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <utils/String8.h> 34093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 35b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross#include <inttypes.h> 36b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross 37093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubernamespace android { 38093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 39093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstruct DataSourceReader : public mkvparser::IMkvReader { 40093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader(const sp<DataSource> &source) 41093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mSource(source) { 42093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 43093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 44093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual int Read(long long position, long length, unsigned char* buffer) { 45093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(position >= 0); 46093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(length >= 0); 47093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 48093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (length == 0) { 49093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 50093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 51093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 52093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber ssize_t n = mSource->readAt(position, buffer, length); 53093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 54093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (n <= 0) { 55093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return -1; 56093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 57093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 58093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 59093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 60093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 61093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual int Length(long long* total, long long* available) { 62c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t size; 63093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (mSource->getSize(&size) != OK) { 64d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber *total = -1; 65d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber *available = (long long)((1ull << 63) - 1); 66d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 67d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return 0; 68093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 69093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 70093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (total) { 71093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *total = size; 72093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 73093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 74093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (available) { 75093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *available = size; 76093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 77093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 78093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 79093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 80093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 81093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberprivate: 82093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<DataSource> mSource; 83093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 84093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader(const DataSourceReader &); 85093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader &operator=(const DataSourceReader &); 86093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}; 87093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 88093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber//////////////////////////////////////////////////////////////////////////////// 89093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 905279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberstruct BlockIterator { 912f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index); 925279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 935279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber bool eos() const; 945279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 955279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber void advance(); 965279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber void reset(); 975ec58d925520e6913fba3fc54413881af751c610Andreas Huber 985ec58d925520e6913fba3fc54413881af751c610Andreas Huber void seek( 99f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann int64_t seekTimeUs, bool isAudio, 1005ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t *actualFrameTimeUs); 1015279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1025279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::Block *block() const; 1035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t blockTimeUs() const; 1045279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1055279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberprivate: 106d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber MatroskaExtractor *mExtractor; 107b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross long long mTrackNum; 1082f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih unsigned long mIndex; 1095279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 110d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Cluster *mCluster; 1115279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::BlockEntry *mBlockEntry; 112d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long mBlockEntryIndex; 113d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 114d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber void advance_l(); 1155279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1165279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator(const BlockIterator &); 1175279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator &operator=(const BlockIterator &); 1185279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}; 1195279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 120093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstruct MatroskaSource : public MediaSource { 121093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource( 122093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MatroskaExtractor> &extractor, size_t index); 123093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 124093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t start(MetaData *params); 125093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t stop(); 126093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 127093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual sp<MetaData> getFormat(); 128093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 129093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t read( 130093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MediaBuffer **buffer, const ReadOptions *options); 131093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 13250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberprotected: 13350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber virtual ~MatroskaSource(); 13450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 135093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberprivate: 136093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber enum Type { 137093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber AVC, 138093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber AAC, 139093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber OTHER 140093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber }; 141093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 142093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MatroskaExtractor> mExtractor; 143093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t mTrackIndex; 144093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber Type mType; 14574a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber bool mIsAudio; 1465279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator mBlockIter; 147b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber size_t mNALSizeLen; // for type AVC 148093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 14950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber List<MediaBuffer *> mPendingFrames; 15050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 151093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber status_t advance(); 152093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 15350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber status_t readBlock(); 15450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber void clearPendingFrames(); 15550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 156093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource(const MatroskaSource &); 157093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource &operator=(const MatroskaSource &); 158093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}; 159093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1602f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shihconst mkvparser::Track* MatroskaExtractor::TrackInfo::getTrack() const { 1612f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return mExtractor->mSegment->GetTracks()->GetTrackByNumber(mTrackNum); 1622f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih} 1632f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 1642f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih// This function does exactly the same as mkvparser::Cues::Find, except that it 1652f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih// searches in our own track based vectors. We should not need this once mkvparser 1662f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih// adds the same functionality. 1672f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shihconst mkvparser::CuePoint::TrackPosition *MatroskaExtractor::TrackInfo::find( 1682f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih long long timeNs) const { 1692f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih ALOGV("mCuePoints.size %zu", mCuePoints.size()); 1702f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (mCuePoints.empty()) { 1712f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return NULL; 1722f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 1732f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 1742f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::CuePoint* cp = mCuePoints.itemAt(0); 1752f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::Track* track = getTrack(); 1762f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (timeNs <= cp->GetTime(mExtractor->mSegment)) { 1772f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return cp->Find(track); 1782f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 1792f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 1802f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih // Binary searches through relevant cues; assumes cues are ordered by timecode. 1812f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih // If we do detect out-of-order cues, return NULL. 1822f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih size_t lo = 0; 1832f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih size_t hi = mCuePoints.size(); 1842f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih while (lo < hi) { 1852f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const size_t mid = lo + (hi - lo) / 2; 1862f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::CuePoint* const midCp = mCuePoints.itemAt(mid); 1872f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const long long cueTimeNs = midCp->GetTime(mExtractor->mSegment); 1882f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (cueTimeNs <= timeNs) { 1892f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih lo = mid + 1; 1902f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } else { 1912f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih hi = mid; 1922f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 1932f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 1942f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 1952f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (lo == 0) { 1962f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return NULL; 1972f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 1982f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 1992f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih cp = mCuePoints.itemAt(lo - 1); 2002f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (cp->GetTime(mExtractor->mSegment) > timeNs) { 2012f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return NULL; 2022f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 2032f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 2042f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return cp->Find(track); 2052f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih} 2062f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 207093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaSource::MatroskaSource( 208093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MatroskaExtractor> &extractor, size_t index) 209093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mExtractor(extractor), 210093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mTrackIndex(index), 211093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType(OTHER), 21274a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber mIsAudio(false), 213d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter(mExtractor.get(), 2142f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih mExtractor->mTracks.itemAt(index).mTrackNum, 2152f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih index), 216b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber mNALSizeLen(0) { 217b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta; 218b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 219093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *mime; 220b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber CHECK(meta->findCString(kKeyMIMEType, &mime)); 221093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 22274a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber mIsAudio = !strncasecmp("audio/", mime, 6); 22374a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 224093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 225093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType = AVC; 226b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 227b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber uint32_t dummy; 228b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber const uint8_t *avcc; 229b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber size_t avccSize; 230b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber CHECK(meta->findData( 231b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)); 232b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 233b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber CHECK_GE(avccSize, 5u); 234b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 235b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber mNALSizeLen = 1 + (avcc[4] & 3); 236b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("mNALSizeLen = %zu", mNALSizeLen); 237093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 238093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType = AAC; 239093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 240093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 241093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 24250c8bea8fba2fcafb14696399028bdbc094dc995Andreas HuberMatroskaSource::~MatroskaSource() { 24350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 24450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 24550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 24684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MatroskaSource::start(MetaData * /* params */) { 2475279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mBlockIter.reset(); 248093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 249093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 250093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 251093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 252093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstatus_t MatroskaSource::stop() { 25350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 25450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 255093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 256093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 257093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 258093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaSource::getFormat() { 259093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mExtractor->mTracks.itemAt(mTrackIndex).mMeta; 260093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 261093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 2625279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber//////////////////////////////////////////////////////////////////////////////// 2635279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2645279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas HuberBlockIterator::BlockIterator( 2652f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index) 266d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber : mExtractor(extractor), 2675279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mTrackNum(trackNum), 2682f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih mIndex(index), 2695279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mCluster(NULL), 270d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntry(NULL), 271d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex(0) { 2725279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber reset(); 2735279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 2745279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2755279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberbool BlockIterator::eos() const { 2765279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return mCluster == NULL || mCluster->EOS(); 2775279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 2785279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2795279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::advance() { 280d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 281d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 282d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 283d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 284d42573cace9db2b5948e540c32beaef80f04153cAndreas Hubervoid BlockIterator::advance_l() { 285d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber for (;;) { 286d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry); 2873856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetEntry returned %ld", res); 288d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 289d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long long pos; 290d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long len; 291d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (res < 0) { 292d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // Need to parse this cluster some more 293d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 294d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL); 295d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 296d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mCluster->Parse(pos, len); 2973856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Parse returned %ld", res); 298d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 299d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (res < 0) { 300d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // I/O error 301d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 30229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cluster::Parse returned result %ld", res); 3035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 304d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = NULL; 3055279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber break; 306093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 3075279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 308d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber continue; 309d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } else if (res == 0) { 310d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // We're done with this cluster 311d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 312d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Cluster *nextCluster; 313d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mExtractor->mSegment->ParseNext( 314d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster, nextCluster, pos, len); 3153856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ParseNext returned %ld", res); 316d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 317e467ef084b75b074d0081616080b54212a7024c8Lajos Molnar if (res != 0) { 318e467ef084b75b074d0081616080b54212a7024c8Lajos Molnar // EOF or error 319d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 320d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = NULL; 321d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber break; 322d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 323d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 324d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_EQ(res, 0); 325d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(nextCluster != NULL); 326d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(!nextCluster->EOS()); 327d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 328d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = nextCluster; 329d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 330d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mCluster->Parse(pos, len); 3313856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Parse (2) returned %ld", res); 332d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_GE(res, 0); 333d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 334d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex = 0; 335d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber continue; 336093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 337093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 338d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(mBlockEntry != NULL); 339d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(mBlockEntry->GetBlock() != NULL); 340d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber ++mBlockEntryIndex; 341d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 342d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) { 3435279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber break; 344093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 3455279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 3465279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 3475279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 3485279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::reset() { 349d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 350093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 351d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = mExtractor->mSegment->GetFirst(); 3522ba7ce928b0fa8917ee202836b0963ca58613453Andreas Huber mBlockEntry = NULL; 353d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex = 0; 354d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 355d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber do { 356d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 357d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } while (!eos() && block()->GetTrackNumber() != mTrackNum); 3585279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 359093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 3605ec58d925520e6913fba3fc54413881af751c610Andreas Hubervoid BlockIterator::seek( 361f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann int64_t seekTimeUs, bool isAudio, 3625ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t *actualFrameTimeUs) { 363d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 364d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 3655ec58d925520e6913fba3fc54413881af751c610Andreas Huber *actualFrameTimeUs = -1ll; 3665ec58d925520e6913fba3fc54413881af751c610Andreas Huber 367bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const int64_t seekTimeNs = seekTimeUs * 1000ll - mExtractor->mSeekPreRollNs; 36810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 36910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mkvparser::Segment* const pSegment = mExtractor->mSegment; 37010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 37110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // Special case the 0 seek to avoid loading Cues when the application 37210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // extraneously seeks to 0 before playing. 37310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (seekTimeNs <= 0) { 374b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("Seek to beginning: %" PRId64, seekTimeUs); 37510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mCluster = pSegment->GetFirst(); 37610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mBlockEntryIndex = 0; 37710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann do { 37810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann advance_l(); 37910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } while (!eos() && block()->GetTrackNumber() != mTrackNum); 38010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 38110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 3825ec58d925520e6913fba3fc54413881af751c610Andreas Huber 383b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("Seeking to: %" PRId64, seekTimeUs); 38410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 38510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // If the Cues have not been located then find them. 38610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::Cues* pCues = pSegment->GetCues(); 38710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::SeekHead* pSH = pSegment->GetSeekHead(); 38810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (!pCues && pSH) { 38910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const size_t count = pSH->GetCount(); 39010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::SeekHead::Entry* pEntry; 39110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGV("No Cues yet"); 39210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 39310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann for (size_t index = 0; index < count; index++) { 39410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pEntry = pSH->GetEntry(index); 39510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 39610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (pEntry->id == 0x0C53BB6B) { // Cues ID 39710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann long len; long long pos; 39810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pSegment->ParseCues(pEntry->pos, pos, len); 39910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pCues = pSegment->GetCues(); 400be7ac3d682729048af27871311808a76c618abdbJohann ALOGV("Cues found"); 40110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann break; 40210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 40310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 40410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 40510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (!pCues) { 40610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGE("No Cues in file"); 40710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 40810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 40910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 41010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann else if (!pSH) { 41110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGE("No SeekHead"); 41210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 41310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 41410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 41510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::CuePoint* pCP; 4162f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih mkvparser::Tracks const *pTracks = pSegment->GetTracks(); 41710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann while (!pCues->DoneParsing()) { 418be7ac3d682729048af27871311808a76c618abdbJohann pCues->LoadCuePoint(); 41910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pCP = pCues->GetLast(); 4202f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih CHECK(pCP); 4212f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 4220644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih size_t trackCount = mExtractor->mTracks.size(); 4232f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih for (size_t index = 0; index < trackCount; ++index) { 4240644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(index); 4250644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih const mkvparser::Track *pTrack = pTracks->GetTrackByNumber(track.mTrackNum); 4262f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (pTrack && pTrack->GetType() == 1 && pCP->Find(pTrack)) { // VIDEO_TRACK 4272f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih track.mCuePoints.push_back(pCP); 4282f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 4292f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 430be7ac3d682729048af27871311808a76c618abdbJohann 43110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (pCP->GetTime(pSegment) >= seekTimeNs) { 432be7ac3d682729048af27871311808a76c618abdbJohann ALOGV("Parsed past relevant Cue"); 43310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann break; 43410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 43510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 43610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 4372f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::CuePoint::TrackPosition *pTP = NULL; 4380644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih const mkvparser::Track *thisTrack = pTracks->GetTrackByNumber(mTrackNum); 4392f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (thisTrack->GetType() == 1) { // video 4402f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(mIndex); 4412f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih pTP = track.find(seekTimeNs); 4422f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } else { 4432f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih // The Cue index is built around video keyframes 4440644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih unsigned long int trackCount = pTracks->GetTracksCount(); 4452f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih for (size_t index = 0; index < trackCount; ++index) { 4462f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::Track *pTrack = pTracks->GetTrackByIndex(index); 4472f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (pTrack && pTrack->GetType() == 1 && pCues->Find(seekTimeNs, pTrack, pCP, pTP)) { 4482f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih ALOGV("Video track located at %zu", index); 4492f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih break; 4502f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 45110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 45210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 45310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 4542f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 455f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // Always *search* based on the video track, but finalize based on mTrackNum 4562f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (!pTP) { 457f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann ALOGE("Did not locate the video track for seeking"); 45810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 45910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 46010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 46110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos); 4625279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 463f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK(mCluster); 464f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK(!mCluster->EOS()); 465f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann 466f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // mBlockEntryIndex starts at 0 but m_block starts at 1 467f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK_GT(pTP->m_block, 0); 468f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann mBlockEntryIndex = pTP->m_block - 1; 4695ec58d925520e6913fba3fc54413881af751c610Andreas Huber 4705ec58d925520e6913fba3fc54413881af751c610Andreas Huber for (;;) { 471d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 4725279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 473f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann if (eos()) break; 4745ec58d925520e6913fba3fc54413881af751c610Andreas Huber 475f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann if (isAudio || block()->IsKey()) { 476f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // Accept the first key frame 4772f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih int64_t frameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL; 4782f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (thisTrack->GetType() == 1 || frameTimeUs >= seekTimeUs) { 4792f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih *actualFrameTimeUs = frameTimeUs; 4802f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih ALOGV("Requested seek point: %" PRId64 " actual: %" PRId64, 4812f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih seekTimeUs, *actualFrameTimeUs); 4822f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih break; 4832f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 48474a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber } 4855279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 486093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 487093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 4885279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberconst mkvparser::Block *BlockIterator::block() const { 4895279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber CHECK(!eos()); 4905279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 4915279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return mBlockEntry->GetBlock(); 4925279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 4935279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 4945279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberint64_t BlockIterator::blockTimeUs() const { 4955279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll; 4965279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 4975279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 4985279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber//////////////////////////////////////////////////////////////////////////////// 4995279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 500b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huberstatic unsigned U24_AT(const uint8_t *ptr) { 501b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; 502b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber} 503b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 50450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Hubervoid MatroskaSource::clearPendingFrames() { 50550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (!mPendingFrames.empty()) { 50650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer *frame = *mPendingFrames.begin(); 50750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.erase(mPendingFrames.begin()); 50850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 50950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber frame->release(); 51050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber frame = NULL; 51150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 51250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 51350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 51450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatus_t MatroskaSource::readBlock() { 51550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber CHECK(mPendingFrames.empty()); 51650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 5175279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (mBlockIter.eos()) { 518093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return ERROR_END_OF_STREAM; 519093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 520093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 5215279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::Block *block = mBlockIter.block(); 52250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 5235279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t timeUs = mBlockIter.blockTimeUs(); 524093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 525d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber for (int i = 0; i < block->GetFrameCount(); ++i) { 526d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Block::Frame &frame = block->GetFrame(i); 527b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 528d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber MediaBuffer *mbuf = new MediaBuffer(frame.len); 529d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mbuf->meta_data()->setInt64(kKeyTime, timeUs); 530d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey()); 531093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 532d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data()); 533d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (n != 0) { 534d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mPendingFrames.clear(); 53550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 536d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter.advance(); 537ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen mbuf->release(); 538d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return ERROR_IO; 53950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 54050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 54150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.push_back(mbuf); 54250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 54350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 544d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter.advance(); 54550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 54650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return OK; 54750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 54850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 54950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatus_t MatroskaSource::read( 55050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer **out, const ReadOptions *options) { 55150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = NULL; 55250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 5535ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t targetSampleTimeUs = -1ll; 5545ec58d925520e6913fba3fc54413881af751c610Andreas Huber 55550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber int64_t seekTimeUs; 55650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber ReadOptions::SeekMode mode; 557d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode) 558d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && !mExtractor->isLiveStreaming()) { 55950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 56074a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 561f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // The audio we want is located by using the Cues to seek the video 562f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // stream to find the target Cluster then iterating to finalize for 563f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // audio. 5645ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t actualFrameTimeUs; 565f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs); 5665ec58d925520e6913fba3fc54413881af751c610Andreas Huber 5675ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 5685ec58d925520e6913fba3fc54413881af751c610Andreas Huber targetSampleTimeUs = actualFrameTimeUs; 5695ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 57050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 57150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 57250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (mPendingFrames.empty()) { 57350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber status_t err = readBlock(); 57450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 57550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber if (err != OK) { 57650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 57750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 57850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return err; 57950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 58050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 58150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 58250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer *frame = *mPendingFrames.begin(); 58350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.erase(mPendingFrames.begin()); 58450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 58550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber if (mType != AVC) { 5865ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (targetSampleTimeUs >= 0ll) { 5875ec58d925520e6913fba3fc54413881af751c610Andreas Huber frame->meta_data()->setInt64( 5885ec58d925520e6913fba3fc54413881af751c610Andreas Huber kKeyTargetTime, targetSampleTimeUs); 5895ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 5905ec58d925520e6913fba3fc54413881af751c610Andreas Huber 59150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = frame; 59250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 59350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return OK; 59450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 59550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 596792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // Each input frame contains one or more NAL fragments, each fragment 597792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // is prefixed by mNALSizeLen bytes giving the fragment length, 598792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // followed by a corresponding number of bytes containing the fragment. 599792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // We output all these fragments into a single large buffer separated 600792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // by startcodes (0x00 0x00 0x00 0x01). 601792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 602792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber const uint8_t *srcPtr = 603792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber (const uint8_t *)frame->data() + frame->range_offset(); 604792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 605792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t srcSize = frame->range_length(); 606792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 607792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t dstSize = 0; 608792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber MediaBuffer *buffer = NULL; 609792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber uint8_t *dstPtr = NULL; 610792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 611792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber for (int32_t pass = 0; pass < 2; ++pass) { 612792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t srcOffset = 0; 613792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t dstOffset = 0; 614792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber while (srcOffset + mNALSizeLen <= srcSize) { 615792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t NALsize; 616792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber switch (mNALSizeLen) { 617792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 1: NALsize = srcPtr[srcOffset]; break; 618792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 2: NALsize = U16_AT(srcPtr + srcOffset); break; 619792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 3: NALsize = U24_AT(srcPtr + srcOffset); break; 620792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 4: NALsize = U32_AT(srcPtr + srcOffset); break; 621792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber default: 622792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber TRESPASS(); 623792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 62450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 6252dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih if (srcOffset + mNALSizeLen + NALsize <= srcOffset + mNALSizeLen) { 6262dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih frame->release(); 6272dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih frame = NULL; 6282dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih 6292dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih return ERROR_MALFORMED; 6302dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih } else if (srcOffset + mNALSizeLen + NALsize > srcSize) { 631792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber break; 632792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 63350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 634792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (pass == 1) { 635792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4); 63650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 637ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen if (frame != buffer) { 638ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen memcpy(&dstPtr[dstOffset + 4], 639ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen &srcPtr[srcOffset + mNALSizeLen], 640ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen NALsize); 641ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen } 642792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 64350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 644792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstOffset += 4; // 0x00 00 00 01 645792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstOffset += NALsize; 64650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 647792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber srcOffset += mNALSizeLen + NALsize; 648792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 64950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 650792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (srcOffset < srcSize) { 651792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // There were trailing bytes or not enough data to complete 652792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // a fragment. 65350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 654792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame->release(); 655792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame = NULL; 65650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 657792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber return ERROR_MALFORMED; 658792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 65950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 660792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (pass == 0) { 661792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstSize = dstOffset; 66250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 663ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen if (dstSize == srcSize && mNALSizeLen == 4) { 664ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen // In this special case we can re-use the input buffer by substituting 665ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen // each 4-byte nal size with a 4-byte start code 666ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen buffer = frame; 667ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen } else { 668ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen buffer = new MediaBuffer(dstSize); 669ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen } 67050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 671792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber int64_t timeUs; 672792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs)); 673792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber int32_t isSync; 674792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)); 67550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 676792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 677792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync); 67850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 679792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstPtr = (uint8_t *)buffer->data(); 680792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 68150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 68250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 683ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen if (frame != buffer) { 684ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen frame->release(); 685ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen frame = NULL; 686ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen } 68750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 6885ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (targetSampleTimeUs >= 0ll) { 6895ec58d925520e6913fba3fc54413881af751c610Andreas Huber buffer->meta_data()->setInt64( 6905ec58d925520e6913fba3fc54413881af751c610Andreas Huber kKeyTargetTime, targetSampleTimeUs); 6915ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 6925ec58d925520e6913fba3fc54413881af751c610Andreas Huber 69350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = buffer; 694093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 695093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 696093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 697093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 698093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber//////////////////////////////////////////////////////////////////////////////// 699093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 700093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source) 701093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mDataSource(source), 702093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mReader(new DataSourceReader(mDataSource)), 7035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mSegment(NULL), 7048c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mExtractedThumbnails(false), 705bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mIsWebm(false), 706bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSeekPreRollNs(0) { 707d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber off64_t size; 708d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mIsLiveStreaming = 709d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber (mDataSource->flags() 710d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber & (DataSource::kWantsPrefetching 711d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber | DataSource::kIsCachingDataSource)) 712d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && mDataSource->getSize(&size) != OK; 713d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 714093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::EBMLHeader ebmlHeader; 715093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long pos; 716093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ebmlHeader.Parse(mReader, pos) < 0) { 717093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 718093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 719093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 7208c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) { 7218c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mIsWebm = true; 7228c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber } 7238c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber 724093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long ret = 725093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::Segment::CreateInstance(mReader, pos, mSegment); 726093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 727093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ret) { 728093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(mSegment == NULL); 729093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 730093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 731093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 732c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar // from mkvparser::Segment::Load(), but stop at first cluster 73310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ret = mSegment->ParseHeaders(); 734c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar if (ret == 0) { 735c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar long len; 736c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ret = mSegment->LoadCluster(pos, len); 737c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar if (ret >= 1) { 738c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar // no more clusters 739c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ret = 0; 740c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar } 741c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar } else if (ret > 0) { 742c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ret = mkvparser::E_BUFFER_NOT_FULL; 743c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar } 744093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 745093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ret < 0) { 746c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ALOGW("Corrupt %s source: %s", mIsWebm ? "webm" : "matroska", 747c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar uriDebugString(mDataSource->getUri()).c_str()); 748093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mSegment; 749093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mSegment = NULL; 750093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 751093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 752093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 75374a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber#if 0 75474a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber const mkvparser::SegmentInfo *info = mSegment->GetInfo(); 755df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("muxing app: %s, writing app: %s", 75674a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber info->GetMuxingAppAsUTF8(), 75774a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber info->GetWritingAppAsUTF8()); 75874a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber#endif 75974a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 760093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber addTracks(); 761093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 762093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 763093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::~MatroskaExtractor() { 764093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mSegment; 765093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mSegment = NULL; 766093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 767093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mReader; 768093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mReader = NULL; 769093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 770093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 771093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersize_t MatroskaExtractor::countTracks() { 772093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mTracks.size(); 773093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 774093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 775093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MediaSource> MatroskaExtractor::getTrack(size_t index) { 776093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (index >= mTracks.size()) { 777093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return NULL; 778093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 779093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 780093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return new MatroskaSource(this, index); 781093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 782093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 783093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaExtractor::getTrackMetaData( 784093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t index, uint32_t flags) { 785093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (index >= mTracks.size()) { 786093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return NULL; 787093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 788093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 789d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails 790d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && !isLiveStreaming()) { 7915279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber findThumbnails(); 7925279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mExtractedThumbnails = true; 7935279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 7945279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 795093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mTracks.itemAt(index).mMeta; 796093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 797093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 798d42573cace9db2b5948e540c32beaef80f04153cAndreas Huberbool MatroskaExtractor::isLiveStreaming() const { 799d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return mIsLiveStreaming; 800d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 801d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 802403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissenstatic int bytesForSize(size_t size) { 803403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen // use at most 28 bits (4 times 7) 804403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen CHECK(size <= 0xfffffff); 805403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 806403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen if (size > 0x1fffff) { 807403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 4; 808403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } else if (size > 0x3fff) { 809403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 3; 810403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } else if (size > 0x7f) { 811403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 2; 812403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } 813403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 1; 814403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen} 815403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 816403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissenstatic void storeSize(uint8_t *data, size_t &idx, size_t size) { 817403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int numBytes = bytesForSize(size); 818403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen idx += numBytes; 819403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 820403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen data += idx; 821403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size_t next = 0; 822403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen while (numBytes--) { 823403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen *--data = (size & 0x7f) | next; 824403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size >>= 7; 825403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen next = 0x80; 826403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } 827403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen} 828403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 829132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kangstatic void addESDSFromCodecPrivate( 830132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang const sp<MetaData> &meta, 831132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang bool isAudio, const void *priv, size_t privSize) { 832093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 833403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int privSizeBytesRequired = bytesForSize(privSize); 834403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize2 = 14 + privSizeBytesRequired + privSize; 835403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize2BytesRequired = bytesForSize(esdsSize2); 836403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2; 837403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize1BytesRequired = bytesForSize(esdsSize1); 838403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1; 839093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber uint8_t *esds = new uint8_t[esdsSize]; 840403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 841403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size_t idx = 0; 842403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x03; 843403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen storeSize(esds, idx, esdsSize1); 844403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; // ES_ID 845403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; // ES_ID 846403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag 847403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x04; 848403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen storeSize(esds, idx, esdsSize2); 849403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = isAudio ? 0x40 // Audio ISO/IEC 14496-3 850403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen : 0x20; // Visual ISO/IEC 14496-2 851403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen for (int i = 0; i < 12; i++) { 852403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; 853403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } 854403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x05; 855403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen storeSize(esds, idx, privSize); 856403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen memcpy(esds + idx, priv, privSize); 85782ac8bf2da940c4439786c346f739f4a496864adAndreas Huber 858093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData(kKeyESDS, 0, esds, esdsSize); 859093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 860093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete[] esds; 861093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber esds = NULL; 862093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 863093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8645ce181568da90c78ba7fad3e084c8479041545dfAndreas Huberstatus_t addVorbisCodecInfo( 865093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MetaData> &meta, 866093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const void *_codecPrivate, size_t codecPrivateSize) { 867093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber // hexdump(_codecPrivate, codecPrivateSize); 868093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8695ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivateSize < 1) { 8705ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 8715ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 872093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 873093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate; 874093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8755ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[0] != 0x02) { 8765ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 8775ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 878093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8795ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber // codecInfo starts with two lengths, len1 and len2, that are 8805ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber // "Xiph-style-lacing encoded"... 881093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8825ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t offset = 1; 8835ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t len1 = 0; 8845ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 8857d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len1 > (SIZE_MAX - 0xff)) { 8867d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen return ERROR_MALFORMED; // would overflow 8877d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen } 8885ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len1 += 0xff; 8895ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ++offset; 8905ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 8915ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (offset >= codecPrivateSize) { 8925ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 8935ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 8947d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len1 > (SIZE_MAX - codecPrivate[offset])) { 8957d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen return ERROR_MALFORMED; // would overflow 8967d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen } 8975ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len1 += codecPrivate[offset++]; 898093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8995ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t len2 = 0; 9005ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 9017d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len2 > (SIZE_MAX - 0xff)) { 9027d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen return ERROR_MALFORMED; // would overflow 9037d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen } 9045ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len2 += 0xff; 9055ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ++offset; 9065ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 9075ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (offset >= codecPrivateSize) { 9085ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 9095ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 9107d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len2 > (SIZE_MAX - codecPrivate[offset])) { 9117d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen return ERROR_MALFORMED; // would overflow 9127d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen } 9135ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len2 += codecPrivate[offset++]; 9145ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 9157d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len1 > SIZE_MAX - len2 || offset > SIZE_MAX - (len1 + len2) || 9167d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen codecPrivateSize < offset + len1 + len2) { 9175ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 9185ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 9195ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 9205ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x01) { 9215ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 9225ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 9235ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1); 9245ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 9255ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber offset += len1; 9265ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x03) { 9275ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 9285ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 9295ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 9305ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber offset += len2; 9315ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x05) { 9325ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 9335ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 934093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 935093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData( 9365ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber kKeyVorbisBooks, 0, &codecPrivate[offset], 9375ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber codecPrivateSize - offset); 9385ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 9395ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return OK; 940093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 941093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 942093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubervoid MatroskaExtractor::addTracks() { 943093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::Tracks *tracks = mSegment->GetTracks(); 944093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 945093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber for (size_t index = 0; index < tracks->GetTracksCount(); ++index) { 946093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::Track *track = tracks->GetTrackByIndex(index); 947093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 94830ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber if (track == NULL) { 94930ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber // Apparently this is currently valid (if unexpected) behaviour 95030ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber // of the mkv parser lib. 95130ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber continue; 95230ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber } 95330ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber 954093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *const codecID = track->GetCodecId(); 9553856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("codec id = %s", codecID); 9563856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("codec name = %s", track->GetCodecNameAsUTF8()); 957093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9581e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih if (codecID == NULL) { 9591e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih ALOGW("unknown codecID is not supported."); 9601e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih continue; 9611e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih } 9621e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih 963093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t codecPrivateSize; 964093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const unsigned char *codecPrivate = 965ff1df9951d09f1a1a8ae2dbc42b82b0f9c164e5eAndreas Huber track->GetCodecPrivate(codecPrivateSize); 966093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 967093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 }; 968093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 969093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MetaData> meta = new MetaData; 970093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9715ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber status_t err = OK; 9725ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 973093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber switch (track->GetType()) { 974093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber case VIDEO_TRACK: 975093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber { 976093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::VideoTrack *vtrack = 977093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber static_cast<const mkvparser::VideoTrack *>(track); 978093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9791e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { 980093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 981093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); 982132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) { 983132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang if (codecPrivateSize > 0) { 984132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta->setCString( 985132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 986132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang addESDSFromCodecPrivate( 987132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta, false, codecPrivate, codecPrivateSize); 988132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else { 989132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is detected, but does not have configuration.", 990132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang codecID); 991132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang continue; 992132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } 993093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcmp("V_VP8", codecID)) { 99494705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8); 99594705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang } else if (!strcmp("V_VP9", codecID)) { 99694705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9); 997093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else { 998132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is not supported.", codecID); 999093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 1000093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1001093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1002093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyWidth, vtrack->GetWidth()); 1003093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyHeight, vtrack->GetHeight()); 1004093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber break; 1005093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1006093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1007093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber case AUDIO_TRACK: 1008093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber { 1009093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::AudioTrack *atrack = 1010093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber static_cast<const mkvparser::AudioTrack *>(track); 1011093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1012093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcmp("A_AAC", codecID)) { 1013093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); 1014093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(codecPrivateSize >= 2); 1015093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1016132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang addESDSFromCodecPrivate( 1017132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta, true, codecPrivate, codecPrivateSize); 1018093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcmp("A_VORBIS", codecID)) { 1019093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 1020093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 10215ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber err = addVorbisCodecInfo( 10225ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber meta, codecPrivate, codecPrivateSize); 1023bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } else if (!strcmp("A_OPUS", codecID)) { 1024bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS); 1025bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize); 1026bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay()); 1027bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll()); 1028bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSeekPreRollNs = track->GetSeekPreRoll(); 1029132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else if (!strcmp("A_MPEG/L3", codecID)) { 1030132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 1031093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else { 1032132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is not supported.", codecID); 1033093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 1034093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1035093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1036093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeySampleRate, atrack->GetSamplingRate()); 1037093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyChannelCount, atrack->GetChannels()); 1038093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber break; 1039093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1040093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1041093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber default: 1042093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 1043093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1044093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 10455ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (err != OK) { 10465ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ALOGE("skipping track, codec specific data was malformed."); 10475ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber continue; 10485ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 10495ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 1050093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long durationNs = mSegment->GetDuration(); 1051093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt64(kKeyDuration, (durationNs + 500) / 1000); 1052093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1053093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mTracks.push(); 1054093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1); 1055093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber trackInfo->mTrackNum = track->GetNumber(); 1056093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber trackInfo->mMeta = meta; 10572f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih trackInfo->mExtractor = this; 1058093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1059093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 1060093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 10615279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid MatroskaExtractor::findThumbnails() { 10625279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 10635279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber TrackInfo *info = &mTracks.editItemAt(i); 10645279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 10655279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const char *mime; 10665279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber CHECK(info->mMeta->findCString(kKeyMIMEType, &mime)); 10675279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 10685279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (strncasecmp(mime, "video/", 6)) { 10695279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber continue; 10705279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 10715279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 10722f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih BlockIterator iter(this, info->mTrackNum, i); 10734719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer int32_t j = 0; 10745279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t thumbnailTimeUs = 0; 10755279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber size_t maxBlockSize = 0; 10764719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer while (!iter.eos() && j < 20) { 10775279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (iter.block()->IsKey()) { 10784719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer ++j; 10795279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1080d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber size_t blockSize = 0; 1081cba4ed0039c8b8fac01b3193d19fc2364f934506Tareq A. Siraj for (int k = 0; k < iter.block()->GetFrameCount(); ++k) { 1082cba4ed0039c8b8fac01b3193d19fc2364f934506Tareq A. Siraj blockSize += iter.block()->GetFrame(k).len; 1083d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 1084d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 10855279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (blockSize > maxBlockSize) { 10865279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber maxBlockSize = blockSize; 10875279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber thumbnailTimeUs = iter.blockTimeUs(); 10885279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 10895279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 10905279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber iter.advance(); 10915279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 10925279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 10935279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 10945279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 10955279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1096093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaExtractor::getMetaData() { 1097093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MetaData> meta = new MetaData; 10988c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber 10998c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber meta->setCString( 11008c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber kKeyMIMEType, 11018c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA); 1102093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1103093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return meta; 1104093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 1105093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1106d42573cace9db2b5948e540c32beaef80f04153cAndreas Huberuint32_t MatroskaExtractor::flags() const { 1107d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber uint32_t x = CAN_PAUSE; 1108d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (!isLiveStreaming()) { 1109d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK; 1110d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 1111d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 1112d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return x; 1113d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 1114d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 1115093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberbool SniffMatroska( 11165a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 11175a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 1118093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader reader(source); 1119093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::EBMLHeader ebmlHeader; 1120093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long pos; 1121093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ebmlHeader.Parse(&reader, pos) < 0) { 1122093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return false; 1123093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1124093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1125093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA); 1126093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *confidence = 0.6; 1127093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1128093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return true; 1129093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 1130093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1131093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} // namespace android 1132