MatroskaExtractor.cpp revision 4f2559d3cdeb7187dedca186d5abc65af4bdb031
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> 27b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber#include <media/stagefright/foundation/hexdump.h> 28093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/DataSource.h> 29093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaBuffer.h> 30093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaDefs.h> 31093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaErrors.h> 32093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaSource.h> 33093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MetaData.h> 34b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber#include <media/stagefright/Utils.h> 35093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <utils/String8.h> 36093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 37b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross#include <inttypes.h> 38b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross 39093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubernamespace android { 40093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 41093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstruct DataSourceReader : public mkvparser::IMkvReader { 42093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader(const sp<DataSource> &source) 43093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mSource(source) { 44093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 45093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 46093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual int Read(long long position, long length, unsigned char* buffer) { 47093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(position >= 0); 48093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(length >= 0); 49093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 50093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (length == 0) { 51093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 52093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 53093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 54093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber ssize_t n = mSource->readAt(position, buffer, length); 55093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 56093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (n <= 0) { 57093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return -1; 58093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 59093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 60093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 61093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 62093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 63093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual int Length(long long* total, long long* available) { 64c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t size; 65093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (mSource->getSize(&size) != OK) { 66d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber *total = -1; 67d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber *available = (long long)((1ull << 63) - 1); 68d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 69d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return 0; 70093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 71093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 72093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (total) { 73093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *total = size; 74093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 75093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 76093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (available) { 77093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *available = size; 78093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 79093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 80093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 81093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 82093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 83093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberprivate: 84093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<DataSource> mSource; 85093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 86093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader(const DataSourceReader &); 87093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader &operator=(const DataSourceReader &); 88093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}; 89093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 90093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber//////////////////////////////////////////////////////////////////////////////// 91093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 925279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberstruct BlockIterator { 932f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index); 945279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 955279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber bool eos() const; 965279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 975279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber void advance(); 985279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber void reset(); 995ec58d925520e6913fba3fc54413881af751c610Andreas Huber 1005ec58d925520e6913fba3fc54413881af751c610Andreas Huber void seek( 101f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann int64_t seekTimeUs, bool isAudio, 1025ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t *actualFrameTimeUs); 1035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1045279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::Block *block() const; 1055279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t blockTimeUs() const; 1065279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1075279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberprivate: 108d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber MatroskaExtractor *mExtractor; 109b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross long long mTrackNum; 1102f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih unsigned long mIndex; 1115279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 112d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Cluster *mCluster; 1135279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::BlockEntry *mBlockEntry; 114d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long mBlockEntryIndex; 115d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 116d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber void advance_l(); 1175279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1185279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator(const BlockIterator &); 1195279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator &operator=(const BlockIterator &); 1205279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}; 1215279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 122093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstruct MatroskaSource : public MediaSource { 123093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource( 124093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MatroskaExtractor> &extractor, size_t index); 125093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 126093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t start(MetaData *params); 127093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t stop(); 128093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 129093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual sp<MetaData> getFormat(); 130093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 131093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t read( 132093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MediaBuffer **buffer, const ReadOptions *options); 133093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 13450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberprotected: 13550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber virtual ~MatroskaSource(); 13650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 137093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberprivate: 138093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber enum Type { 139093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber AVC, 140093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber AAC, 141093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber OTHER 142093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber }; 143093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 144093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MatroskaExtractor> mExtractor; 145093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t mTrackIndex; 146093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber Type mType; 14774a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber bool mIsAudio; 1485279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator mBlockIter; 1494f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih ssize_t mNALSizeLen; // for type AVC 150093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 15150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber List<MediaBuffer *> mPendingFrames; 15250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 153093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber status_t advance(); 154093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 155793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih status_t setWebmBlockCryptoInfo(MediaBuffer *mbuf); 15650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber status_t readBlock(); 15750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber void clearPendingFrames(); 15850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 159093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource(const MatroskaSource &); 160093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource &operator=(const MatroskaSource &); 161093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}; 162093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1632f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shihconst mkvparser::Track* MatroskaExtractor::TrackInfo::getTrack() const { 1642f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return mExtractor->mSegment->GetTracks()->GetTrackByNumber(mTrackNum); 1652f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih} 1662f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 1672f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih// This function does exactly the same as mkvparser::Cues::Find, except that it 1682f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih// searches in our own track based vectors. We should not need this once mkvparser 1692f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih// adds the same functionality. 1702f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shihconst mkvparser::CuePoint::TrackPosition *MatroskaExtractor::TrackInfo::find( 1712f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih long long timeNs) const { 1722f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih ALOGV("mCuePoints.size %zu", mCuePoints.size()); 1732f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (mCuePoints.empty()) { 1742f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return NULL; 1752f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 1762f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 1772f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::CuePoint* cp = mCuePoints.itemAt(0); 1782f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::Track* track = getTrack(); 1792f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (timeNs <= cp->GetTime(mExtractor->mSegment)) { 1802f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return cp->Find(track); 1812f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 1822f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 1832f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih // Binary searches through relevant cues; assumes cues are ordered by timecode. 1842f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih // If we do detect out-of-order cues, return NULL. 1852f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih size_t lo = 0; 1862f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih size_t hi = mCuePoints.size(); 1872f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih while (lo < hi) { 1882f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const size_t mid = lo + (hi - lo) / 2; 1892f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::CuePoint* const midCp = mCuePoints.itemAt(mid); 1902f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const long long cueTimeNs = midCp->GetTime(mExtractor->mSegment); 1912f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (cueTimeNs <= timeNs) { 1922f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih lo = mid + 1; 1932f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } else { 1942f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih hi = mid; 1952f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 1962f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 1972f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 1982f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (lo == 0) { 1992f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return NULL; 2002f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 2012f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 2022f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih cp = mCuePoints.itemAt(lo - 1); 2032f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (cp->GetTime(mExtractor->mSegment) > timeNs) { 2042f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return NULL; 2052f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 2062f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 2072f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih return cp->Find(track); 2082f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih} 2092f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 210093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaSource::MatroskaSource( 211093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MatroskaExtractor> &extractor, size_t index) 212093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mExtractor(extractor), 213093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mTrackIndex(index), 214093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType(OTHER), 21574a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber mIsAudio(false), 216d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter(mExtractor.get(), 2172f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih mExtractor->mTracks.itemAt(index).mTrackNum, 2182f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih index), 2194f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih mNALSizeLen(-1) { 220b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta; 221b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 222093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *mime; 223b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber CHECK(meta->findCString(kKeyMIMEType, &mime)); 224093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 22574a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber mIsAudio = !strncasecmp("audio/", mime, 6); 22674a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 227093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 228093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType = AVC; 229b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 230b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber uint32_t dummy; 231b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber const uint8_t *avcc; 232b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber size_t avccSize; 2334f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih int32_t nalSizeLen = 0; 2344f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (meta->findInt32(kKeyNalLengthSize, &nalSizeLen)) { 2354f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (nalSizeLen >= 0 && nalSizeLen <= 4) { 2364f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih mNALSizeLen = nalSizeLen; 2374f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 2384f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } else if (meta->findData(kKeyAVCC, &dummy, (const void **)&avcc, &avccSize) 2394f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih && avccSize >= 5u) { 2404f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih mNALSizeLen = 1 + (avcc[4] & 3); 2414f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih ALOGV("mNALSizeLen = %zd", mNALSizeLen); 2424f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } else { 2434f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih ALOGE("No mNALSizeLen"); 2444f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 245093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 246093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType = AAC; 247093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 248093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 249093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 25050c8bea8fba2fcafb14696399028bdbc094dc995Andreas HuberMatroskaSource::~MatroskaSource() { 25150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 25250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 25350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 25484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MatroskaSource::start(MetaData * /* params */) { 2554f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (mType == AVC && mNALSizeLen < 0) { 2564f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih return ERROR_MALFORMED; 2574f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 2584f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih 2595279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mBlockIter.reset(); 260093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 261093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 262093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 263093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 264093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstatus_t MatroskaSource::stop() { 26550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 26650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 267093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 268093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 269093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 270093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaSource::getFormat() { 271093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mExtractor->mTracks.itemAt(mTrackIndex).mMeta; 272093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 273093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 2745279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber//////////////////////////////////////////////////////////////////////////////// 2755279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2765279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas HuberBlockIterator::BlockIterator( 2772f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih MatroskaExtractor *extractor, unsigned long trackNum, unsigned long index) 278d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber : mExtractor(extractor), 2795279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mTrackNum(trackNum), 2802f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih mIndex(index), 2815279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mCluster(NULL), 282d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntry(NULL), 283d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex(0) { 2845279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber reset(); 2855279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 2865279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2875279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberbool BlockIterator::eos() const { 2885279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return mCluster == NULL || mCluster->EOS(); 2895279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 2905279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2915279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::advance() { 292d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 293d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 294d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 295d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 296d42573cace9db2b5948e540c32beaef80f04153cAndreas Hubervoid BlockIterator::advance_l() { 297d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber for (;;) { 298d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry); 2993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetEntry returned %ld", res); 300d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 301d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long long pos; 302d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long len; 303d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (res < 0) { 304d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // Need to parse this cluster some more 305d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 306d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL); 307d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 308d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mCluster->Parse(pos, len); 3093856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Parse returned %ld", res); 310d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 311d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (res < 0) { 312d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // I/O error 313d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 31429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cluster::Parse returned result %ld", res); 3155279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 316d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = NULL; 3175279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber break; 318093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 3195279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 320d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber continue; 321d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } else if (res == 0) { 322d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // We're done with this cluster 323d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 324d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Cluster *nextCluster; 325d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mExtractor->mSegment->ParseNext( 326d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster, nextCluster, pos, len); 3273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ParseNext returned %ld", res); 328d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 329e467ef084b75b074d0081616080b54212a7024c8Lajos Molnar if (res != 0) { 330e467ef084b75b074d0081616080b54212a7024c8Lajos Molnar // EOF or error 331d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 332d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = NULL; 333d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber break; 334d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 335d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 336d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_EQ(res, 0); 337d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(nextCluster != NULL); 338d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(!nextCluster->EOS()); 339d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 340d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = nextCluster; 341d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 342d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mCluster->Parse(pos, len); 3433856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Parse (2) returned %ld", res); 344d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_GE(res, 0); 345d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 346d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex = 0; 347d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber continue; 348093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 349093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 350d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(mBlockEntry != NULL); 351d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(mBlockEntry->GetBlock() != NULL); 352d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber ++mBlockEntryIndex; 353d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 354d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) { 3555279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber break; 356093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 3575279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 3585279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 3595279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 3605279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::reset() { 361d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 362093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 363d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = mExtractor->mSegment->GetFirst(); 3642ba7ce928b0fa8917ee202836b0963ca58613453Andreas Huber mBlockEntry = NULL; 365d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex = 0; 366d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 367d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber do { 368d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 369d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } while (!eos() && block()->GetTrackNumber() != mTrackNum); 3705279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 371093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 3725ec58d925520e6913fba3fc54413881af751c610Andreas Hubervoid BlockIterator::seek( 373f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann int64_t seekTimeUs, bool isAudio, 3745ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t *actualFrameTimeUs) { 375d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 376d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 3775ec58d925520e6913fba3fc54413881af751c610Andreas Huber *actualFrameTimeUs = -1ll; 3785ec58d925520e6913fba3fc54413881af751c610Andreas Huber 379bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const int64_t seekTimeNs = seekTimeUs * 1000ll - mExtractor->mSeekPreRollNs; 38010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 38110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mkvparser::Segment* const pSegment = mExtractor->mSegment; 38210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 38310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // Special case the 0 seek to avoid loading Cues when the application 38410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // extraneously seeks to 0 before playing. 38510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (seekTimeNs <= 0) { 386b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("Seek to beginning: %" PRId64, seekTimeUs); 38710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mCluster = pSegment->GetFirst(); 38810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mBlockEntryIndex = 0; 38910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann do { 39010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann advance_l(); 39110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } while (!eos() && block()->GetTrackNumber() != mTrackNum); 39210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 39310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 3945ec58d925520e6913fba3fc54413881af751c610Andreas Huber 395b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("Seeking to: %" PRId64, seekTimeUs); 39610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 39710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // If the Cues have not been located then find them. 39810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::Cues* pCues = pSegment->GetCues(); 39910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::SeekHead* pSH = pSegment->GetSeekHead(); 40010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (!pCues && pSH) { 40110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const size_t count = pSH->GetCount(); 40210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::SeekHead::Entry* pEntry; 40310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGV("No Cues yet"); 40410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 40510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann for (size_t index = 0; index < count; index++) { 40610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pEntry = pSH->GetEntry(index); 40710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 40810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (pEntry->id == 0x0C53BB6B) { // Cues ID 40910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann long len; long long pos; 41010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pSegment->ParseCues(pEntry->pos, pos, len); 41110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pCues = pSegment->GetCues(); 412be7ac3d682729048af27871311808a76c618abdbJohann ALOGV("Cues found"); 41310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann break; 41410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 41510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 41610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 41710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (!pCues) { 41810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGE("No Cues in file"); 41910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 42010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 42110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 42210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann else if (!pSH) { 42310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGE("No SeekHead"); 42410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 42510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 42610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 42710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::CuePoint* pCP; 4282f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih mkvparser::Tracks const *pTracks = pSegment->GetTracks(); 42910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann while (!pCues->DoneParsing()) { 430be7ac3d682729048af27871311808a76c618abdbJohann pCues->LoadCuePoint(); 43110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pCP = pCues->GetLast(); 4322f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih CHECK(pCP); 4332f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 4340644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih size_t trackCount = mExtractor->mTracks.size(); 4352f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih for (size_t index = 0; index < trackCount; ++index) { 4360644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(index); 4370644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih const mkvparser::Track *pTrack = pTracks->GetTrackByNumber(track.mTrackNum); 4382f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (pTrack && pTrack->GetType() == 1 && pCP->Find(pTrack)) { // VIDEO_TRACK 4392f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih track.mCuePoints.push_back(pCP); 4402f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 4412f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 442be7ac3d682729048af27871311808a76c618abdbJohann 44310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (pCP->GetTime(pSegment) >= seekTimeNs) { 444be7ac3d682729048af27871311808a76c618abdbJohann ALOGV("Parsed past relevant Cue"); 44510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann break; 44610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 44710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 44810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 4492f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::CuePoint::TrackPosition *pTP = NULL; 4500644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih const mkvparser::Track *thisTrack = pTracks->GetTrackByNumber(mTrackNum); 4512f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (thisTrack->GetType() == 1) { // video 4522f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(mIndex); 4532f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih pTP = track.find(seekTimeNs); 4542f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } else { 4552f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih // The Cue index is built around video keyframes 4560644f95a8976470e84c6c0a6d96585ae6437ecd2Robert Shih unsigned long int trackCount = pTracks->GetTracksCount(); 4572f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih for (size_t index = 0; index < trackCount; ++index) { 4582f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih const mkvparser::Track *pTrack = pTracks->GetTrackByIndex(index); 4592f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (pTrack && pTrack->GetType() == 1 && pCues->Find(seekTimeNs, pTrack, pCP, pTP)) { 4602f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih ALOGV("Video track located at %zu", index); 4612f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih break; 4622f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 46310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 46410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 46510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 4662f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih 467f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // Always *search* based on the video track, but finalize based on mTrackNum 4682f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (!pTP) { 469f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann ALOGE("Did not locate the video track for seeking"); 47010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 47110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 47210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 47310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos); 4745279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 475f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK(mCluster); 476f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK(!mCluster->EOS()); 477f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann 478f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // mBlockEntryIndex starts at 0 but m_block starts at 1 479f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK_GT(pTP->m_block, 0); 480f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann mBlockEntryIndex = pTP->m_block - 1; 4815ec58d925520e6913fba3fc54413881af751c610Andreas Huber 4825ec58d925520e6913fba3fc54413881af751c610Andreas Huber for (;;) { 483d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 4845279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 485f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann if (eos()) break; 4865ec58d925520e6913fba3fc54413881af751c610Andreas Huber 487f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann if (isAudio || block()->IsKey()) { 488f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // Accept the first key frame 4892f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih int64_t frameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL; 4902f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih if (thisTrack->GetType() == 1 || frameTimeUs >= seekTimeUs) { 4912f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih *actualFrameTimeUs = frameTimeUs; 4922f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih ALOGV("Requested seek point: %" PRId64 " actual: %" PRId64, 4932f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih seekTimeUs, *actualFrameTimeUs); 4942f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih break; 4952f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih } 49674a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber } 4975279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 498093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 499093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 5005279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberconst mkvparser::Block *BlockIterator::block() const { 5015279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber CHECK(!eos()); 5025279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 5035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return mBlockEntry->GetBlock(); 5045279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 5055279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 5065279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberint64_t BlockIterator::blockTimeUs() const { 5074f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (mCluster == NULL || mBlockEntry == NULL) { 5084f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih return -1; 5094f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 5105279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll; 5115279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 5125279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 5135279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber//////////////////////////////////////////////////////////////////////////////// 5145279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 515b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huberstatic unsigned U24_AT(const uint8_t *ptr) { 516b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; 517b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber} 518b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 51950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Hubervoid MatroskaSource::clearPendingFrames() { 52050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (!mPendingFrames.empty()) { 52150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer *frame = *mPendingFrames.begin(); 52250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.erase(mPendingFrames.begin()); 52350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 52450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber frame->release(); 52550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber frame = NULL; 52650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 52750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 52850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 529793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shihstatus_t MatroskaSource::setWebmBlockCryptoInfo(MediaBuffer *mbuf) { 530793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih if (mbuf->range_length() < 1 || mbuf->range_length() - 1 > INT32_MAX) { 531793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih // 1-byte signal 532793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih return ERROR_MALFORMED; 533793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih } 534793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih 535793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih const uint8_t *data = (const uint8_t *)mbuf->data() + mbuf->range_offset(); 536793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih bool blockEncrypted = data[0] & 0x1; 537793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih if (blockEncrypted && mbuf->range_length() < 9) { 538793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih // 1-byte signal + 8-byte IV 539793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih return ERROR_MALFORMED; 540793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih } 541793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih 542793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih sp<MetaData> meta = mbuf->meta_data(); 543793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih if (blockEncrypted) { 544793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih /* 545793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * 0 1 2 3 546793c9fb11114c7be4636b8cae5477995aadeb71dRobert 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 547793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 548793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | Signal Byte | | 549793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * +-+-+-+-+-+-+-+-+ IV | 550793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | | 551793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 552793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | | | 553793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * |-+-+-+-+-+-+-+-+ | 554793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * : Bytes 1..N of encrypted frame : 555793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | | 556793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | | 557793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 558793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih */ 559793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih int32_t plainSizes[] = { 0 }; 560793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih int32_t encryptedSizes[] = { static_cast<int32_t>(mbuf->range_length() - 9) }; 561793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih uint8_t ctrCounter[16] = { 0 }; 562793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih uint32_t type; 563793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih const uint8_t *keyId; 564793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih size_t keyIdSize; 565793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih sp<MetaData> trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta; 566793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih CHECK(trackMeta->findData(kKeyCryptoKey, &type, (const void **)&keyId, &keyIdSize)); 567793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih meta->setData(kKeyCryptoKey, 0, keyId, keyIdSize); 568793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih memcpy(ctrCounter, data + 1, 8); 569793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih meta->setData(kKeyCryptoIV, 0, ctrCounter, 16); 570793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes)); 571793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes)); 572793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih mbuf->set_range(9, mbuf->range_length() - 9); 573793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih } else { 574793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih /* 575793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * 0 1 2 3 576793c9fb11114c7be4636b8cae5477995aadeb71dRobert 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 577793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 578793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | Signal Byte | | 579793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * +-+-+-+-+-+-+-+-+ | 580793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * : Bytes 1..N of unencrypted frame : 581793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | | 582793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * | | 583793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 584793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih */ 585793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih int32_t plainSizes[] = { static_cast<int32_t>(mbuf->range_length() - 1) }; 586793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih int32_t encryptedSizes[] = { 0 }; 587793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih meta->setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes)); 588793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih meta->setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes)); 589793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih mbuf->set_range(1, mbuf->range_length() - 1); 590793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih } 591793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih 592793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih return OK; 593793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih} 594793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih 59550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatus_t MatroskaSource::readBlock() { 59650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber CHECK(mPendingFrames.empty()); 59750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 5985279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (mBlockIter.eos()) { 599093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return ERROR_END_OF_STREAM; 600093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 601093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 6025279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::Block *block = mBlockIter.block(); 60350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 6045279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t timeUs = mBlockIter.blockTimeUs(); 605093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 606d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber for (int i = 0; i < block->GetFrameCount(); ++i) { 607d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Block::Frame &frame = block->GetFrame(i); 608b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 609d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber MediaBuffer *mbuf = new MediaBuffer(frame.len); 610d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mbuf->meta_data()->setInt64(kKeyTime, timeUs); 611d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey()); 612093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 613793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih status_t err = frame.Read(mExtractor->mReader, static_cast<uint8_t *>(mbuf->data())); 614793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih if (err == OK 615793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih && mExtractor->mIsWebm 616793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih && mExtractor->mTracks.itemAt(mTrackIndex).mEncrypted) { 617793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih err = setWebmBlockCryptoInfo(mbuf); 618793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih } 619793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih 620793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih if (err != OK) { 621d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mPendingFrames.clear(); 62250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 623d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter.advance(); 624ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen mbuf->release(); 625793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih return err; 62650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 62750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 62850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.push_back(mbuf); 62950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 63050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 631d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter.advance(); 63250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 63350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return OK; 63450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 63550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 63650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatus_t MatroskaSource::read( 63750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer **out, const ReadOptions *options) { 63850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = NULL; 63950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 6405ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t targetSampleTimeUs = -1ll; 6415ec58d925520e6913fba3fc54413881af751c610Andreas Huber 64250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber int64_t seekTimeUs; 64350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber ReadOptions::SeekMode mode; 644d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode) 645d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && !mExtractor->isLiveStreaming()) { 64650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 64774a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 648f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // The audio we want is located by using the Cues to seek the video 649f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // stream to find the target Cluster then iterating to finalize for 650f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // audio. 6515ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t actualFrameTimeUs; 652f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs); 6535ec58d925520e6913fba3fc54413881af751c610Andreas Huber 6545ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 6555ec58d925520e6913fba3fc54413881af751c610Andreas Huber targetSampleTimeUs = actualFrameTimeUs; 6565ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 65750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 65850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 65950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (mPendingFrames.empty()) { 66050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber status_t err = readBlock(); 66150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 66250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber if (err != OK) { 66350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 66450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 66550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return err; 66650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 66750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 66850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 66950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer *frame = *mPendingFrames.begin(); 67050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.erase(mPendingFrames.begin()); 67150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 6724f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (mType != AVC || mNALSizeLen == 0) { 6735ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (targetSampleTimeUs >= 0ll) { 6745ec58d925520e6913fba3fc54413881af751c610Andreas Huber frame->meta_data()->setInt64( 6755ec58d925520e6913fba3fc54413881af751c610Andreas Huber kKeyTargetTime, targetSampleTimeUs); 6765ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 6775ec58d925520e6913fba3fc54413881af751c610Andreas Huber 67850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = frame; 67950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 68050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return OK; 68150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 68250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 683792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // Each input frame contains one or more NAL fragments, each fragment 684792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // is prefixed by mNALSizeLen bytes giving the fragment length, 685792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // followed by a corresponding number of bytes containing the fragment. 686792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // We output all these fragments into a single large buffer separated 687792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // by startcodes (0x00 0x00 0x00 0x01). 6884f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih // 6894f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih // When mNALSizeLen is 0, we assume the data is already in the format 6904f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih // desired. 691792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 692792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber const uint8_t *srcPtr = 693792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber (const uint8_t *)frame->data() + frame->range_offset(); 694792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 695792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t srcSize = frame->range_length(); 696792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 697792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t dstSize = 0; 698792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber MediaBuffer *buffer = NULL; 699792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber uint8_t *dstPtr = NULL; 700792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 701792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber for (int32_t pass = 0; pass < 2; ++pass) { 702792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t srcOffset = 0; 703792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t dstOffset = 0; 704792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber while (srcOffset + mNALSizeLen <= srcSize) { 705792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t NALsize; 706792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber switch (mNALSizeLen) { 707792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 1: NALsize = srcPtr[srcOffset]; break; 708792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 2: NALsize = U16_AT(srcPtr + srcOffset); break; 709792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 3: NALsize = U24_AT(srcPtr + srcOffset); break; 710792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 4: NALsize = U32_AT(srcPtr + srcOffset); break; 711792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber default: 712792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber TRESPASS(); 713792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 71450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 7152dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih if (srcOffset + mNALSizeLen + NALsize <= srcOffset + mNALSizeLen) { 7162dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih frame->release(); 7172dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih frame = NULL; 7182dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih 7192dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih return ERROR_MALFORMED; 7202dcf6138ebc9c5688aeae151d2fbde55a2826128Robert Shih } else if (srcOffset + mNALSizeLen + NALsize > srcSize) { 721792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber break; 722792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 72350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 724792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (pass == 1) { 725792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4); 72650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 727ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen if (frame != buffer) { 728ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen memcpy(&dstPtr[dstOffset + 4], 729ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen &srcPtr[srcOffset + mNALSizeLen], 730ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen NALsize); 731ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen } 732792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 73350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 734792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstOffset += 4; // 0x00 00 00 01 735792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstOffset += NALsize; 73650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 737792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber srcOffset += mNALSizeLen + NALsize; 738792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 73950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 740792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (srcOffset < srcSize) { 741792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // There were trailing bytes or not enough data to complete 742792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // a fragment. 74350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 744792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame->release(); 745792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame = NULL; 74650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 747792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber return ERROR_MALFORMED; 748792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 74950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 750792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (pass == 0) { 751792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstSize = dstOffset; 75250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 753ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen if (dstSize == srcSize && mNALSizeLen == 4) { 754ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen // In this special case we can re-use the input buffer by substituting 755ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen // each 4-byte nal size with a 4-byte start code 756ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen buffer = frame; 757ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen } else { 758ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen buffer = new MediaBuffer(dstSize); 759ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen } 76050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 761792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber int64_t timeUs; 762792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs)); 763792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber int32_t isSync; 764792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)); 76550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 766792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 767792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync); 76850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 769792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstPtr = (uint8_t *)buffer->data(); 770792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 77150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 77250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 773ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen if (frame != buffer) { 774ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen frame->release(); 775ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen frame = NULL; 776ba29bb20a18aa98813ce42f99cff4910a153e87cMarco Nelissen } 77750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 7785ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (targetSampleTimeUs >= 0ll) { 7795ec58d925520e6913fba3fc54413881af751c610Andreas Huber buffer->meta_data()->setInt64( 7805ec58d925520e6913fba3fc54413881af751c610Andreas Huber kKeyTargetTime, targetSampleTimeUs); 7815ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 7825ec58d925520e6913fba3fc54413881af751c610Andreas Huber 78350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = buffer; 784093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 785093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 786093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 787093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 788093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber//////////////////////////////////////////////////////////////////////////////// 789093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 790093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source) 791093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mDataSource(source), 792093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mReader(new DataSourceReader(mDataSource)), 7935279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mSegment(NULL), 7948c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mExtractedThumbnails(false), 795bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mIsWebm(false), 796bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSeekPreRollNs(0) { 797d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber off64_t size; 798d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mIsLiveStreaming = 799d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber (mDataSource->flags() 800d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber & (DataSource::kWantsPrefetching 801d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber | DataSource::kIsCachingDataSource)) 802d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && mDataSource->getSize(&size) != OK; 803d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 804093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::EBMLHeader ebmlHeader; 805093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long pos; 806093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ebmlHeader.Parse(mReader, pos) < 0) { 807093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 808093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 809093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8108c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) { 8118c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mIsWebm = true; 8128c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber } 8138c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber 814093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long ret = 815093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::Segment::CreateInstance(mReader, pos, mSegment); 816093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 817093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ret) { 818093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(mSegment == NULL); 819093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 820093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 821093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 822c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar // from mkvparser::Segment::Load(), but stop at first cluster 82310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ret = mSegment->ParseHeaders(); 824c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar if (ret == 0) { 825c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar long len; 826c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ret = mSegment->LoadCluster(pos, len); 827c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar if (ret >= 1) { 828c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar // no more clusters 829c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ret = 0; 830c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar } 831c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar } else if (ret > 0) { 832c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ret = mkvparser::E_BUFFER_NOT_FULL; 833c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar } 834093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 835093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ret < 0) { 836c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ALOGW("Corrupt %s source: %s", mIsWebm ? "webm" : "matroska", 837c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar uriDebugString(mDataSource->getUri()).c_str()); 838093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mSegment; 839093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mSegment = NULL; 840093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 841093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 842093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 84374a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber#if 0 84474a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber const mkvparser::SegmentInfo *info = mSegment->GetInfo(); 845df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("muxing app: %s, writing app: %s", 84674a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber info->GetMuxingAppAsUTF8(), 84774a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber info->GetWritingAppAsUTF8()); 84874a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber#endif 84974a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 850093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber addTracks(); 851093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 852093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 853093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::~MatroskaExtractor() { 854093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mSegment; 855093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mSegment = NULL; 856093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 857093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mReader; 858093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mReader = NULL; 859093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 860093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 861093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersize_t MatroskaExtractor::countTracks() { 862093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mTracks.size(); 863093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 864093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 865b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissensp<IMediaSource> MatroskaExtractor::getTrack(size_t index) { 866093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (index >= mTracks.size()) { 867093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return NULL; 868093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 869093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 870093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return new MatroskaSource(this, index); 871093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 872093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 873093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaExtractor::getTrackMetaData( 874093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t index, uint32_t flags) { 875093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (index >= mTracks.size()) { 876093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return NULL; 877093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 878093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 879d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails 880d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && !isLiveStreaming()) { 8815279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber findThumbnails(); 8825279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mExtractedThumbnails = true; 8835279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 8845279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 885093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mTracks.itemAt(index).mMeta; 886093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 887093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 888d42573cace9db2b5948e540c32beaef80f04153cAndreas Huberbool MatroskaExtractor::isLiveStreaming() const { 889d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return mIsLiveStreaming; 890d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 891d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 892403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissenstatic int bytesForSize(size_t size) { 893403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen // use at most 28 bits (4 times 7) 894403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen CHECK(size <= 0xfffffff); 895403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 896403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen if (size > 0x1fffff) { 897403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 4; 898403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } else if (size > 0x3fff) { 899403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 3; 900403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } else if (size > 0x7f) { 901403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 2; 902403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } 903403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 1; 904403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen} 905403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 906403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissenstatic void storeSize(uint8_t *data, size_t &idx, size_t size) { 907403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int numBytes = bytesForSize(size); 908403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen idx += numBytes; 909403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 910403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen data += idx; 911403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size_t next = 0; 912403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen while (numBytes--) { 913403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen *--data = (size & 0x7f) | next; 914403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size >>= 7; 915403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen next = 0x80; 916403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } 917403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen} 918403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 919132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kangstatic void addESDSFromCodecPrivate( 920132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang const sp<MetaData> &meta, 921132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang bool isAudio, const void *priv, size_t privSize) { 922093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 923403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int privSizeBytesRequired = bytesForSize(privSize); 924403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize2 = 14 + privSizeBytesRequired + privSize; 925403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize2BytesRequired = bytesForSize(esdsSize2); 926403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2; 927403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize1BytesRequired = bytesForSize(esdsSize1); 928403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1; 929093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber uint8_t *esds = new uint8_t[esdsSize]; 930403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 931403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size_t idx = 0; 932403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x03; 933403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen storeSize(esds, idx, esdsSize1); 934403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; // ES_ID 935403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; // ES_ID 936403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag 937403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x04; 938403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen storeSize(esds, idx, esdsSize2); 939403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = isAudio ? 0x40 // Audio ISO/IEC 14496-3 940403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen : 0x20; // Visual ISO/IEC 14496-2 941403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen for (int i = 0; i < 12; i++) { 942403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; 943403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } 944403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x05; 945403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen storeSize(esds, idx, privSize); 946403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen memcpy(esds + idx, priv, privSize); 94782ac8bf2da940c4439786c346f739f4a496864adAndreas Huber 948093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData(kKeyESDS, 0, esds, esdsSize); 949093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 950093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete[] esds; 951093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber esds = NULL; 952093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 953093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9545ce181568da90c78ba7fad3e084c8479041545dfAndreas Huberstatus_t addVorbisCodecInfo( 955093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MetaData> &meta, 956093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const void *_codecPrivate, size_t codecPrivateSize) { 957093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber // hexdump(_codecPrivate, codecPrivateSize); 958093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9595ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivateSize < 1) { 9605ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 9615ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 962093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 963093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate; 964093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9655ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[0] != 0x02) { 9665ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 9675ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 968093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9695ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber // codecInfo starts with two lengths, len1 and len2, that are 9705ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber // "Xiph-style-lacing encoded"... 971093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9725ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t offset = 1; 9735ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t len1 = 0; 9745ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 9757d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len1 > (SIZE_MAX - 0xff)) { 9767d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen return ERROR_MALFORMED; // would overflow 9777d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen } 9785ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len1 += 0xff; 9795ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ++offset; 9805ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 9815ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (offset >= codecPrivateSize) { 9825ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 9835ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 9847d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len1 > (SIZE_MAX - codecPrivate[offset])) { 9857d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen return ERROR_MALFORMED; // would overflow 9867d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen } 9875ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len1 += codecPrivate[offset++]; 988093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9895ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t len2 = 0; 9905ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 9917d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len2 > (SIZE_MAX - 0xff)) { 9927d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen return ERROR_MALFORMED; // would overflow 9937d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen } 9945ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len2 += 0xff; 9955ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ++offset; 9965ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 9975ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (offset >= codecPrivateSize) { 9985ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 9995ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 10007d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len2 > (SIZE_MAX - codecPrivate[offset])) { 10017d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen return ERROR_MALFORMED; // would overflow 10027d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen } 10035ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len2 += codecPrivate[offset++]; 10045ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 10057d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen if (len1 > SIZE_MAX - len2 || offset > SIZE_MAX - (len1 + len2) || 10067d681539b821664d0417f8dd6beaed3352b34787Marco Nelissen codecPrivateSize < offset + len1 + len2) { 10075ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 10085ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 10095ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 10105ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x01) { 10115ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 10125ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 10135ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1); 10145ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 10155ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber offset += len1; 10165ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x03) { 10175ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 10185ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 10195ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 10205ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber offset += len2; 10215ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x05) { 10225ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 10235ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 1024093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1025093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData( 10265ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber kKeyVorbisBooks, 0, &codecPrivate[offset], 10275ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber codecPrivateSize - offset); 10285ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 10295ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return OK; 1030093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 1031093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 10324f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shihstatus_t MatroskaExtractor::synthesizeAVCC(TrackInfo *trackInfo, size_t index) { 10334f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih BlockIterator iter(this, trackInfo->mTrackNum, index); 10344f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (iter.eos()) { 10354f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih return ERROR_MALFORMED; 10364f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 10374f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih 10384f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih const mkvparser::Block *block = iter.block(); 10394f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (block->GetFrameCount() <= 0) { 10404f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih return ERROR_MALFORMED; 10414f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 10424f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih 10434f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih const mkvparser::Block::Frame &frame = block->GetFrame(0); 10444f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih sp<ABuffer> abuf = new ABuffer(frame.len); 10454f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih long n = frame.Read(mReader, abuf->data()); 10464f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (n != 0) { 10474f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih return ERROR_MALFORMED; 10484f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 10494f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih 10504f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih sp<MetaData> avcMeta = MakeAVCCodecSpecificData(abuf); 10514f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (avcMeta == NULL) { 10524f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih return ERROR_MALFORMED; 10534f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 10544f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih 10554f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih // Override the synthesized nal length size, which is arbitrary 10564f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih avcMeta->setInt32(kKeyNalLengthSize, 0); 10574f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih trackInfo->mMeta = avcMeta; 10584f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih return OK; 10594f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih} 10604f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih 1061093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubervoid MatroskaExtractor::addTracks() { 1062093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::Tracks *tracks = mSegment->GetTracks(); 1063093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1064093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber for (size_t index = 0; index < tracks->GetTracksCount(); ++index) { 1065093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::Track *track = tracks->GetTrackByIndex(index); 1066093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 106730ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber if (track == NULL) { 106830ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber // Apparently this is currently valid (if unexpected) behaviour 106930ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber // of the mkv parser lib. 107030ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber continue; 107130ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber } 107230ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber 1073093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *const codecID = track->GetCodecId(); 10743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("codec id = %s", codecID); 10753856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("codec name = %s", track->GetCodecNameAsUTF8()); 1076093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 10771e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih if (codecID == NULL) { 10781e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih ALOGW("unknown codecID is not supported."); 10791e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih continue; 10801e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih } 10811e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih 1082093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t codecPrivateSize; 1083093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const unsigned char *codecPrivate = 1084ff1df9951d09f1a1a8ae2dbc42b82b0f9c164e5eAndreas Huber track->GetCodecPrivate(codecPrivateSize); 1085093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1086093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 }; 1087093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1088093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MetaData> meta = new MetaData; 1089093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 10905ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber status_t err = OK; 10915ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 1092093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber switch (track->GetType()) { 1093093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber case VIDEO_TRACK: 1094093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber { 1095093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::VideoTrack *vtrack = 1096093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber static_cast<const mkvparser::VideoTrack *>(track); 1097093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 10981e2a0e6adc3d70879b00e5295c54a74209b71e1bRobert Shih if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { 1099093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 1100093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); 1101132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) { 1102132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang if (codecPrivateSize > 0) { 1103132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta->setCString( 1104132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 1105132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang addESDSFromCodecPrivate( 1106132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta, false, codecPrivate, codecPrivateSize); 1107132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else { 1108132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is detected, but does not have configuration.", 1109132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang codecID); 1110132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang continue; 1111132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } 1112093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcmp("V_VP8", codecID)) { 111394705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8); 111494705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang } else if (!strcmp("V_VP9", codecID)) { 111594705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9); 1116093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else { 1117132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is not supported.", codecID); 1118093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 1119093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1120093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1121093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyWidth, vtrack->GetWidth()); 1122093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyHeight, vtrack->GetHeight()); 1123093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber break; 1124093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1125093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1126093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber case AUDIO_TRACK: 1127093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber { 1128093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::AudioTrack *atrack = 1129093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber static_cast<const mkvparser::AudioTrack *>(track); 1130093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1131093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcmp("A_AAC", codecID)) { 1132093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); 1133093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(codecPrivateSize >= 2); 1134093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1135132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang addESDSFromCodecPrivate( 1136132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta, true, codecPrivate, codecPrivateSize); 1137093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcmp("A_VORBIS", codecID)) { 1138093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 1139093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 11405ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber err = addVorbisCodecInfo( 11415ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber meta, codecPrivate, codecPrivateSize); 1142bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } else if (!strcmp("A_OPUS", codecID)) { 1143bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS); 1144bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize); 1145bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay()); 1146bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll()); 1147bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSeekPreRollNs = track->GetSeekPreRoll(); 1148132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else if (!strcmp("A_MPEG/L3", codecID)) { 1149132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 1150093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else { 1151132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is not supported.", codecID); 1152093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 1153093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1154093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1155093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeySampleRate, atrack->GetSamplingRate()); 1156093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyChannelCount, atrack->GetChannels()); 1157093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber break; 1158093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1159093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1160093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber default: 1161093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 1162093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1163093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 11645ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (err != OK) { 11655ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ALOGE("skipping track, codec specific data was malformed."); 11665ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber continue; 11675ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 11685ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 1169093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long durationNs = mSegment->GetDuration(); 1170093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt64(kKeyDuration, (durationNs + 500) / 1000); 1171093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1172093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mTracks.push(); 11734f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih size_t n = mTracks.size() - 1; 11744f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih TrackInfo *trackInfo = &mTracks.editItemAt(n); 1175093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber trackInfo->mTrackNum = track->GetNumber(); 1176093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber trackInfo->mMeta = meta; 11772f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih trackInfo->mExtractor = this; 1178793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih 1179793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih trackInfo->mEncrypted = false; 1180793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih for(size_t i = 0; i < track->GetContentEncodingCount() && !trackInfo->mEncrypted; i++) { 1181793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih const mkvparser::ContentEncoding *encoding = track->GetContentEncodingByIndex(i); 1182793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih for(size_t j = 0; j < encoding->GetEncryptionCount(); j++) { 1183793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih const mkvparser::ContentEncoding::ContentEncryption *encryption; 1184793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih encryption = encoding->GetEncryptionByIndex(j); 1185793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih meta->setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len); 1186793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih trackInfo->mEncrypted = true; 1187793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih break; 1188793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih } 1189793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih } 11904f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih 11914f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (!strcmp("V_MPEG4/ISO/AVC", codecID) && codecPrivateSize == 0) { 11924f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih // Attempt to recover from AVC track without codec private data 11934f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih err = synthesizeAVCC(trackInfo, n); 11944f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih if (err != OK) { 11954f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih mTracks.pop(); 11964f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 11974f2559d3cdeb7187dedca186d5abc65af4bdb031Robert Shih } 1198093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1199093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 1200093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 12015279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid MatroskaExtractor::findThumbnails() { 12025279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 12035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber TrackInfo *info = &mTracks.editItemAt(i); 12045279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 12055279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const char *mime; 12065279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber CHECK(info->mMeta->findCString(kKeyMIMEType, &mime)); 12075279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 12085279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (strncasecmp(mime, "video/", 6)) { 12095279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber continue; 12105279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 12115279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 12122f46e8152fb881d3a1d7afd223f1ed51f6e358b8Robert Shih BlockIterator iter(this, info->mTrackNum, i); 12134719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer int32_t j = 0; 12145279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t thumbnailTimeUs = 0; 12155279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber size_t maxBlockSize = 0; 12164719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer while (!iter.eos() && j < 20) { 12175279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (iter.block()->IsKey()) { 12184719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer ++j; 12195279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1220d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber size_t blockSize = 0; 1221cba4ed0039c8b8fac01b3193d19fc2364f934506Tareq A. Siraj for (int k = 0; k < iter.block()->GetFrameCount(); ++k) { 1222cba4ed0039c8b8fac01b3193d19fc2364f934506Tareq A. Siraj blockSize += iter.block()->GetFrame(k).len; 1223d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 1224d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 12255279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (blockSize > maxBlockSize) { 12265279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber maxBlockSize = blockSize; 12275279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber thumbnailTimeUs = iter.blockTimeUs(); 12285279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 12295279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 12305279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber iter.advance(); 12315279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 12325279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 12335279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 12345279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 12355279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1236093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaExtractor::getMetaData() { 1237093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MetaData> meta = new MetaData; 12388c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber 12398c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber meta->setCString( 12408c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber kKeyMIMEType, 12418c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA); 1242093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1243093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return meta; 1244093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 1245093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1246d42573cace9db2b5948e540c32beaef80f04153cAndreas Huberuint32_t MatroskaExtractor::flags() const { 1247d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber uint32_t x = CAN_PAUSE; 1248d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (!isLiveStreaming()) { 1249d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK; 1250d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 1251d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 1252d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return x; 1253d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 1254d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 1255093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberbool SniffMatroska( 12565a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 12575a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 1258093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader reader(source); 1259093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::EBMLHeader ebmlHeader; 1260093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long pos; 1261093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ebmlHeader.Parse(&reader, pos) < 0) { 1262093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return false; 1263093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1264093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1265093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA); 1266093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *confidence = 0.6; 1267093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1268093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return true; 1269093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 1270093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1271093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} // namespace android 1272