MatroskaExtractor.cpp revision c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0
1093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber/* 2093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * Copyright (C) 2010 The Android Open Source Project 3093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * 4093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * you may not use this file except in compliance with the License. 6093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * You may obtain a copy of the License at 7093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * 8093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * 10093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * Unless required by applicable law or agreed to in writing, software 11093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * See the License for the specific language governing permissions and 14093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber * limitations under the License. 15093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber */ 16093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 17093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber//#define LOG_NDEBUG 0 18093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#define LOG_TAG "MatroskaExtractor" 19093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <utils/Log.h> 20093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 21093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include "MatroskaExtractor.h" 22093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 23093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include "mkvparser.hpp" 24093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 25b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber#include <media/stagefright/foundation/ADebug.h> 26b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber#include <media/stagefright/foundation/hexdump.h> 27093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/DataSource.h> 28093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaBuffer.h> 29093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaDefs.h> 30093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaErrors.h> 31093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MediaSource.h> 32093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <media/stagefright/MetaData.h> 33b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber#include <media/stagefright/Utils.h> 34093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include <utils/String8.h> 35093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 36b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross#include <inttypes.h> 37b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross 38093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubernamespace android { 39093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 40093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstruct DataSourceReader : public mkvparser::IMkvReader { 41093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader(const sp<DataSource> &source) 42093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mSource(source) { 43093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 44093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 45093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual int Read(long long position, long length, unsigned char* buffer) { 46093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(position >= 0); 47093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(length >= 0); 48093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 49093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (length == 0) { 50093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 51093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 52093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 53093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber ssize_t n = mSource->readAt(position, buffer, length); 54093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 55093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (n <= 0) { 56093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return -1; 57093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 58093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 59093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 60093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 61093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 62093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual int Length(long long* total, long long* available) { 63c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t size; 64093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (mSource->getSize(&size) != OK) { 65d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber *total = -1; 66d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber *available = (long long)((1ull << 63) - 1); 67d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 68d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return 0; 69093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 70093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 71093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (total) { 72093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *total = size; 73093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 74093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 75093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (available) { 76093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *available = size; 77093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 78093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 79093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 80093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 81093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 82093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberprivate: 83093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<DataSource> mSource; 84093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 85093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader(const DataSourceReader &); 86093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader &operator=(const DataSourceReader &); 87093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}; 88093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 89093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber//////////////////////////////////////////////////////////////////////////////// 90093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 915279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberstruct BlockIterator { 92d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum); 935279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 945279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber bool eos() const; 955279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 965279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber void advance(); 975279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber void reset(); 985ec58d925520e6913fba3fc54413881af751c610Andreas Huber 995ec58d925520e6913fba3fc54413881af751c610Andreas Huber void seek( 100f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann int64_t seekTimeUs, bool isAudio, 1015ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t *actualFrameTimeUs); 1025279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::Block *block() const; 1045279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t blockTimeUs() const; 1055279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1065279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberprivate: 107d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber MatroskaExtractor *mExtractor; 108b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross long long mTrackNum; 1095279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 110d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Cluster *mCluster; 1115279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::BlockEntry *mBlockEntry; 112d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long mBlockEntryIndex; 113d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 114d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber void advance_l(); 1155279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1165279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator(const BlockIterator &); 1175279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator &operator=(const BlockIterator &); 1185279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}; 1195279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 120093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstruct MatroskaSource : public MediaSource { 121093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource( 122093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MatroskaExtractor> &extractor, size_t index); 123093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 124093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t start(MetaData *params); 125093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t stop(); 126093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 127093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual sp<MetaData> getFormat(); 128093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 129093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t read( 130093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MediaBuffer **buffer, const ReadOptions *options); 131093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 13250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberprotected: 13350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber virtual ~MatroskaSource(); 13450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 135093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberprivate: 136093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber enum Type { 137093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber AVC, 138093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber AAC, 139093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber OTHER 140093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber }; 141093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 142093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MatroskaExtractor> mExtractor; 143093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t mTrackIndex; 144093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber Type mType; 14574a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber bool mIsAudio; 1465279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator mBlockIter; 147b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber size_t mNALSizeLen; // for type AVC 148093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 14950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber List<MediaBuffer *> mPendingFrames; 15050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 151093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber status_t advance(); 152093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 15350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber status_t readBlock(); 15450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber void clearPendingFrames(); 15550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 156093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource(const MatroskaSource &); 157093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource &operator=(const MatroskaSource &); 158093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}; 159093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 160093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaSource::MatroskaSource( 161093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MatroskaExtractor> &extractor, size_t index) 162093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mExtractor(extractor), 163093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mTrackIndex(index), 164093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType(OTHER), 16574a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber mIsAudio(false), 166d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter(mExtractor.get(), 167b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber mExtractor->mTracks.itemAt(index).mTrackNum), 168b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber mNALSizeLen(0) { 169b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta; 170b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 171093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *mime; 172b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber CHECK(meta->findCString(kKeyMIMEType, &mime)); 173093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 17474a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber mIsAudio = !strncasecmp("audio/", mime, 6); 17574a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 176093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 177093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType = AVC; 178b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 179b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber uint32_t dummy; 180b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber const uint8_t *avcc; 181b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber size_t avccSize; 182b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber CHECK(meta->findData( 183b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)); 184b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 185b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber CHECK_GE(avccSize, 5u); 186b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 187b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber mNALSizeLen = 1 + (avcc[4] & 3); 188b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("mNALSizeLen = %zu", mNALSizeLen); 189093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 190093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType = AAC; 191093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 192093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 193093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 19450c8bea8fba2fcafb14696399028bdbc094dc995Andreas HuberMatroskaSource::~MatroskaSource() { 19550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 19650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 19750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 19884333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MatroskaSource::start(MetaData * /* params */) { 1995279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mBlockIter.reset(); 200093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 201093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 202093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 203093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 204093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstatus_t MatroskaSource::stop() { 20550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 20650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 207093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 208093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 209093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 210093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaSource::getFormat() { 211093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mExtractor->mTracks.itemAt(mTrackIndex).mMeta; 212093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 213093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 2145279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber//////////////////////////////////////////////////////////////////////////////// 2155279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2165279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas HuberBlockIterator::BlockIterator( 217d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber MatroskaExtractor *extractor, unsigned long trackNum) 218d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber : mExtractor(extractor), 2195279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mTrackNum(trackNum), 2205279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mCluster(NULL), 221d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntry(NULL), 222d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex(0) { 2235279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber reset(); 2245279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 2255279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2265279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberbool BlockIterator::eos() const { 2275279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return mCluster == NULL || mCluster->EOS(); 2285279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 2295279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2305279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::advance() { 231d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 232d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 233d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 234d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 235d42573cace9db2b5948e540c32beaef80f04153cAndreas Hubervoid BlockIterator::advance_l() { 236d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber for (;;) { 237d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry); 2383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetEntry returned %ld", res); 239d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 240d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long long pos; 241d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long len; 242d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (res < 0) { 243d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // Need to parse this cluster some more 244d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 245d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL); 246d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 247d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mCluster->Parse(pos, len); 2483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Parse returned %ld", res); 249d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 250d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (res < 0) { 251d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // I/O error 252d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 25329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cluster::Parse returned result %ld", res); 2545279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 255d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = NULL; 2565279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber break; 257093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 2585279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 259d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber continue; 260d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } else if (res == 0) { 261d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // We're done with this cluster 262d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 263d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Cluster *nextCluster; 264d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mExtractor->mSegment->ParseNext( 265d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster, nextCluster, pos, len); 2663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ParseNext returned %ld", res); 267d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 268e467ef084b75b074d0081616080b54212a7024c8Lajos Molnar if (res != 0) { 269e467ef084b75b074d0081616080b54212a7024c8Lajos Molnar // EOF or error 270d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 271d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = NULL; 272d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber break; 273d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 274d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 275d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_EQ(res, 0); 276d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(nextCluster != NULL); 277d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(!nextCluster->EOS()); 278d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 279d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = nextCluster; 280d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 281d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mCluster->Parse(pos, len); 2823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Parse (2) returned %ld", res); 283d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_GE(res, 0); 284d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 285d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex = 0; 286d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber continue; 287093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 288093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 289d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(mBlockEntry != NULL); 290d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(mBlockEntry->GetBlock() != NULL); 291d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber ++mBlockEntryIndex; 292d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 293d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) { 2945279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber break; 295093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 2965279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 2975279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 2985279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2995279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::reset() { 300d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 301093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 302d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = mExtractor->mSegment->GetFirst(); 3032ba7ce928b0fa8917ee202836b0963ca58613453Andreas Huber mBlockEntry = NULL; 304d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex = 0; 305d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 306d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber do { 307d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 308d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } while (!eos() && block()->GetTrackNumber() != mTrackNum); 3095279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 310093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 3115ec58d925520e6913fba3fc54413881af751c610Andreas Hubervoid BlockIterator::seek( 312f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann int64_t seekTimeUs, bool isAudio, 3135ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t *actualFrameTimeUs) { 314d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 315d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 3165ec58d925520e6913fba3fc54413881af751c610Andreas Huber *actualFrameTimeUs = -1ll; 3175ec58d925520e6913fba3fc54413881af751c610Andreas Huber 318bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const int64_t seekTimeNs = seekTimeUs * 1000ll - mExtractor->mSeekPreRollNs; 31910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 32010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mkvparser::Segment* const pSegment = mExtractor->mSegment; 32110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 32210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // Special case the 0 seek to avoid loading Cues when the application 32310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // extraneously seeks to 0 before playing. 32410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (seekTimeNs <= 0) { 325b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("Seek to beginning: %" PRId64, seekTimeUs); 32610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mCluster = pSegment->GetFirst(); 32710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mBlockEntryIndex = 0; 32810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann do { 32910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann advance_l(); 33010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } while (!eos() && block()->GetTrackNumber() != mTrackNum); 33110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 33210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 3335ec58d925520e6913fba3fc54413881af751c610Andreas Huber 334b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("Seeking to: %" PRId64, seekTimeUs); 33510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 33610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // If the Cues have not been located then find them. 33710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::Cues* pCues = pSegment->GetCues(); 33810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::SeekHead* pSH = pSegment->GetSeekHead(); 33910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (!pCues && pSH) { 34010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const size_t count = pSH->GetCount(); 34110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::SeekHead::Entry* pEntry; 34210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGV("No Cues yet"); 34310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 34410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann for (size_t index = 0; index < count; index++) { 34510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pEntry = pSH->GetEntry(index); 34610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 34710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (pEntry->id == 0x0C53BB6B) { // Cues ID 34810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann long len; long long pos; 34910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pSegment->ParseCues(pEntry->pos, pos, len); 35010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pCues = pSegment->GetCues(); 351be7ac3d682729048af27871311808a76c618abdbJohann ALOGV("Cues found"); 35210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann break; 35310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 35410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 35510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 35610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (!pCues) { 35710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGE("No Cues in file"); 35810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 35910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 36010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 36110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann else if (!pSH) { 36210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGE("No SeekHead"); 36310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 36410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 36510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 36610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::CuePoint* pCP; 36710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann while (!pCues->DoneParsing()) { 368be7ac3d682729048af27871311808a76c618abdbJohann pCues->LoadCuePoint(); 36910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pCP = pCues->GetLast(); 370be7ac3d682729048af27871311808a76c618abdbJohann 37110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (pCP->GetTime(pSegment) >= seekTimeNs) { 372be7ac3d682729048af27871311808a76c618abdbJohann ALOGV("Parsed past relevant Cue"); 37310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann break; 37410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 37510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 37610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 377f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // The Cue index is built around video keyframes 37810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mkvparser::Tracks const *pTracks = pSegment->GetTracks(); 37910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::Track *pTrack = NULL; 38010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann for (size_t index = 0; index < pTracks->GetTracksCount(); ++index) { 38110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pTrack = pTracks->GetTrackByIndex(index); 38210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (pTrack && pTrack->GetType() == 1) { // VIDEO_TRACK 383b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("Video track located at %zu", index); 38410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann break; 38510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 38610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 38710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 388f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // Always *search* based on the video track, but finalize based on mTrackNum 38910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::CuePoint::TrackPosition* pTP; 390f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann if (pTrack && pTrack->GetType() == 1) { 39110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pCues->Find(seekTimeNs, pTrack, pCP, pTP); 39210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } else { 393f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann ALOGE("Did not locate the video track for seeking"); 39410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 39510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 39610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 39710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos); 3985279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 399f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK(mCluster); 400f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK(!mCluster->EOS()); 401f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann 402f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // mBlockEntryIndex starts at 0 but m_block starts at 1 403f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK_GT(pTP->m_block, 0); 404f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann mBlockEntryIndex = pTP->m_block - 1; 4055ec58d925520e6913fba3fc54413881af751c610Andreas Huber 4065ec58d925520e6913fba3fc54413881af751c610Andreas Huber for (;;) { 407d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 4085279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 409f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann if (eos()) break; 4105ec58d925520e6913fba3fc54413881af751c610Andreas Huber 411f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann if (isAudio || block()->IsKey()) { 412f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // Accept the first key frame 413f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann *actualFrameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL; 414b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross ALOGV("Requested seek point: %" PRId64 " actual: %" PRId64, 41584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber seekTimeUs, *actualFrameTimeUs); 4165ec58d925520e6913fba3fc54413881af751c610Andreas Huber break; 41774a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber } 4185279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 419093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 420093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 4215279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberconst mkvparser::Block *BlockIterator::block() const { 4225279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber CHECK(!eos()); 4235279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 4245279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return mBlockEntry->GetBlock(); 4255279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 4265279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 4275279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberint64_t BlockIterator::blockTimeUs() const { 4285279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll; 4295279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 4305279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 4315279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber//////////////////////////////////////////////////////////////////////////////// 4325279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 433b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huberstatic unsigned U24_AT(const uint8_t *ptr) { 434b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; 435b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber} 436b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 43750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatic size_t clz(uint8_t x) { 43850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber size_t numLeadingZeroes = 0; 439093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 44050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (!(x & 0x80)) { 44150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber ++numLeadingZeroes; 44250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber x = x << 1; 443093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 444093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 44550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return numLeadingZeroes; 44650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 44750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 44850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Hubervoid MatroskaSource::clearPendingFrames() { 44950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (!mPendingFrames.empty()) { 45050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer *frame = *mPendingFrames.begin(); 45150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.erase(mPendingFrames.begin()); 45250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 45350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber frame->release(); 45450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber frame = NULL; 45550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 45650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 45750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 45850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatus_t MatroskaSource::readBlock() { 45950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber CHECK(mPendingFrames.empty()); 46050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 4615279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (mBlockIter.eos()) { 462093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return ERROR_END_OF_STREAM; 463093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 464093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 4655279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::Block *block = mBlockIter.block(); 46650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 4675279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t timeUs = mBlockIter.blockTimeUs(); 468093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 469d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber for (int i = 0; i < block->GetFrameCount(); ++i) { 470d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Block::Frame &frame = block->GetFrame(i); 471b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 472d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber MediaBuffer *mbuf = new MediaBuffer(frame.len); 473d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mbuf->meta_data()->setInt64(kKeyTime, timeUs); 474d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey()); 475093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 476d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data()); 477d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (n != 0) { 478d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mPendingFrames.clear(); 47950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 480d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter.advance(); 481d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return ERROR_IO; 48250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 48350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 48450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.push_back(mbuf); 48550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 48650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 487d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter.advance(); 48850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 48950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return OK; 49050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 49150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 49250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatus_t MatroskaSource::read( 49350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer **out, const ReadOptions *options) { 49450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = NULL; 49550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 4965ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t targetSampleTimeUs = -1ll; 4975ec58d925520e6913fba3fc54413881af751c610Andreas Huber 49850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber int64_t seekTimeUs; 49950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber ReadOptions::SeekMode mode; 500d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode) 501d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && !mExtractor->isLiveStreaming()) { 50250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 50374a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 504f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // The audio we want is located by using the Cues to seek the video 505f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // stream to find the target Cluster then iterating to finalize for 506f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // audio. 5075ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t actualFrameTimeUs; 508f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs); 5095ec58d925520e6913fba3fc54413881af751c610Andreas Huber 5105ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 5115ec58d925520e6913fba3fc54413881af751c610Andreas Huber targetSampleTimeUs = actualFrameTimeUs; 5125ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 51350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 51450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 51550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (mPendingFrames.empty()) { 51650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber status_t err = readBlock(); 51750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 51850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber if (err != OK) { 51950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 52050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 52150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return err; 52250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 52350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 52450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 52550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer *frame = *mPendingFrames.begin(); 52650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.erase(mPendingFrames.begin()); 52750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 52850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber if (mType != AVC) { 5295ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (targetSampleTimeUs >= 0ll) { 5305ec58d925520e6913fba3fc54413881af751c610Andreas Huber frame->meta_data()->setInt64( 5315ec58d925520e6913fba3fc54413881af751c610Andreas Huber kKeyTargetTime, targetSampleTimeUs); 5325ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 5335ec58d925520e6913fba3fc54413881af751c610Andreas Huber 53450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = frame; 53550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 53650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return OK; 53750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 53850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 539792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // Each input frame contains one or more NAL fragments, each fragment 540792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // is prefixed by mNALSizeLen bytes giving the fragment length, 541792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // followed by a corresponding number of bytes containing the fragment. 542792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // We output all these fragments into a single large buffer separated 543792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // by startcodes (0x00 0x00 0x00 0x01). 544792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 545792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber const uint8_t *srcPtr = 546792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber (const uint8_t *)frame->data() + frame->range_offset(); 547792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 548792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t srcSize = frame->range_length(); 549792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 550792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t dstSize = 0; 551792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber MediaBuffer *buffer = NULL; 552792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber uint8_t *dstPtr = NULL; 553792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 554792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber for (int32_t pass = 0; pass < 2; ++pass) { 555792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t srcOffset = 0; 556792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t dstOffset = 0; 557792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber while (srcOffset + mNALSizeLen <= srcSize) { 558792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t NALsize; 559792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber switch (mNALSizeLen) { 560792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 1: NALsize = srcPtr[srcOffset]; break; 561792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 2: NALsize = U16_AT(srcPtr + srcOffset); break; 562792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 3: NALsize = U24_AT(srcPtr + srcOffset); break; 563792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 4: NALsize = U32_AT(srcPtr + srcOffset); break; 564792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber default: 565792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber TRESPASS(); 566792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 56750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 568792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (srcOffset + mNALSizeLen + NALsize > srcSize) { 569792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber break; 570792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 57150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 572792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (pass == 1) { 573792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4); 57450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 575792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber memcpy(&dstPtr[dstOffset + 4], 576792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber &srcPtr[srcOffset + mNALSizeLen], 577792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber NALsize); 578792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 57950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 580792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstOffset += 4; // 0x00 00 00 01 581792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstOffset += NALsize; 58250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 583792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber srcOffset += mNALSizeLen + NALsize; 584792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 58550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 586792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (srcOffset < srcSize) { 587792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // There were trailing bytes or not enough data to complete 588792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // a fragment. 58950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 590792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame->release(); 591792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame = NULL; 59250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 593792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber return ERROR_MALFORMED; 594792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 59550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 596792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (pass == 0) { 597792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstSize = dstOffset; 59850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 599792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer = new MediaBuffer(dstSize); 60050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 601792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber int64_t timeUs; 602792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs)); 603792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber int32_t isSync; 604792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)); 60550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 606792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 607792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync); 60850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 609792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstPtr = (uint8_t *)buffer->data(); 610792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 61150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 61250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 613792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame->release(); 614792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame = NULL; 61550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 6165ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (targetSampleTimeUs >= 0ll) { 6175ec58d925520e6913fba3fc54413881af751c610Andreas Huber buffer->meta_data()->setInt64( 6185ec58d925520e6913fba3fc54413881af751c610Andreas Huber kKeyTargetTime, targetSampleTimeUs); 6195ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 6205ec58d925520e6913fba3fc54413881af751c610Andreas Huber 62150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = buffer; 622093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 623093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 624093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 625093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 626093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber//////////////////////////////////////////////////////////////////////////////// 627093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 628093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source) 629093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mDataSource(source), 630093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mReader(new DataSourceReader(mDataSource)), 6315279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mSegment(NULL), 6328c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mExtractedThumbnails(false), 633bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mIsWebm(false), 634bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSeekPreRollNs(0) { 635d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber off64_t size; 636d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mIsLiveStreaming = 637d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber (mDataSource->flags() 638d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber & (DataSource::kWantsPrefetching 639d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber | DataSource::kIsCachingDataSource)) 640d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && mDataSource->getSize(&size) != OK; 641d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 642093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::EBMLHeader ebmlHeader; 643093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long pos; 644093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ebmlHeader.Parse(mReader, pos) < 0) { 645093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 646093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 647093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 6488c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) { 6498c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mIsWebm = true; 6508c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber } 6518c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber 652093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long ret = 653093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::Segment::CreateInstance(mReader, pos, mSegment); 654093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 655093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ret) { 656093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(mSegment == NULL); 657093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 658093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 659093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 660c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar // from mkvparser::Segment::Load(), but stop at first cluster 66110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ret = mSegment->ParseHeaders(); 662c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar if (ret == 0) { 663c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar long len; 664c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ret = mSegment->LoadCluster(pos, len); 665c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar if (ret >= 1) { 666c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar // no more clusters 667c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ret = 0; 668c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar } 669c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar } else if (ret > 0) { 670c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ret = mkvparser::E_BUFFER_NOT_FULL; 671c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar } 672093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 673093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ret < 0) { 674c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar ALOGW("Corrupt %s source: %s", mIsWebm ? "webm" : "matroska", 675c51db0a6bfb71ea9c934fb7971cb5ae1f1cf03a0Lajos Molnar uriDebugString(mDataSource->getUri()).c_str()); 676093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mSegment; 677093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mSegment = NULL; 678093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 679093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 680093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 68174a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber#if 0 68274a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber const mkvparser::SegmentInfo *info = mSegment->GetInfo(); 683df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("muxing app: %s, writing app: %s", 68474a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber info->GetMuxingAppAsUTF8(), 68574a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber info->GetWritingAppAsUTF8()); 68674a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber#endif 68774a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 688093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber addTracks(); 689093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 690093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 691093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::~MatroskaExtractor() { 692093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mSegment; 693093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mSegment = NULL; 694093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 695093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mReader; 696093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mReader = NULL; 697093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 698093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 699093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersize_t MatroskaExtractor::countTracks() { 700093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mTracks.size(); 701093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 702093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 703093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MediaSource> MatroskaExtractor::getTrack(size_t index) { 704093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (index >= mTracks.size()) { 705093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return NULL; 706093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 707093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 708093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return new MatroskaSource(this, index); 709093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 710093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 711093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaExtractor::getTrackMetaData( 712093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t index, uint32_t flags) { 713093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (index >= mTracks.size()) { 714093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return NULL; 715093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 716093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 717d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails 718d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && !isLiveStreaming()) { 7195279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber findThumbnails(); 7205279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mExtractedThumbnails = true; 7215279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 7225279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 723093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mTracks.itemAt(index).mMeta; 724093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 725093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 726d42573cace9db2b5948e540c32beaef80f04153cAndreas Huberbool MatroskaExtractor::isLiveStreaming() const { 727d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return mIsLiveStreaming; 728d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 729d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 730403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissenstatic int bytesForSize(size_t size) { 731403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen // use at most 28 bits (4 times 7) 732403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen CHECK(size <= 0xfffffff); 733403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 734403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen if (size > 0x1fffff) { 735403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 4; 736403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } else if (size > 0x3fff) { 737403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 3; 738403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } else if (size > 0x7f) { 739403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 2; 740403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } 741403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen return 1; 742403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen} 743403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 744403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissenstatic void storeSize(uint8_t *data, size_t &idx, size_t size) { 745403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int numBytes = bytesForSize(size); 746403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen idx += numBytes; 747403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 748403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen data += idx; 749403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size_t next = 0; 750403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen while (numBytes--) { 751403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen *--data = (size & 0x7f) | next; 752403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size >>= 7; 753403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen next = 0x80; 754403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } 755403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen} 756403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 757132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kangstatic void addESDSFromCodecPrivate( 758132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang const sp<MetaData> &meta, 759132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang bool isAudio, const void *priv, size_t privSize) { 760093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 761403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int privSizeBytesRequired = bytesForSize(privSize); 762403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize2 = 14 + privSizeBytesRequired + privSize; 763403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize2BytesRequired = bytesForSize(esdsSize2); 764403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2; 765403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen int esdsSize1BytesRequired = bytesForSize(esdsSize1); 766403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1; 767093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber uint8_t *esds = new uint8_t[esdsSize]; 768403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen 769403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen size_t idx = 0; 770403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x03; 771403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen storeSize(esds, idx, esdsSize1); 772403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; // ES_ID 773403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; // ES_ID 774403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag 775403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x04; 776403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen storeSize(esds, idx, esdsSize2); 777403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = isAudio ? 0x40 // Audio ISO/IEC 14496-3 778403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen : 0x20; // Visual ISO/IEC 14496-2 779403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen for (int i = 0; i < 12; i++) { 780403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x00; 781403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen } 782403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen esds[idx++] = 0x05; 783403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen storeSize(esds, idx, privSize); 784403484d6d76ede31fc71c88495b69108a4df8319Marco Nelissen memcpy(esds + idx, priv, privSize); 78582ac8bf2da940c4439786c346f739f4a496864adAndreas Huber 786093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData(kKeyESDS, 0, esds, esdsSize); 787093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 788093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete[] esds; 789093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber esds = NULL; 790093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 791093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 7925ce181568da90c78ba7fad3e084c8479041545dfAndreas Huberstatus_t addVorbisCodecInfo( 793093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MetaData> &meta, 794093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const void *_codecPrivate, size_t codecPrivateSize) { 795093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber // hexdump(_codecPrivate, codecPrivateSize); 796093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 7975ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivateSize < 1) { 7985ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 7995ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 800093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 801093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate; 802093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8035ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[0] != 0x02) { 8045ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 8055ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 806093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8075ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber // codecInfo starts with two lengths, len1 and len2, that are 8085ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber // "Xiph-style-lacing encoded"... 809093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8105ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t offset = 1; 8115ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t len1 = 0; 8125ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 8135ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len1 += 0xff; 8145ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ++offset; 8155ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 8165ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (offset >= codecPrivateSize) { 8175ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 8185ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 8195ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len1 += codecPrivate[offset++]; 820093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8215ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t len2 = 0; 8225ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 8235ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len2 += 0xff; 8245ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ++offset; 8255ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 8265ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (offset >= codecPrivateSize) { 8275ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 8285ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 8295ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len2 += codecPrivate[offset++]; 8305ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 8315ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivateSize < offset + len1 + len2) { 8325ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 8335ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 8345ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 8355ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x01) { 8365ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 8375ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 8385ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1); 8395ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 8405ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber offset += len1; 8415ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x03) { 8425ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 8435ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 8445ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 8455ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber offset += len2; 8465ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x05) { 8475ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 8485ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 849093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 850093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData( 8515ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber kKeyVorbisBooks, 0, &codecPrivate[offset], 8525ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber codecPrivateSize - offset); 8535ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 8545ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return OK; 855093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 856093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 857093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubervoid MatroskaExtractor::addTracks() { 858093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::Tracks *tracks = mSegment->GetTracks(); 859093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 860093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber for (size_t index = 0; index < tracks->GetTracksCount(); ++index) { 861093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::Track *track = tracks->GetTrackByIndex(index); 862093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 86330ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber if (track == NULL) { 86430ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber // Apparently this is currently valid (if unexpected) behaviour 86530ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber // of the mkv parser lib. 86630ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber continue; 86730ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber } 86830ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber 869093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *const codecID = track->GetCodecId(); 8703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("codec id = %s", codecID); 8713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("codec name = %s", track->GetCodecNameAsUTF8()); 872093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 873093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t codecPrivateSize; 874093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const unsigned char *codecPrivate = 875ff1df9951d09f1a1a8ae2dbc42b82b0f9c164e5eAndreas Huber track->GetCodecPrivate(codecPrivateSize); 876093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 877093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 }; 878093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 879093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MetaData> meta = new MetaData; 880093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8815ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber status_t err = OK; 8825ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 883093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber switch (track->GetType()) { 884093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber case VIDEO_TRACK: 885093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber { 886093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::VideoTrack *vtrack = 887093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber static_cast<const mkvparser::VideoTrack *>(track); 888093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 889093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { 890093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 891093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); 892132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) { 893132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang if (codecPrivateSize > 0) { 894132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta->setCString( 895132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 896132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang addESDSFromCodecPrivate( 897132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta, false, codecPrivate, codecPrivateSize); 898132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else { 899132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is detected, but does not have configuration.", 900132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang codecID); 901132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang continue; 902132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } 903093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcmp("V_VP8", codecID)) { 90494705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8); 90594705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang } else if (!strcmp("V_VP9", codecID)) { 90694705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9); 907093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else { 908132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is not supported.", codecID); 909093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 910093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 911093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 912093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyWidth, vtrack->GetWidth()); 913093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyHeight, vtrack->GetHeight()); 914093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber break; 915093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 916093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 917093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber case AUDIO_TRACK: 918093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber { 919093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::AudioTrack *atrack = 920093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber static_cast<const mkvparser::AudioTrack *>(track); 921093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 922093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcmp("A_AAC", codecID)) { 923093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); 924093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(codecPrivateSize >= 2); 925093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 926132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang addESDSFromCodecPrivate( 927132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta, true, codecPrivate, codecPrivateSize); 928093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcmp("A_VORBIS", codecID)) { 929093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 930093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9315ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber err = addVorbisCodecInfo( 9325ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber meta, codecPrivate, codecPrivateSize); 933bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } else if (!strcmp("A_OPUS", codecID)) { 934bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS); 935bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize); 936bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay()); 937bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll()); 938bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSeekPreRollNs = track->GetSeekPreRoll(); 939132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else if (!strcmp("A_MPEG/L3", codecID)) { 940132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 941093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else { 942132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is not supported.", codecID); 943093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 944093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 945093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 946093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeySampleRate, atrack->GetSamplingRate()); 947093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyChannelCount, atrack->GetChannels()); 948093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber break; 949093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 950093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 951093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber default: 952093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 953093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 954093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9555ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (err != OK) { 9565ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ALOGE("skipping track, codec specific data was malformed."); 9575ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber continue; 9585ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 9595ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 960093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long durationNs = mSegment->GetDuration(); 961093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt64(kKeyDuration, (durationNs + 500) / 1000); 962093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 963093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mTracks.push(); 964093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1); 965093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber trackInfo->mTrackNum = track->GetNumber(); 966093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber trackInfo->mMeta = meta; 967093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 968093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 969093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9705279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid MatroskaExtractor::findThumbnails() { 9715279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 9725279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber TrackInfo *info = &mTracks.editItemAt(i); 9735279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 9745279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const char *mime; 9755279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber CHECK(info->mMeta->findCString(kKeyMIMEType, &mime)); 9765279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 9775279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (strncasecmp(mime, "video/", 6)) { 9785279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber continue; 9795279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 9805279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 981d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber BlockIterator iter(this, info->mTrackNum); 9824719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer int32_t j = 0; 9835279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t thumbnailTimeUs = 0; 9845279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber size_t maxBlockSize = 0; 9854719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer while (!iter.eos() && j < 20) { 9865279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (iter.block()->IsKey()) { 9874719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer ++j; 9885279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 989d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber size_t blockSize = 0; 990cba4ed0039c8b8fac01b3193d19fc2364f934506Tareq A. Siraj for (int k = 0; k < iter.block()->GetFrameCount(); ++k) { 991cba4ed0039c8b8fac01b3193d19fc2364f934506Tareq A. Siraj blockSize += iter.block()->GetFrame(k).len; 992d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 993d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 9945279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (blockSize > maxBlockSize) { 9955279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber maxBlockSize = blockSize; 9965279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber thumbnailTimeUs = iter.blockTimeUs(); 9975279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 9985279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 9995279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber iter.advance(); 10005279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 10015279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 10025279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 10035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 10045279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1005093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaExtractor::getMetaData() { 1006093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MetaData> meta = new MetaData; 10078c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber 10088c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber meta->setCString( 10098c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber kKeyMIMEType, 10108c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA); 1011093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1012093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return meta; 1013093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 1014093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1015d42573cace9db2b5948e540c32beaef80f04153cAndreas Huberuint32_t MatroskaExtractor::flags() const { 1016d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber uint32_t x = CAN_PAUSE; 1017d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (!isLiveStreaming()) { 1018d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK; 1019d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 1020d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 1021d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return x; 1022d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 1023d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 1024093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberbool SniffMatroska( 10255a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 10265a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 1027093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader reader(source); 1028093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::EBMLHeader ebmlHeader; 1029093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long pos; 1030093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ebmlHeader.Parse(&reader, pos) < 0) { 1031093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return false; 1032093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 1033093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1034093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA); 1035093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *confidence = 0.6; 1036093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1037093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return true; 1038093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 1039093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1040093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} // namespace android 1041