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" 224f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih#include "avc_utils.h" 23093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 24b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber#include <media/stagefright/foundation/ADebug.h> 252dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih#include <media/stagefright/foundation/AUtils.h> 264f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih#include <media/stagefright/foundation/ABuffer.h> 27d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar#include <media/stagefright/foundation/ColorUtils.h> 28b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber#include <media/stagefright/foundation/hexdump.h> 29093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/DataSource.h> 30093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaBuffer.h> 31093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaDefs.h> 32093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaErrors.h> 33093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaSource.h> 34093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MetaData.h> 35b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber#include <media/stagefright/Utils.h> 36093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <utils/String8.h> 37093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 38b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross#include <inttypes.h> 39b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross 40093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubernamespace android { 41093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 42093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstruct DataSourceReader : public mkvparser::IMkvReader { 43093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader(const sp<DataSource> &source) 44093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mSource(source) { 45093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 46093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 47093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual int Read(long long position, long length, unsigned char* buffer) { 48093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(position >= 0); 49093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(length >= 0); 50093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 51093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (length == 0) { 52093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 53093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 54093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 55093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber ssize_t n = mSource->readAt(position, buffer, length); 56093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 57093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (n <= 0) { 58093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return -1; 59093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 60093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 61093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 62093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 63093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 64093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual int Length(long long* total, long long* available) { 65c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t size; 66093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (mSource->getSize(&size) != OK) { 67d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber *total = -1; 68d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber *available = (long long)((1ull << 63) - 1); 69d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 70d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return 0; 71093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 72093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 73093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (total) { 74093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *total = size; 75093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 76093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 77093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (available) { 78093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *available = size; 79093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 80093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 81093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 82093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 83093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 84093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberprivate: 85093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<DataSource> mSource; 86093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 87093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader(const DataSourceReader &); 88093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader &operator=(const DataSourceReader &); 89093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}; 90093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 91093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber//////////////////////////////////////////////////////////////////////////////// 92093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 935279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberstruct BlockIterator { 942f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index); 955279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 965279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber bool eos() const; 975279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 985279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber void advance(); 995279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber void reset(); 1005ec58d925520e6913fba3fc54413881af751c610Andreas Huber 1015ec58d925520e6913fba3fc54413881af751c610Andreas Huber void seek( 102f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann int64_t seekTimeUs, bool isAudio, 1035ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t *actualFrameTimeUs); 1045279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1055279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::Block *block() const; 1065279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t blockTimeUs() const; 1075279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1085279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberprivate: 109d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber MatroskaExtractor *mExtractor; 110b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross long long mTrackNum; 1112f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih unsigned long mIndex; 1125279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 113d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Cluster *mCluster; 1145279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::BlockEntry *mBlockEntry; 115d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long mBlockEntryIndex; 116d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 117d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber void advance_l(); 1185279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1195279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator(const BlockIterator &); 1205279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator &operator=(const BlockIterator &); 1215279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}; 1225279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 123093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstruct MatroskaSource : public MediaSource { 124093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource( 125093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MatroskaExtractor> &extractor, size_t index); 126093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 127093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t start(MetaData *params); 128093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t stop(); 129093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 130093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual sp<MetaData> getFormat(); 131093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 132093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t read( 133093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MediaBuffer **buffer, const ReadOptions *options); 134093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 13550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberprotected: 13650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber virtual ~MatroskaSource(); 13750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 138093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberprivate: 139093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber enum Type { 140093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber AVC, 141093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber AAC, 142093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber OTHER 143093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber }; 144093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 145093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MatroskaExtractor> mExtractor; 146093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t mTrackIndex; 147093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber Type mType; 14874a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber bool mIsAudio; 1495279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator mBlockIter; 1504f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih ssize_t mNALSizeLen; // for type AVC 151093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 15250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber List<MediaBuffer *> mPendingFrames; 15350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 154093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber status_t advance(); 155093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 156793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih status_t setWebmBlockCryptoInfo(MediaBuffer *mbuf); 15750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber status_t readBlock(); 15850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber void clearPendingFrames(); 15950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 160093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource(const MatroskaSource &); 161093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource &operator=(const MatroskaSource &); 162093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}; 163093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1642f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shihconst mkvparser::Track* MatroskaExtractor::TrackInfo::getTrack() const { 1652f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return mExtractor->mSegment->GetTracks()->GetTrackByNumber(mTrackNum); 1662f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih} 1672f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 1682f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih// This function does exactly the same as mkvparser::Cues::Find, except that it 1692f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih// searches in our own track based vectors. We should not need this once mkvparser 1702f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih// adds the same functionality. 1712f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shihconst mkvparser::CuePoint::TrackPosition *MatroskaExtractor::TrackInfo::find( 1722f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih long long timeNs) const { 1732f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih ALOGV("mCuePoints.size %zu", mCuePoints.size()); 1742f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (mCuePoints.empty()) { 1752f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return NULL; 1762f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 1772f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 1782f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::CuePoint* cp = mCuePoints.itemAt(0); 1792f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::Track* track = getTrack(); 1802f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (timeNs <= cp->GetTime(mExtractor->mSegment)) { 1812f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return cp->Find(track); 1822f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 1832f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 1842f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih // Binary searches through relevant cues; assumes cues are ordered by timecode. 1852f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih // If we do detect out-of-order cues, return NULL. 1862f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih size_t lo = 0; 1872f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih size_t hi = mCuePoints.size(); 1882f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih while (lo < hi) { 1892f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const size_t mid = lo + (hi - lo) / 2; 1902f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::CuePoint* const midCp = mCuePoints.itemAt(mid); 1912f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const long long cueTimeNs = midCp->GetTime(mExtractor->mSegment); 1922f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (cueTimeNs <= timeNs) { 1932f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih lo = mid + 1; 1942f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } else { 1952f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih hi = mid; 1962f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 1972f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 1982f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 1992f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (lo == 0) { 2002f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return NULL; 2012f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 2022f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 2032f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih cp = mCuePoints.itemAt(lo - 1); 2042f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (cp->GetTime(mExtractor->mSegment) > timeNs) { 2052f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return NULL; 2062f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 2072f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 2082f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return cp->Find(track); 2092f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih} 2102f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 211093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaSource::MatroskaSource( 212093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MatroskaExtractor> &extractor, size_t index) 213093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mExtractor(extractor), 214093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mTrackIndex(index), 215093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType(OTHER), 21674a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber mIsAudio(false), 217d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter(mExtractor.get(), 2182f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih mExtractor->mTracks.itemAt(index).mTrackNum, 2192f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih index), 2204f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih mNALSizeLen(-1) { 221b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta; 222b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 223093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *mime; 224b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber CHECK(meta->findCString(kKeyMIMEType, &mime)); 225093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 22674a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber mIsAudio = !strncasecmp("audio/", mime, 6); 22774a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 228093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 229093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType = AVC; 230b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 231b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber uint32_t dummy; 232b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber const uint8_t *avcc; 233b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber size_t avccSize; 2344f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih int32_t nalSizeLen = 0; 2354f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (meta->findInt32(kKeyNalLengthSize, &nalSizeLen)) { 2364f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (nalSizeLen >= 0 && nalSizeLen <= 4) { 2374f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih mNALSizeLen = nalSizeLen; 2384f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 2394f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } else if (meta->findData(kKeyAVCC, &dummy, (const void **)&avcc, &avccSize) 2404f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih && avccSize >= 5u) { 2414f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih mNALSizeLen = 1 + (avcc[4] & 3); 2424f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih ALOGV("mNALSizeLen = %zd", mNALSizeLen); 2434f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } else { 2444f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih ALOGE("No mNALSizeLen"); 2454f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 246093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 247093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType = AAC; 248093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 249093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 250093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 25150c8bea8fba2fcafb14696399028bdbc094dc995Andreas HuberMatroskaSource::~MatroskaSource() { 25250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 25350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 25450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 25584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MatroskaSource::start(MetaData * /* params */) { 2564f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (mType == AVC && mNALSizeLen < 0) { 2574f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih return ERROR_MALFORMED; 2584f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 2594f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih 2605279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mBlockIter.reset(); 261093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 262093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 263093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 264093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 265093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstatus_t MatroskaSource::stop() { 26650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 26750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 268093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 269093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 270093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 271093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaSource::getFormat() { 272093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mExtractor->mTracks.itemAt(mTrackIndex).mMeta; 273093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 274093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 2755279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber//////////////////////////////////////////////////////////////////////////////// 2765279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2775279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas HuberBlockIterator::BlockIterator( 2782f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index) 279d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber : mExtractor(extractor), 2805279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mTrackNum(trackNum), 2812f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih mIndex(index), 2825279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mCluster(NULL), 283d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntry(NULL), 284d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex(0) { 2855279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber reset(); 2865279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 2875279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2885279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberbool BlockIterator::eos() const { 2895279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return mCluster == NULL || mCluster->EOS(); 2905279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 2915279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2925279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::advance() { 293d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 294d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 295d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 296d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 297d42573cace9db2b5948e540c32beaef80f04153cAndreas Hubervoid BlockIterator::advance_l() { 298d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber for (;;) { 299d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry); 3003856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetEntry returned %ld", res); 301d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 302d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long long pos; 303d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long len; 304d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (res < 0) { 305d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // Need to parse this cluster some more 306d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 307d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL); 308d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 309d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mCluster->Parse(pos, len); 3103856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Parse returned %ld", res); 311d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 312d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (res < 0) { 313d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // I/O error 314d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 31529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cluster::Parse returned result %ld", res); 3165279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 317d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = NULL; 3185279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber break; 319093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 3205279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 321d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber continue; 322d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } else if (res == 0) { 323d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // We're done with this cluster 324d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 325d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Cluster *nextCluster; 326d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mExtractor->mSegment->ParseNext( 327d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster, nextCluster, pos, len); 3283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ParseNext returned %ld", res); 329d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 330e467ef084b75b074d0081616080b54212a7024c8Lajos Molnar if (res != 0) { 331e467ef084b75b074d0081616080b54212a7024c8Lajos Molnar // EOF or error 332d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 333d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = NULL; 334d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber break; 335d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 336d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 337d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_EQ(res, 0); 338d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(nextCluster != NULL); 339d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(!nextCluster->EOS()); 340d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 341d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = nextCluster; 342d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 343d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mCluster->Parse(pos, len); 3443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Parse (2) returned %ld", res); 345d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_GE(res, 0); 346d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 347d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex = 0; 348d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber continue; 349093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 350093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 351d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(mBlockEntry != NULL); 352d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(mBlockEntry->GetBlock() != NULL); 353d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber ++mBlockEntryIndex; 354d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 355d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) { 3565279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber break; 357093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 3585279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 3595279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 3605279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 3615279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::reset() { 362d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 363093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 364d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = mExtractor->mSegment->GetFirst(); 3652ba7ce928b0fa8917ee202836b0963ca58613453Andreas Huber mBlockEntry = NULL; 366d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex = 0; 367d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 368d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber do { 369d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 370d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } while (!eos() && block()->GetTrackNumber() != mTrackNum); 3715279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 372093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 3735ec58d925520e6913fba3fc54413881af751c610Andreas Hubervoid BlockIterator::seek( 374f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann int64_t seekTimeUs, bool isAudio, 3755ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t *actualFrameTimeUs) { 376d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 377d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 3785ec58d925520e6913fba3fc54413881af751c610Andreas Huber *actualFrameTimeUs = -1ll; 3795ec58d925520e6913fba3fc54413881af751c610Andreas Huber 380bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const int64_t seekTimeNs = seekTimeUs * 1000ll - mExtractor->mSeekPreRollNs; 38110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 38210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mkvparser::Segment* const pSegment = mExtractor->mSegment; 38310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 38410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // Special case the 0 seek to avoid loading Cues when the application 38510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // extraneously seeks to 0 before playing. 38610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (seekTimeNs <= 0) { 387b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("Seek to beginning: %" PRId64, seekTimeUs); 38810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mCluster = pSegment->GetFirst(); 38910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mBlockEntryIndex = 0; 39010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann do { 39110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann advance_l(); 39210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } while (!eos() && block()->GetTrackNumber() != mTrackNum); 39310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 39410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 3955ec58d925520e6913fba3fc54413881af751c610Andreas Huber 396b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("Seeking to: %" PRId64, seekTimeUs); 39710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 39810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // If the Cues have not been located then find them. 39910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::Cues* pCues = pSegment->GetCues(); 40010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::SeekHead* pSH = pSegment->GetSeekHead(); 40110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (!pCues && pSH) { 40210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const size_t count = pSH->GetCount(); 40310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::SeekHead::Entry* pEntry; 40410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGV("No Cues yet"); 40510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 40610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann for (size_t index = 0; index < count; index++) { 40710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pEntry = pSH->GetEntry(index); 40810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 40910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (pEntry->id == 0x0C53BB6B) { // Cues ID 41010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann long len; long long pos; 41110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pSegment->ParseCues(pEntry->pos, pos, len); 41210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pCues = pSegment->GetCues(); 413be7ac3d682729048af27871311808a76c618abdbJohann ALOGV("Cues found"); 41410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann break; 41510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 41610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 41710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 41810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (!pCues) { 41910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGE("No Cues in file"); 42010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 42110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 42210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 42310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann else if (!pSH) { 42410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGE("No SeekHead"); 42510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 42610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 42710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 42810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::CuePoint* pCP; 4292f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih mkvparser::Tracks const *pTracks = pSegment->GetTracks(); 43010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann while (!pCues->DoneParsing()) { 431be7ac3d682729048af27871311808a76c618abdbJohann pCues->LoadCuePoint(); 43210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pCP = pCues->GetLast(); 4332f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih CHECK(pCP); 4342f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 4350644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih size_t trackCount = mExtractor->mTracks.size(); 4362f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih for (size_t index = 0; index < trackCount; ++index) { 4370644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(index); 4380644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih const mkvparser::Track *pTrack = pTracks->GetTrackByNumber(track.mTrackNum); 4392f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (pTrack && pTrack->GetType() == 1 && pCP->Find(pTrack)) { // VIDEO_TRACK 4402f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih track.mCuePoints.push_back(pCP); 4412f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 4422f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 443be7ac3d682729048af27871311808a76c618abdbJohann 44410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (pCP->GetTime(pSegment) >= seekTimeNs) { 445be7ac3d682729048af27871311808a76c618abdbJohann ALOGV("Parsed past relevant Cue"); 44610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann break; 44710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 44810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 44910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 4502f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::CuePoint::TrackPosition *pTP = NULL; 4510644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih const mkvparser::Track *thisTrack = pTracks->GetTrackByNumber(mTrackNum); 4522f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (thisTrack->GetType() == 1) { // video 4532f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(mIndex); 4542f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih pTP = track.find(seekTimeNs); 4552f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } else { 4562f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih // The Cue index is built around video keyframes 4570644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih unsigned long int trackCount = pTracks->GetTracksCount(); 4582f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih for (size_t index = 0; index < trackCount; ++index) { 4592f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::Track *pTrack = pTracks->GetTrackByIndex(index); 4602f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (pTrack && pTrack->GetType() == 1 && pCues->Find(seekTimeNs, pTrack, pCP, pTP)) { 4612f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih ALOGV("Video track located at %zu", index); 4622f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih break; 4632f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 46410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 46510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 46610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 4672f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 468f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // Always *search* based on the video track, but finalize based on mTrackNum 4692f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (!pTP) { 470f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann ALOGE("Did not locate the video track for seeking"); 47110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 47210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 47310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 47410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos); 4755279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 476f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK(mCluster); 477f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK(!mCluster->EOS()); 478f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann 479f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // mBlockEntryIndex starts at 0 but m_block starts at 1 480f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK_GT(pTP->m_block, 0); 481f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann mBlockEntryIndex = pTP->m_block - 1; 4825ec58d925520e6913fba3fc54413881af751c610Andreas Huber 4835ec58d925520e6913fba3fc54413881af751c610Andreas Huber for (;;) { 484d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 4855279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 486f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann if (eos()) break; 4875ec58d925520e6913fba3fc54413881af751c610Andreas Huber 488f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann if (isAudio || block()->IsKey()) { 489f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // Accept the first key frame 4902f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih int64_t frameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL; 4912f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (thisTrack->GetType() == 1 || frameTimeUs >= seekTimeUs) { 4922f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih *actualFrameTimeUs = frameTimeUs; 4932f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih ALOGV("Requested seek point: %" PRId64 " actual: %" PRId64, 4942f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih seekTimeUs, *actualFrameTimeUs); 4952f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih break; 4962f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 49774a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber } 4985279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 499093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 500093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 5015279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberconst mkvparser::Block *BlockIterator::block() const { 5025279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber CHECK(!eos()); 5035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 5045279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return mBlockEntry->GetBlock(); 5055279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 5065279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 5075279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberint64_t BlockIterator::blockTimeUs() const { 5084f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (mCluster == NULL || mBlockEntry == NULL) { 5094f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih return -1; 5104f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 5115279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll; 5125279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 5135279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 5145279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber//////////////////////////////////////////////////////////////////////////////// 5155279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 516b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huberstatic unsigned U24_AT(const uint8_t *ptr) { 517b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; 518b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber} 519b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 52050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Hubervoid MatroskaSource::clearPendingFrames() { 52150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (!mPendingFrames.empty()) { 52250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer *frame = *mPendingFrames.begin(); 52350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.erase(mPendingFrames.begin()); 52450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 52550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber frame->release(); 52650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber frame = NULL; 52750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 52850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 52950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 530793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shihstatus_t MatroskaSource::setWebmBlockCryptoInfo(MediaBuffer *mbuf) { 531793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih if (mbuf->range_length() < 1 || mbuf->range_length() - 1 > INT32_MAX) { 532793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih // 1-byte signal 533793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih return ERROR_MALFORMED; 534793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih } 535793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih 536793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih const uint8_t *data = (const uint8_t *)mbuf->data() + mbuf->range_offset(); 537793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih bool blockEncrypted = data[0] & 0x1; 538793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih if (blockEncrypted && mbuf->range_length() < 9) { 539793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih // 1-byte signal + 8-byte IV 540793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih return ERROR_MALFORMED; 541793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih } 542793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih 543793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih sp<MetaData> meta = mbuf->meta_data(); 544793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih if (blockEncrypted) { 545793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih /* 546793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * 0 1 2 3 547793c9fb11114c7be4636b8cae5477995aadeb71dRobert 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 548793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 549793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | Signal Byte | | 550793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * +-+-+-+-+-+-+-+-+ IV | 551793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | | 552793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 553793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | | | 554793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * |-+-+-+-+-+-+-+-+ | 555793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * : Bytes 1..N of encrypted frame : 556793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | | 557793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | | 558793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 559793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih */ 560793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih int32_t plainSizes[] = { 0 }; 561793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih int32_t encryptedSizes[] = { static_cast<int32_t>(mbuf->range_length() - 9) }; 562793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih uint8_t ctrCounter[16] = { 0 }; 563793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih uint32_t type; 564793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih const uint8_t *keyId; 565793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih size_t keyIdSize; 566793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih sp<MetaData> trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta; 567793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih CHECK(trackMeta->findData(kKeyCryptoKey, &type, (const void **)&keyId, &keyIdSize)); 568793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih meta->setData(kKeyCryptoKey, 0, keyId, keyIdSize); 569793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih memcpy(ctrCounter, data + 1, 8); 570793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih meta->setData(kKeyCryptoIV, 0, ctrCounter, 16); 571793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes)); 572793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes)); 573793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih mbuf->set_range(9, mbuf->range_length() - 9); 574793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih } else { 575793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih /* 576793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * 0 1 2 3 577793c9fb11114c7be4636b8cae5477995aadeb71dRobert 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 578793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 579793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | Signal Byte | | 580793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * +-+-+-+-+-+-+-+-+ | 581793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * : Bytes 1..N of unencrypted frame : 582793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | | 583793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | | 584793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 585793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih */ 586793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih int32_t plainSizes[] = { static_cast<int32_t>(mbuf->range_length() - 1) }; 587793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih int32_t encryptedSizes[] = { 0 }; 588793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes)); 589793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes)); 590793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih mbuf->set_range(1, mbuf->range_length() - 1); 591793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih } 592793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih 593793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih return OK; 594793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih} 595793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih 59650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatus_t MatroskaSource::readBlock() { 59750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber CHECK(mPendingFrames.empty()); 59850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 5995279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (mBlockIter.eos()) { 600093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return ERROR_END_OF_STREAM; 601093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 602093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 6035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::Block *block = mBlockIter.block(); 60450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 6055279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t timeUs = mBlockIter.blockTimeUs(); 606093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 607d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber for (int i = 0; i < block->GetFrameCount(); ++i) { 608d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Block::Frame &frame = block->GetFrame(i); 609b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 610d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber MediaBuffer *mbuf = new MediaBuffer(frame.len); 611d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mbuf->meta_data()->setInt64(kKeyTime, timeUs); 612d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey()); 613093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 614793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih status_t err = frame.Read(mExtractor->mReader, static_cast<uint8_t *>(mbuf->data())); 615793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih if (err == OK 616793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih && mExtractor->mIsWebm 617793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih && mExtractor->mTracks.itemAt(mTrackIndex).mEncrypted) { 618793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih err = setWebmBlockCryptoInfo(mbuf); 619793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih } 620793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih 621793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih if (err != OK) { 622d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mPendingFrames.clear(); 62350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 624d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter.advance(); 625ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen mbuf->release(); 626793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih return err; 62750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 62850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 62950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.push_back(mbuf); 63050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 63150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 632d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter.advance(); 63350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 63450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return OK; 63550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 63650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 63750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatus_t MatroskaSource::read( 63850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer **out, const ReadOptions *options) { 63950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = NULL; 64050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 6415ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t targetSampleTimeUs = -1ll; 6425ec58d925520e6913fba3fc54413881af751c610Andreas Huber 64350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber int64_t seekTimeUs; 64450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber ReadOptions::SeekMode mode; 645d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode) 646d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && !mExtractor->isLiveStreaming()) { 64750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 64874a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 649f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // The audio we want is located by using the Cues to seek the video 650f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // stream to find the target Cluster then iterating to finalize for 651f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // audio. 6525ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t actualFrameTimeUs; 653f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs); 6545ec58d925520e6913fba3fc54413881af751c610Andreas Huber 6555ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 6565ec58d925520e6913fba3fc54413881af751c610Andreas Huber targetSampleTimeUs = actualFrameTimeUs; 6575ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 65850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 65950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 66050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (mPendingFrames.empty()) { 66150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber status_t err = readBlock(); 66250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 66350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber if (err != OK) { 66450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 66550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 66650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return err; 66750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 66850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 66950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 67050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer *frame = *mPendingFrames.begin(); 67150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.erase(mPendingFrames.begin()); 67250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 6734f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (mType != AVC || mNALSizeLen == 0) { 6745ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (targetSampleTimeUs >= 0ll) { 6755ec58d925520e6913fba3fc54413881af751c610Andreas Huber frame->meta_data()->setInt64( 6765ec58d925520e6913fba3fc54413881af751c610Andreas Huber kKeyTargetTime, targetSampleTimeUs); 6775ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 6785ec58d925520e6913fba3fc54413881af751c610Andreas Huber 67950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = frame; 68050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 68150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return OK; 68250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 68350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 684792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // Each input frame contains one or more NAL fragments, each fragment 685792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // is prefixed by mNALSizeLen bytes giving the fragment length, 686792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // followed by a corresponding number of bytes containing the fragment. 687792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // We output all these fragments into a single large buffer separated 688792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // by startcodes (0x00 0x00 0x00 0x01). 6894f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih // 6904f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih // When mNALSizeLen is 0, we assume the data is already in the format 6914f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih // desired. 692792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 693792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber const uint8_t *srcPtr = 694792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber (const uint8_t *)frame->data() + frame->range_offset(); 695792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 696792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t srcSize = frame->range_length(); 697792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 698792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t dstSize = 0; 699792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber MediaBuffer *buffer = NULL; 700792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber uint8_t *dstPtr = NULL; 701792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 702792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber for (int32_t pass = 0; pass < 2; ++pass) { 703792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t srcOffset = 0; 704792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t dstOffset = 0; 705792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber while (srcOffset + mNALSizeLen <= srcSize) { 706792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t NALsize; 707792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber switch (mNALSizeLen) { 708792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 1: NALsize = srcPtr[srcOffset]; break; 709792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 2: NALsize = U16_AT(srcPtr + srcOffset); break; 710792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 3: NALsize = U24_AT(srcPtr + srcOffset); break; 711792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 4: NALsize = U32_AT(srcPtr + srcOffset); break; 712792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber default: 713792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber TRESPASS(); 714792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 71550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 7162dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih if (srcOffset + mNALSizeLen + NALsize <= srcOffset + mNALSizeLen) { 7172dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih frame->release(); 7182dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih frame = NULL; 7192dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih 7202dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih return ERROR_MALFORMED; 7212dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih } else if (srcOffset + mNALSizeLen + NALsize > srcSize) { 722792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber break; 723792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 72450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 725792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (pass == 1) { 726792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4); 72750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 728ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen if (frame != buffer) { 729ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen memcpy(&dstPtr[dstOffset + 4], 730ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen &srcPtr[srcOffset + mNALSizeLen], 731ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen NALsize); 732ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen } 733792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 73450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 735792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstOffset += 4; // 0x00 00 00 01 736792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstOffset += NALsize; 73750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 738792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber srcOffset += mNALSizeLen + NALsize; 739792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 74050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 741792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (srcOffset < srcSize) { 742792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // There were trailing bytes or not enough data to complete 743792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // a fragment. 74450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 745792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame->release(); 746792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame = NULL; 74750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 748792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber return ERROR_MALFORMED; 749792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 75050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 751792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (pass == 0) { 752792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstSize = dstOffset; 75350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 754ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen if (dstSize == srcSize && mNALSizeLen == 4) { 755ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen // In this special case we can re-use the input buffer by substituting 756ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen // each 4-byte nal size with a 4-byte start code 757ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen buffer = frame; 758ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen } else { 759ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen buffer = new MediaBuffer(dstSize); 760ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen } 76150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 762792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber int64_t timeUs; 763792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs)); 764792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber int32_t isSync; 765792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)); 76650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 767792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 768792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync); 76950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 770792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstPtr = (uint8_t *)buffer->data(); 771792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 77250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 77350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 774ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen if (frame != buffer) { 775ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen frame->release(); 776ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen frame = NULL; 777ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen } 77850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 7795ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (targetSampleTimeUs >= 0ll) { 7805ec58d925520e6913fba3fc54413881af751c610Andreas Huber buffer->meta_data()->setInt64( 7815ec58d925520e6913fba3fc54413881af751c610Andreas Huber kKeyTargetTime, targetSampleTimeUs); 7825ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 7835ec58d925520e6913fba3fc54413881af751c610Andreas Huber 78450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = buffer; 785093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 786093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 787093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 788093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 789093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber//////////////////////////////////////////////////////////////////////////////// 790093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 791093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source) 792093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mDataSource(source), 793093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mReader(new DataSourceReader(mDataSource)), 7945279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mSegment(NULL), 7958c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mExtractedThumbnails(false), 796bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mIsWebm(false), 797bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSeekPreRollNs(0) { 798d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber off64_t size; 799d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mIsLiveStreaming = 800d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber (mDataSource->flags() 801d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber & (DataSource::kWantsPrefetching 802d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber | DataSource::kIsCachingDataSource)) 803d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && mDataSource->getSize(&size) != OK; 804d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 805093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::EBMLHeader ebmlHeader; 806093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long pos; 807093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ebmlHeader.Parse(mReader, pos) < 0) { 808093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 809093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 810093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8118c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) { 8128c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mIsWebm = true; 8138c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber } 8148c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber 815093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long ret = 816093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::Segment::CreateInstance(mReader, pos, mSegment); 817093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 818093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ret) { 819093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(mSegment == NULL); 820093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 821093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 822093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 823c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar // from mkvparser::Segment::Load(), but stop at first cluster 82410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ret = mSegment->ParseHeaders(); 825c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar if (ret == 0) { 826c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar long len; 827c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ret = mSegment->LoadCluster(pos, len); 828c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar if (ret >= 1) { 829c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar // no more clusters 830c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ret = 0; 831c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar } 832c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar } else if (ret > 0) { 833c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ret = mkvparser::E_BUFFER_NOT_FULL; 834c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar } 835093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 836093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ret < 0) { 837c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ALOGW("Corrupt %s source: %s", mIsWebm ? "webm" : "matroska", 838c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar uriDebugString(mDataSource->getUri()).c_str()); 839093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mSegment; 840093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mSegment = NULL; 841093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 842093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 843093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 84474a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber#if 0 84574a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber const mkvparser::SegmentInfo *info = mSegment->GetInfo(); 846df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("muxing app: %s, writing app: %s", 84774a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber info->GetMuxingAppAsUTF8(), 84874a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber info->GetWritingAppAsUTF8()); 84974a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber#endif 85074a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 851093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber addTracks(); 852093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 853093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 854093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::~MatroskaExtractor() { 855093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mSegment; 856093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mSegment = NULL; 857093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 858093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mReader; 859093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mReader = NULL; 860093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 861093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 862093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersize_t MatroskaExtractor::countTracks() { 863093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mTracks.size(); 864093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 865093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 866b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissensp<IMediaSource> MatroskaExtractor::getTrack(size_t index) { 867093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (index >= mTracks.size()) { 868093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return NULL; 869093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 870093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 871093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return new MatroskaSource(this, index); 872093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 873093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 874093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaExtractor::getTrackMetaData( 875093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t index, uint32_t flags) { 876093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (index >= mTracks.size()) { 877093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return NULL; 878093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 879093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 880d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails 881d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && !isLiveStreaming()) { 8825279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber findThumbnails(); 8835279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mExtractedThumbnails = true; 8845279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 8855279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 886093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mTracks.itemAt(index).mMeta; 887093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 888093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 889d42573cace9db2b5948e540c32beaef80f04153cAndreas Huberbool MatroskaExtractor::isLiveStreaming() const { 890d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return mIsLiveStreaming; 891d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 892d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 893403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissenstatic int bytesForSize(size_t size) { 894403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen // use at most 28 bits (4 times 7) 895403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen CHECK(size <= 0xfffffff); 896403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 897403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen if (size > 0x1fffff) { 898403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 4; 899403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } else if (size > 0x3fff) { 900403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 3; 901403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } else if (size > 0x7f) { 902403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 2; 903403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } 904403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 1; 905403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen} 906403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 907403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissenstatic void storeSize(uint8_t *data, size_t &idx, size_t size) { 908403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int numBytes = bytesForSize(size); 909403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen idx += numBytes; 910403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 911403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen data += idx; 912403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size_t next = 0; 913403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen while (numBytes--) { 914403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen *--data = (size & 0x7f) | next; 915403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size >>= 7; 916403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen next = 0x80; 917403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } 918403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen} 919403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 920132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kangstatic void addESDSFromCodecPrivate( 921132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang const sp<MetaData> &meta, 922132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang bool isAudio, const void *priv, size_t privSize) { 923093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 924403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int privSizeBytesRequired = bytesForSize(privSize); 925403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize2 = 14 + privSizeBytesRequired + privSize; 926403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize2BytesRequired = bytesForSize(esdsSize2); 927403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2; 928403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize1BytesRequired = bytesForSize(esdsSize1); 929403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1; 930093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber uint8_t *esds = new uint8_t[esdsSize]; 931403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 932403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size_t idx = 0; 933403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x03; 934403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen storeSize(esds, idx, esdsSize1); 935403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; // ES_ID 936403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; // ES_ID 937403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag 938403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x04; 939403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen storeSize(esds, idx, esdsSize2); 940403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = isAudio ? 0x40 // Audio ISO/IEC 14496-3 941403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen : 0x20; // Visual ISO/IEC 14496-2 942403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen for (int i = 0; i < 12; i++) { 943403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; 944403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } 945403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x05; 946403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen storeSize(esds, idx, privSize); 947403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen memcpy(esds + idx, priv, privSize); 94882ac8bf2da940c4439786c346f739f4a496864adAndreas Huber 949093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData(kKeyESDS, 0, esds, esdsSize); 950093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 951093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete[] esds; 952093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber esds = NULL; 953093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 954093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9555ce181568da90c78ba7fad3e084c8479041545dfAndreas Huberstatus_t addVorbisCodecInfo( 956093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MetaData> &meta, 957093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const void *_codecPrivate, size_t codecPrivateSize) { 958093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber // hexdump(_codecPrivate, codecPrivateSize); 959093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9605ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivateSize < 1) { 9615ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 9625ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 963093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 964093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate; 965093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9665ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[0] != 0x02) { 9675ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 9685ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 969093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9705ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber // codecInfo starts with two lengths, len1 and len2, that are 9715ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber // "Xiph-style-lacing encoded"... 972093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9735ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t offset = 1; 9745ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t len1 = 0; 9755ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 9767d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len1 > (SIZE_MAX - 0xff)) { 9777d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen return ERROR_MALFORMED; // would overflow 9787d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen } 9795ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len1 += 0xff; 9805ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ++offset; 9815ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 9825ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (offset >= codecPrivateSize) { 9835ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 9845ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 9857d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len1 > (SIZE_MAX - codecPrivate[offset])) { 9867d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen return ERROR_MALFORMED; // would overflow 9877d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen } 9885ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len1 += codecPrivate[offset++]; 989093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9905ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t len2 = 0; 9915ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 9927d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len2 > (SIZE_MAX - 0xff)) { 9937d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen return ERROR_MALFORMED; // would overflow 9947d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen } 9955ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len2 += 0xff; 9965ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ++offset; 9975ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 9985ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (offset >= codecPrivateSize) { 9995ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 10005ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 10017d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len2 > (SIZE_MAX - codecPrivate[offset])) { 10027d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen return ERROR_MALFORMED; // would overflow 10037d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen } 10045ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len2 += codecPrivate[offset++]; 10055ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 10067d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len1 > SIZE_MAX - len2 || offset > SIZE_MAX - (len1 + len2) || 10077d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen codecPrivateSize < offset + len1 + len2) { 10085ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 10095ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 10105ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 10115ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x01) { 10125ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 10135ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 10145ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1); 10155ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 10165ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber offset += len1; 10175ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x03) { 10185ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 10195ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 10205ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 10215ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber offset += len2; 10225ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x05) { 10235ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 10245ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 1025093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1026093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData( 10275ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber kKeyVorbisBooks, 0, &codecPrivate[offset], 10285ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber codecPrivateSize - offset); 10295ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 10305ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return OK; 1031093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 1032093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 10334f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shihstatus_t MatroskaExtractor::synthesizeAVCC(TrackInfo *trackInfo, size_t index) { 10344f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih BlockIterator iter(this, trackInfo->mTrackNum, index); 10354f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (iter.eos()) { 10364f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih return ERROR_MALFORMED; 10374f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 10384f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih 10394f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih const mkvparser::Block *block = iter.block(); 10404f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (block->GetFrameCount() <= 0) { 10414f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih return ERROR_MALFORMED; 10424f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 10434f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih 10444f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih const mkvparser::Block::Frame &frame = block->GetFrame(0); 10454f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih sp<ABuffer> abuf = new ABuffer(frame.len); 10464f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih long n = frame.Read(mReader, abuf->data()); 10474f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (n != 0) { 10484f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih return ERROR_MALFORMED; 10494f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 10504f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih 10514f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih sp<MetaData> avcMeta = MakeAVCCodecSpecificData(abuf); 10524f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (avcMeta == NULL) { 10534f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih return ERROR_MALFORMED; 10544f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 10554f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih 10564f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih // Override the synthesized nal length size, which is arbitrary 10574f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih avcMeta->setInt32(kKeyNalLengthSize, 0); 10584f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih trackInfo->mMeta = avcMeta; 10594f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih return OK; 10604f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih} 10614f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih 1062d637d296bb0954756d3d231633fad73fadd70316Lajos Molnarstatic inline bool isValidInt32ColourValue(long long value) { 1063d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar return value != mkvparser::Colour::kValueNotPresent 1064d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar && value >= INT32_MIN 1065d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar && value <= INT32_MAX; 1066d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar} 1067d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar 1068d637d296bb0954756d3d231633fad73fadd70316Lajos Molnarstatic inline bool isValidUint16ColourValue(long long value) { 1069d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar return value != mkvparser::Colour::kValueNotPresent 1070d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar && value >= 0 1071d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar && value <= UINT16_MAX; 1072d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar} 1073d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar 1074d637d296bb0954756d3d231633fad73fadd70316Lajos Molnarstatic inline bool isValidPrimary(const mkvparser::PrimaryChromaticity *primary) { 1075d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar return primary != NULL && primary->x >= 0 && primary->x <= 1 1076d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar && primary->y >= 0 && primary->y <= 1; 1077d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar} 1078d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar 1079d637d296bb0954756d3d231633fad73fadd70316Lajos Molnarvoid MatroskaExtractor::getColorInformation( 1080d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar const mkvparser::VideoTrack *vtrack, sp<MetaData> &meta) { 1081d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar const mkvparser::Colour *color = vtrack->GetColour(); 1082d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar if (color == NULL) { 1083d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar return; 1084d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 1085d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar 1086d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar // Color Aspects 1087d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar { 1088d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar int32_t primaries = 2; // ISO unspecified 1089d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar int32_t transfer = 2; // ISO unspecified 1090d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar int32_t coeffs = 2; // ISO unspecified 1091d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar bool fullRange = false; // default 1092d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar bool rangeSpecified = false; 1093d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar 1094d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar if (isValidInt32ColourValue(color->primaries)) { 1095d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar primaries = color->primaries; 1096d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 1097d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar if (isValidInt32ColourValue(color->transfer_characteristics)) { 1098d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar transfer = color->transfer_characteristics; 1099d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 1100d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar if (isValidInt32ColourValue(color->matrix_coefficients)) { 1101d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar coeffs = color->matrix_coefficients; 1102d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 1103d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar if (color->range != mkvparser::Colour::kValueNotPresent 1104d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar && color->range != 0 /* MKV unspecified */) { 1105d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar // We only support MKV broadcast range (== limited) and full range. 1106d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar // We treat all other value as the default limited range. 1107d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar fullRange = color->range == 2 /* MKV fullRange */; 1108d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar rangeSpecified = true; 1109d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 1110d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar 1111d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar ColorAspects aspects; 1112d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar ColorUtils::convertIsoColorAspectsToCodecAspects( 1113d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar primaries, transfer, coeffs, fullRange, aspects); 1114d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar meta->setInt32(kKeyColorPrimaries, aspects.mPrimaries); 1115d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar meta->setInt32(kKeyTransferFunction, aspects.mTransfer); 1116d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar meta->setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs); 1117d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar meta->setInt32( 1118d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar kKeyColorRange, rangeSpecified ? aspects.mRange : ColorAspects::RangeUnspecified); 1119d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 1120d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar 1121d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar // HDR Static Info 1122d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar { 1123d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar HDRStaticInfo info, nullInfo; // nullInfo is a fully unspecified static info 1124d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar memset(&info, 0, sizeof(info)); 1125d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar memset(&nullInfo, 0, sizeof(nullInfo)); 1126d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar if (isValidUint16ColourValue(color->max_cll)) { 1127d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar info.sType1.mMaxContentLightLevel = color->max_cll; 1128d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 1129d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar if (isValidUint16ColourValue(color->max_fall)) { 1130d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar info.sType1.mMaxFrameAverageLightLevel = color->max_fall; 1131d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 1132d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar const mkvparser::MasteringMetadata *mastering = color->mastering_metadata; 1133d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar if (mastering != NULL) { 1134d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar // Convert matroska values to HDRStaticInfo equivalent values for each fully specified 1135d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar // group. See CTA-681.3 section 3.2.1 for more info. 1136d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar if (mastering->luminance_max >= 0.5 && mastering->luminance_max < 65535.5) { 1137d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar info.sType1.mMaxDisplayLuminance = (uint16_t)(mastering->luminance_max + 0.5); 1138d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 1139d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar if (mastering->luminance_min >= 0.00005 && mastering->luminance_min < 6.55355) { 114012c703291529dd19bb83579f1e3b33ecb444340dLajos Molnar // HDRStaticInfo Type1 stores min luminance scaled 10000:1 1141d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar info.sType1.mMinDisplayLuminance = 1142d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar (uint16_t)(10000 * mastering->luminance_min + 0.5); 1143d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 114412c703291529dd19bb83579f1e3b33ecb444340dLajos Molnar // HDRStaticInfo Type1 stores primaries scaled 50000:1 1145d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar if (isValidPrimary(mastering->white_point)) { 1146d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar info.sType1.mW.x = (uint16_t)(50000 * mastering->white_point->x + 0.5); 1147d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar info.sType1.mW.y = (uint16_t)(50000 * mastering->white_point->y + 0.5); 1148d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 1149d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar if (isValidPrimary(mastering->r) && isValidPrimary(mastering->g) 1150d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar && isValidPrimary(mastering->b)) { 1151d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar info.sType1.mR.x = (uint16_t)(50000 * mastering->r->x + 0.5); 1152d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar info.sType1.mR.y = (uint16_t)(50000 * mastering->r->y + 0.5); 1153d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar info.sType1.mG.x = (uint16_t)(50000 * mastering->g->x + 0.5); 1154d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar info.sType1.mG.y = (uint16_t)(50000 * mastering->g->y + 0.5); 1155d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar info.sType1.mB.x = (uint16_t)(50000 * mastering->b->x + 0.5); 1156d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar info.sType1.mB.y = (uint16_t)(50000 * mastering->b->y + 0.5); 1157d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 1158d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 1159d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar // Only advertise static info if at least one of the groups have been specified. 1160d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar if (memcmp(&info, &nullInfo, sizeof(info)) != 0) { 1161d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar info.mID = HDRStaticInfo::kType1; 1162d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar meta->setData(kKeyHdrStaticInfo, 'hdrS', &info, sizeof(info)); 1163d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 1164d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar } 1165d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar} 1166d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar 1167093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubervoid MatroskaExtractor::addTracks() { 1168093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::Tracks *tracks = mSegment->GetTracks(); 1169093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1170093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber for (size_t index = 0; index < tracks->GetTracksCount(); ++index) { 1171093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::Track *track = tracks->GetTrackByIndex(index); 1172093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 117330ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber if (track == NULL) { 117430ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber // Apparently this is currently valid (if unexpected) behaviour 117530ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber // of the mkv parser lib. 117630ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber continue; 117730ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber } 117830ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber 1179093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *const codecID = track->GetCodecId(); 11803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("codec id = %s", codecID); 11813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("codec name = %s", track->GetCodecNameAsUTF8()); 1182093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 11831e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih if (codecID == NULL) { 11841e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih ALOGW("unknown codecID is not supported."); 11851e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih continue; 11861e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih } 11871e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih 1188093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t codecPrivateSize; 1189093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const unsigned char *codecPrivate = 1190ff1df9951d09f1a1a8ae2dbc42b82b0f9c164e5eAndreas Huber track->GetCodecPrivate(codecPrivateSize); 1191093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1192093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 }; 1193093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1194093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MetaData> meta = new MetaData; 1195093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 11965ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber status_t err = OK; 11975ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 1198093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber switch (track->GetType()) { 1199093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber case VIDEO_TRACK: 1200093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber { 1201093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::VideoTrack *vtrack = 1202093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber static_cast<const mkvparser::VideoTrack *>(track); 1203093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 12041e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { 1205093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 1206093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); 1207132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) { 1208132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang if (codecPrivateSize > 0) { 1209132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta->setCString( 1210132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 1211132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang addESDSFromCodecPrivate( 1212132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta, false, codecPrivate, codecPrivateSize); 1213132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else { 1214132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is detected, but does not have configuration.", 1215132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang codecID); 1216132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang continue; 1217132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } 1218093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcmp("V_VP8", codecID)) { 121994705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8); 122094705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang } else if (!strcmp("V_VP9", codecID)) { 122194705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9); 1222d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian if (codecPrivateSize > 0) { 1223d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian // 'csd-0' for VP9 is the Blob of Codec Private data as 1224d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian // specified in http://www.webmproject.org/vp9/profiles/. 1225d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian meta->setData( 1226d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian kKeyVp9CodecPrivate, 0, codecPrivate, 1227d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian codecPrivateSize); 1228d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian } 1229093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else { 1230132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is not supported.", codecID); 1231093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 1232093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1233093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1234093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyWidth, vtrack->GetWidth()); 1235093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyHeight, vtrack->GetHeight()); 1236d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar 1237d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar getColorInformation(vtrack, meta); 1238d637d296bb0954756d3d231633fad73fadd70316Lajos Molnar 1239093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber break; 1240093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1241093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1242093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber case AUDIO_TRACK: 1243093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber { 1244093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::AudioTrack *atrack = 1245093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber static_cast<const mkvparser::AudioTrack *>(track); 1246093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1247093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcmp("A_AAC", codecID)) { 1248093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); 1249093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(codecPrivateSize >= 2); 1250093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1251132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang addESDSFromCodecPrivate( 1252132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta, true, codecPrivate, codecPrivateSize); 1253093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcmp("A_VORBIS", codecID)) { 1254093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 1255093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 12565ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber err = addVorbisCodecInfo( 12575ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber meta, codecPrivate, codecPrivateSize); 1258bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } else if (!strcmp("A_OPUS", codecID)) { 1259bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS); 1260bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize); 1261bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay()); 1262bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll()); 1263bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSeekPreRollNs = track->GetSeekPreRoll(); 1264132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else if (!strcmp("A_MPEG/L3", codecID)) { 1265132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 1266093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else { 1267132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is not supported.", codecID); 1268093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 1269093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1270093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1271093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeySampleRate, atrack->GetSamplingRate()); 1272093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyChannelCount, atrack->GetChannels()); 1273093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber break; 1274093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1275093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1276093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber default: 1277093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 1278093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1279093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 12805ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (err != OK) { 12815ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ALOGE("skipping track, codec specific data was malformed."); 12825ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber continue; 12835ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 12845ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 1285093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long durationNs = mSegment->GetDuration(); 1286093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt64(kKeyDuration, (durationNs + 500) / 1000); 1287093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1288093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mTracks.push(); 12894f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih size_t n = mTracks.size() - 1; 12904f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih TrackInfo *trackInfo = &mTracks.editItemAt(n); 1291093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber trackInfo->mTrackNum = track->GetNumber(); 1292093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber trackInfo->mMeta = meta; 12932f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih trackInfo->mExtractor = this; 1294793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih 1295793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih trackInfo->mEncrypted = false; 1296793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih for(size_t i = 0; i < track->GetContentEncodingCount() && !trackInfo->mEncrypted; i++) { 1297793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih const mkvparser::ContentEncoding *encoding = track->GetContentEncodingByIndex(i); 1298793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih for(size_t j = 0; j < encoding->GetEncryptionCount(); j++) { 1299793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih const mkvparser::ContentEncoding::ContentEncryption *encryption; 1300793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih encryption = encoding->GetEncryptionByIndex(j); 1301793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih meta->setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len); 1302793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih trackInfo->mEncrypted = true; 1303793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih break; 1304793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih } 1305793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih } 13064f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih 13074f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (!strcmp("V_MPEG4/ISO/AVC", codecID) && codecPrivateSize == 0) { 13084f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih // Attempt to recover from AVC track without codec private data 13094f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih err = synthesizeAVCC(trackInfo, n); 13104f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (err != OK) { 13114f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih mTracks.pop(); 13124f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 13134f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 1314093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1315093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 1316093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 13175279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid MatroskaExtractor::findThumbnails() { 13185279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 13195279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber TrackInfo *info = &mTracks.editItemAt(i); 13205279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 13215279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const char *mime; 13225279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber CHECK(info->mMeta->findCString(kKeyMIMEType, &mime)); 13235279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 13245279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (strncasecmp(mime, "video/", 6)) { 13255279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber continue; 13265279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 13275279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 13282f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih BlockIterator iter(this, info->mTrackNum, i); 13294719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer int32_t j = 0; 13305279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t thumbnailTimeUs = 0; 13315279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber size_t maxBlockSize = 0; 13324719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer while (!iter.eos() && j < 20) { 13335279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (iter.block()->IsKey()) { 13344719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer ++j; 13355279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1336d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber size_t blockSize = 0; 1337cba4ed0039c8b8fac01b3193d19fc2364f934506Tareq A. Siraj for (int k = 0; k < iter.block()->GetFrameCount(); ++k) { 1338cba4ed0039c8b8fac01b3193d19fc2364f934506Tareq A. Siraj blockSize += iter.block()->GetFrame(k).len; 1339d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 1340d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 13415279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (blockSize > maxBlockSize) { 13425279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber maxBlockSize = blockSize; 13435279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber thumbnailTimeUs = iter.blockTimeUs(); 13445279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 13455279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 13465279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber iter.advance(); 13475279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 13485279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 13495279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 13505279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 13515279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1352093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaExtractor::getMetaData() { 1353093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MetaData> meta = new MetaData; 13548c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber 13558c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber meta->setCString( 13568c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber kKeyMIMEType, 13578c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA); 1358093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1359093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return meta; 1360093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 1361093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1362d42573cace9db2b5948e540c32beaef80f04153cAndreas Huberuint32_t MatroskaExtractor::flags() const { 1363d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber uint32_t x = CAN_PAUSE; 1364d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (!isLiveStreaming()) { 1365d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK; 1366d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 1367d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 1368d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return x; 1369d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 1370d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 1371093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberbool SniffMatroska( 13725a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 13735a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 1374093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader reader(source); 1375093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::EBMLHeader ebmlHeader; 1376093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long pos; 1377093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ebmlHeader.Parse(&reader, pos) < 0) { 1378093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return false; 1379093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1380093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1381093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA); 1382093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *confidence = 0.6; 1383093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1384093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return true; 1385093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 1386093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1387093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} // namespace android 1388