MatroskaExtractor.cpp revision be7ac3d682729048af27871311808a76c618abdb
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 36093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubernamespace android { 37093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 38093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstruct DataSourceReader : public mkvparser::IMkvReader { 39093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader(const sp<DataSource> &source) 40093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mSource(source) { 41093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 42093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 43093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual int Read(long long position, long length, unsigned char* buffer) { 44093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(position >= 0); 45093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(length >= 0); 46093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 47093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (length == 0) { 48093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 49093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 50093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 51093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber ssize_t n = mSource->readAt(position, buffer, length); 52093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 53093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (n <= 0) { 54093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return -1; 55093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 56093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 57093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 58093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 59093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 60093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual int Length(long long* total, long long* available) { 61c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t size; 62093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (mSource->getSize(&size) != OK) { 63d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber *total = -1; 64d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber *available = (long long)((1ull << 63) - 1); 65d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 66d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return 0; 67093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 68093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 69093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (total) { 70093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *total = size; 71093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 72093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 73093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (available) { 74093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *available = size; 75093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 76093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 77093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return 0; 78093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 79093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 80093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberprivate: 81093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<DataSource> mSource; 82093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 83093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader(const DataSourceReader &); 84093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader &operator=(const DataSourceReader &); 85093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}; 86093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 87093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber//////////////////////////////////////////////////////////////////////////////// 88093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 895279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberstruct BlockIterator { 90d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum); 915279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 925279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber bool eos() const; 935279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 945279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber void advance(); 955279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber void reset(); 965ec58d925520e6913fba3fc54413881af751c610Andreas Huber 975ec58d925520e6913fba3fc54413881af751c610Andreas Huber void seek( 985ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t seekTimeUs, bool seekToKeyFrame, 995ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t *actualFrameTimeUs); 1005279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1015279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::Block *block() const; 1025279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t blockTimeUs() const; 1035279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1045279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberprivate: 105d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber MatroskaExtractor *mExtractor; 1065279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber unsigned long mTrackNum; 1075279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 108d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Cluster *mCluster; 1095279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::BlockEntry *mBlockEntry; 110d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long mBlockEntryIndex; 111d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 112d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber void advance_l(); 1135279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 1145279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator(const BlockIterator &); 1155279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator &operator=(const BlockIterator &); 1165279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber}; 1175279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 118093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstruct MatroskaSource : public MediaSource { 119093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource( 120093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MatroskaExtractor> &extractor, size_t index); 121093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 122093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t start(MetaData *params); 123093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t stop(); 124093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 125093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual sp<MetaData> getFormat(); 126093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 127093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber virtual status_t read( 128093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MediaBuffer **buffer, const ReadOptions *options); 129093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 13050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberprotected: 13150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber virtual ~MatroskaSource(); 13250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 133093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberprivate: 134093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber enum Type { 135093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber AVC, 136093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber AAC, 137093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber OTHER 138093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber }; 139093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 140093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MatroskaExtractor> mExtractor; 141093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t mTrackIndex; 142093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber Type mType; 14374a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber bool mIsAudio; 1445279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber BlockIterator mBlockIter; 145b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber size_t mNALSizeLen; // for type AVC 146093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 14750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber List<MediaBuffer *> mPendingFrames; 14850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 149093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber status_t advance(); 150093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 15150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber status_t readBlock(); 15250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber void clearPendingFrames(); 15350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 154093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource(const MatroskaSource &); 155093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber MatroskaSource &operator=(const MatroskaSource &); 156093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber}; 157093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 158093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaSource::MatroskaSource( 159093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MatroskaExtractor> &extractor, size_t index) 160093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mExtractor(extractor), 161093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mTrackIndex(index), 162093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType(OTHER), 16374a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber mIsAudio(false), 164d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter(mExtractor.get(), 165b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber mExtractor->mTracks.itemAt(index).mTrackNum), 166b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber mNALSizeLen(0) { 167b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta; 168b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 169093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *mime; 170b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber CHECK(meta->findCString(kKeyMIMEType, &mime)); 171093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 17274a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber mIsAudio = !strncasecmp("audio/", mime, 6); 17374a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 174093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 175093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType = AVC; 176b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 177b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber uint32_t dummy; 178b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber const uint8_t *avcc; 179b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber size_t avccSize; 180b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber CHECK(meta->findData( 181b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)); 182b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 183b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber CHECK_GE(avccSize, 5u); 184b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 185b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber mNALSizeLen = 1 + (avcc[4] & 3); 1863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("mNALSizeLen = %d", mNALSizeLen); 187093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 188093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mType = AAC; 189093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 190093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 191093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 19250c8bea8fba2fcafb14696399028bdbc094dc995Andreas HuberMatroskaSource::~MatroskaSource() { 19350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 19450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 19550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 196093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstatus_t MatroskaSource::start(MetaData *params) { 1975279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mBlockIter.reset(); 198093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 199093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 200093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 201093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 202093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberstatus_t MatroskaSource::stop() { 20350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 20450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 205093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 206093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 207093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 208093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaSource::getFormat() { 209093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mExtractor->mTracks.itemAt(mTrackIndex).mMeta; 210093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 211093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 2125279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber//////////////////////////////////////////////////////////////////////////////// 2135279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2145279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas HuberBlockIterator::BlockIterator( 215d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber MatroskaExtractor *extractor, unsigned long trackNum) 216d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber : mExtractor(extractor), 2175279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mTrackNum(trackNum), 2185279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mCluster(NULL), 219d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntry(NULL), 220d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex(0) { 2215279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber reset(); 2225279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 2235279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2245279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberbool BlockIterator::eos() const { 2255279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return mCluster == NULL || mCluster->EOS(); 2265279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 2275279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2285279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::advance() { 229d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 230d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 231d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 232d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 233d42573cace9db2b5948e540c32beaef80f04153cAndreas Hubervoid BlockIterator::advance_l() { 234d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber for (;;) { 235d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry); 2363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetEntry returned %ld", res); 237d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 238d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long long pos; 239d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long len; 240d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (res < 0) { 241d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // Need to parse this cluster some more 242d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 243d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL); 244d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 245d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mCluster->Parse(pos, len); 2463856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Parse returned %ld", res); 247d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 248d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (res < 0) { 249d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // I/O error 250d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 25129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Cluster::Parse returned result %ld", res); 2525279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 253d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = NULL; 2545279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber break; 255093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 2565279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 257d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber continue; 258d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } else if (res == 0) { 259d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // We're done with this cluster 260d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 261d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Cluster *nextCluster; 262d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mExtractor->mSegment->ParseNext( 263d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster, nextCluster, pos, len); 2643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ParseNext returned %ld", res); 265d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 266d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (res > 0) { 267d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber // EOF 268d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 269d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = NULL; 270d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber break; 271d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 272d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 273d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_EQ(res, 0); 274d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(nextCluster != NULL); 275d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(!nextCluster->EOS()); 276d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 277d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = nextCluster; 278d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 279d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber res = mCluster->Parse(pos, len); 2803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Parse (2) returned %ld", res); 281d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK_GE(res, 0); 282d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 283d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex = 0; 284d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber continue; 285093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 286093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 287d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(mBlockEntry != NULL); 288d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber CHECK(mBlockEntry->GetBlock() != NULL); 289d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber ++mBlockEntryIndex; 290d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 291d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) { 2925279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber break; 293093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 2945279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 2955279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 2965279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 2975279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid BlockIterator::reset() { 298d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 299093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 300d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mCluster = mExtractor->mSegment->GetFirst(); 3012ba7ce928b0fa8917ee202836b0963ca58613453Andreas Huber mBlockEntry = NULL; 302d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockEntryIndex = 0; 303d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 304d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber do { 305d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 306d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } while (!eos() && block()->GetTrackNumber() != mTrackNum); 3075279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 308093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 3095ec58d925520e6913fba3fc54413881af751c610Andreas Hubervoid BlockIterator::seek( 3105ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t seekTimeUs, bool seekToKeyFrame, 3115ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t *actualFrameTimeUs) { 312d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber Mutex::Autolock autoLock(mExtractor->mLock); 313d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 3145ec58d925520e6913fba3fc54413881af751c610Andreas Huber *actualFrameTimeUs = -1ll; 3155ec58d925520e6913fba3fc54413881af751c610Andreas Huber 31610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const int64_t seekTimeNs = seekTimeUs * 1000ll; 31710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 31810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mkvparser::Segment* const pSegment = mExtractor->mSegment; 31910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 32010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // Special case the 0 seek to avoid loading Cues when the application 32110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // extraneously seeks to 0 before playing. 32210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (seekTimeNs <= 0) { 32310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGV("Seek to beginning: %lld", seekTimeUs); 32410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mCluster = pSegment->GetFirst(); 32510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mBlockEntryIndex = 0; 32610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann do { 32710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann advance_l(); 32810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } while (!eos() && block()->GetTrackNumber() != mTrackNum); 32910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 33010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 3315ec58d925520e6913fba3fc54413881af751c610Andreas Huber 33210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGV("Seeking to: %lld", seekTimeUs); 33310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 33410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // If the Cues have not been located then find them. 33510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::Cues* pCues = pSegment->GetCues(); 33610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::SeekHead* pSH = pSegment->GetSeekHead(); 33710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (!pCues && pSH) { 33810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const size_t count = pSH->GetCount(); 33910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::SeekHead::Entry* pEntry; 34010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGV("No Cues yet"); 34110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 34210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann for (size_t index = 0; index < count; index++) { 34310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pEntry = pSH->GetEntry(index); 34410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 34510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (pEntry->id == 0x0C53BB6B) { // Cues ID 34610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann long len; long long pos; 34710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pSegment->ParseCues(pEntry->pos, pos, len); 34810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pCues = pSegment->GetCues(); 349be7ac3d682729048af27871311808a76c618abdbJohann ALOGV("Cues found"); 35010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann break; 35110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 35210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 35310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 35410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (!pCues) { 35510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGE("No Cues in file"); 35610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 35710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 35810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 35910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann else if (!pSH) { 36010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGE("No SeekHead"); 36110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 36210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 36310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 36410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::CuePoint* pCP; 36510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann while (!pCues->DoneParsing()) { 366be7ac3d682729048af27871311808a76c618abdbJohann pCues->LoadCuePoint(); 36710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pCP = pCues->GetLast(); 368be7ac3d682729048af27871311808a76c618abdbJohann 36910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (pCP->GetTime(pSegment) >= seekTimeNs) { 370be7ac3d682729048af27871311808a76c618abdbJohann ALOGV("Parsed past relevant Cue"); 37110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann break; 37210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 37310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 37410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 37510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // Find the video track for seeking. It doesn't make sense to search the 37610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // audio track because we'd still want to make sure we're jumping to a 37710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // keyframe in the video track. 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 38310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGV("Video track located at %d", index); 38410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann break; 38510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 38610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 38710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 38810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::CuePoint::TrackPosition* pTP; 38910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (pTrack) { 39010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pCues->Find(seekTimeNs, pTrack, pCP, pTP); 39110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } else { 39210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGE("Did not locate a VIDEO_TRACK"); 39310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 39410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 39510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 39610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos); 39710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (pTP->m_block > 0) { 39810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann // m_block starts at 1, but mBlockEntryIndex is expected to start at 0 39910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mBlockEntryIndex = pTP->m_block - 1; 40010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } else { 40110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGE("m_block must be > 0"); 40210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 40310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 4045279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 4055ec58d925520e6913fba3fc54413881af751c610Andreas Huber long prevKeyFrameBlockEntryIndex = -1; 4065ec58d925520e6913fba3fc54413881af751c610Andreas Huber 4075ec58d925520e6913fba3fc54413881af751c610Andreas Huber for (;;) { 408d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 4095279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 4105ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (eos()) { 4115ec58d925520e6913fba3fc54413881af751c610Andreas Huber break; 4125ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 4135ec58d925520e6913fba3fc54413881af751c610Andreas Huber 4145ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (block()->GetTrackNumber() != mTrackNum) { 4155ec58d925520e6913fba3fc54413881af751c610Andreas Huber continue; 4165ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 4175ec58d925520e6913fba3fc54413881af751c610Andreas Huber 4185ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (block()->IsKey()) { 4195ec58d925520e6913fba3fc54413881af751c610Andreas Huber prevKeyFrameBlockEntryIndex = mBlockEntryIndex - 1; 4205ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 4215ec58d925520e6913fba3fc54413881af751c610Andreas Huber 4225ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t timeNs = block()->GetTime(mCluster); 4235ec58d925520e6913fba3fc54413881af751c610Andreas Huber 4245ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (timeNs >= seekTimeNs) { 4255ec58d925520e6913fba3fc54413881af751c610Andreas Huber *actualFrameTimeUs = (timeNs + 500ll) / 1000ll; 4265ec58d925520e6913fba3fc54413881af751c610Andreas Huber break; 42774a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber } 4285279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 4295ec58d925520e6913fba3fc54413881af751c610Andreas Huber 4305ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (eos()) { 4315ec58d925520e6913fba3fc54413881af751c610Andreas Huber return; 4325ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 4335ec58d925520e6913fba3fc54413881af751c610Andreas Huber 4345ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (seekToKeyFrame && !block()->IsKey()) { 4355ec58d925520e6913fba3fc54413881af751c610Andreas Huber CHECK_GE(prevKeyFrameBlockEntryIndex, 0); 4365ec58d925520e6913fba3fc54413881af751c610Andreas Huber mBlockEntryIndex = prevKeyFrameBlockEntryIndex; 4375ec58d925520e6913fba3fc54413881af751c610Andreas Huber advance_l(); 4385ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 439093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 440093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 4415279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberconst mkvparser::Block *BlockIterator::block() const { 4425279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber CHECK(!eos()); 4435279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 4445279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return mBlockEntry->GetBlock(); 4455279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 4465279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 4475279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberint64_t BlockIterator::blockTimeUs() const { 4485279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll; 4495279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 4505279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 4515279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber//////////////////////////////////////////////////////////////////////////////// 4525279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 453b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huberstatic unsigned U24_AT(const uint8_t *ptr) { 454b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; 455b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber} 456b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 45750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatic size_t clz(uint8_t x) { 45850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber size_t numLeadingZeroes = 0; 459093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 46050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (!(x & 0x80)) { 46150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber ++numLeadingZeroes; 46250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber x = x << 1; 463093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 464093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 46550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return numLeadingZeroes; 46650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 46750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 46850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Hubervoid MatroskaSource::clearPendingFrames() { 46950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (!mPendingFrames.empty()) { 47050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer *frame = *mPendingFrames.begin(); 47150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.erase(mPendingFrames.begin()); 47250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 47350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber frame->release(); 47450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber frame = NULL; 47550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 47650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 47750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 47850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatus_t MatroskaSource::readBlock() { 47950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber CHECK(mPendingFrames.empty()); 48050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 4815279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (mBlockIter.eos()) { 482093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return ERROR_END_OF_STREAM; 483093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 484093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 4855279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::Block *block = mBlockIter.block(); 48650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 4875279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t timeUs = mBlockIter.blockTimeUs(); 488093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 489d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber for (int i = 0; i < block->GetFrameCount(); ++i) { 490d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Block::Frame &frame = block->GetFrame(i); 491b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 492d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber MediaBuffer *mbuf = new MediaBuffer(frame.len); 493d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mbuf->meta_data()->setInt64(kKeyTime, timeUs); 494d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey()); 495093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 496d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data()); 497d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (n != 0) { 498d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mPendingFrames.clear(); 49950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 500d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter.advance(); 501d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return ERROR_IO; 50250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 50350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 50450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.push_back(mbuf); 50550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 50650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 507d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter.advance(); 50850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 50950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return OK; 51050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 51150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 51250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatus_t MatroskaSource::read( 51350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer **out, const ReadOptions *options) { 51450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = NULL; 51550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 5165ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t targetSampleTimeUs = -1ll; 5175ec58d925520e6913fba3fc54413881af751c610Andreas Huber 51850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber int64_t seekTimeUs; 51950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber ReadOptions::SeekMode mode; 520d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode) 521d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && !mExtractor->isLiveStreaming()) { 52250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 52374a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 52474a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber // Apparently keyframe indication in audio tracks is unreliable, 52574a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber // fortunately in all our currently supported audio encodings every 52674a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber // frame is effectively a keyframe. 5275ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t actualFrameTimeUs; 5285ec58d925520e6913fba3fc54413881af751c610Andreas Huber mBlockIter.seek(seekTimeUs, !mIsAudio, &actualFrameTimeUs); 5295ec58d925520e6913fba3fc54413881af751c610Andreas Huber 5305ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 5315ec58d925520e6913fba3fc54413881af751c610Andreas Huber targetSampleTimeUs = actualFrameTimeUs; 5325ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 53350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 53450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 53550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (mPendingFrames.empty()) { 53650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber status_t err = readBlock(); 53750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 53850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber if (err != OK) { 53950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 54050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 54150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return err; 54250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 54350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 54450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 54550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer *frame = *mPendingFrames.begin(); 54650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.erase(mPendingFrames.begin()); 54750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 54850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber if (mType != AVC) { 5495ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (targetSampleTimeUs >= 0ll) { 5505ec58d925520e6913fba3fc54413881af751c610Andreas Huber frame->meta_data()->setInt64( 5515ec58d925520e6913fba3fc54413881af751c610Andreas Huber kKeyTargetTime, targetSampleTimeUs); 5525ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 5535ec58d925520e6913fba3fc54413881af751c610Andreas Huber 55450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = frame; 55550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 55650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return OK; 55750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 55850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 559792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // Each input frame contains one or more NAL fragments, each fragment 560792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // is prefixed by mNALSizeLen bytes giving the fragment length, 561792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // followed by a corresponding number of bytes containing the fragment. 562792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // We output all these fragments into a single large buffer separated 563792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // by startcodes (0x00 0x00 0x00 0x01). 564792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 565792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber const uint8_t *srcPtr = 566792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber (const uint8_t *)frame->data() + frame->range_offset(); 567792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 568792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t srcSize = frame->range_length(); 569792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 570792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t dstSize = 0; 571792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber MediaBuffer *buffer = NULL; 572792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber uint8_t *dstPtr = NULL; 573792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 574792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber for (int32_t pass = 0; pass < 2; ++pass) { 575792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t srcOffset = 0; 576792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t dstOffset = 0; 577792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber while (srcOffset + mNALSizeLen <= srcSize) { 578792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t NALsize; 579792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber switch (mNALSizeLen) { 580792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 1: NALsize = srcPtr[srcOffset]; break; 581792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 2: NALsize = U16_AT(srcPtr + srcOffset); break; 582792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 3: NALsize = U24_AT(srcPtr + srcOffset); break; 583792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 4: NALsize = U32_AT(srcPtr + srcOffset); break; 584792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber default: 585792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber TRESPASS(); 586792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 58750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 588792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (srcOffset + mNALSizeLen + NALsize > srcSize) { 589792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber break; 590792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 59150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 592792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (pass == 1) { 593792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4); 59450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 595792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber memcpy(&dstPtr[dstOffset + 4], 596792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber &srcPtr[srcOffset + mNALSizeLen], 597792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber NALsize); 598792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 59950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 600792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstOffset += 4; // 0x00 00 00 01 601792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstOffset += NALsize; 60250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 603792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber srcOffset += mNALSizeLen + NALsize; 604792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 60550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 606792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (srcOffset < srcSize) { 607792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // There were trailing bytes or not enough data to complete 608792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // a fragment. 60950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 610792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame->release(); 611792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame = NULL; 61250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 613792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber return ERROR_MALFORMED; 614792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 61550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 616792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (pass == 0) { 617792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstSize = dstOffset; 61850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 619792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer = new MediaBuffer(dstSize); 62050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 621792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber int64_t timeUs; 622792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs)); 623792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber int32_t isSync; 624792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)); 62550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 626792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 627792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync); 62850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 629792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstPtr = (uint8_t *)buffer->data(); 630792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 63150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 63250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 633792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame->release(); 634792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame = NULL; 63550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 6365ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (targetSampleTimeUs >= 0ll) { 6375ec58d925520e6913fba3fc54413881af751c610Andreas Huber buffer->meta_data()->setInt64( 6385ec58d925520e6913fba3fc54413881af751c610Andreas Huber kKeyTargetTime, targetSampleTimeUs); 6395ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 6405ec58d925520e6913fba3fc54413881af751c610Andreas Huber 64150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = buffer; 642093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 643093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 644093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 645093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 646093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber//////////////////////////////////////////////////////////////////////////////// 647093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 648093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source) 649093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mDataSource(source), 650093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mReader(new DataSourceReader(mDataSource)), 6515279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mSegment(NULL), 6528c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mExtractedThumbnails(false), 6538c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mIsWebm(false) { 654d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber off64_t size; 655d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mIsLiveStreaming = 656d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber (mDataSource->flags() 657d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber & (DataSource::kWantsPrefetching 658d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber | DataSource::kIsCachingDataSource)) 659d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && mDataSource->getSize(&size) != OK; 660d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 661093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::EBMLHeader ebmlHeader; 662093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long pos; 663093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ebmlHeader.Parse(mReader, pos) < 0) { 664093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 665093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 666093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 6678c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) { 6688c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mIsWebm = true; 6698c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber } 6708c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber 671093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long ret = 672093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::Segment::CreateInstance(mReader, pos, mSegment); 673093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 674093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ret) { 675093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(mSegment == NULL); 676093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 677093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 678093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 67910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ret = mSegment->ParseHeaders(); 68010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann CHECK_EQ(ret, 0); 681d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 68210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann long len; 68310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ret = mSegment->LoadCluster(pos, len); 68410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann CHECK_EQ(ret, 0); 685093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 686093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ret < 0) { 687093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mSegment; 688093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mSegment = NULL; 689093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 690093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 691093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 69274a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber#if 0 69374a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber const mkvparser::SegmentInfo *info = mSegment->GetInfo(); 694df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("muxing app: %s, writing app: %s", 69574a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber info->GetMuxingAppAsUTF8(), 69674a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber info->GetWritingAppAsUTF8()); 69774a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber#endif 69874a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 699093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber addTracks(); 700093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 701093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 702093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::~MatroskaExtractor() { 703093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mSegment; 704093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mSegment = NULL; 705093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 706093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mReader; 707093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mReader = NULL; 708093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 709093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 710093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersize_t MatroskaExtractor::countTracks() { 711093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mTracks.size(); 712093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 713093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 714093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MediaSource> MatroskaExtractor::getTrack(size_t index) { 715093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (index >= mTracks.size()) { 716093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return NULL; 717093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 718093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 719093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return new MatroskaSource(this, index); 720093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 721093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 722093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaExtractor::getTrackMetaData( 723093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t index, uint32_t flags) { 724093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (index >= mTracks.size()) { 725093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return NULL; 726093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 727093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 728d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails 729d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && !isLiveStreaming()) { 7305279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber findThumbnails(); 7315279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mExtractedThumbnails = true; 7325279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 7335279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 734093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mTracks.itemAt(index).mMeta; 735093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 736093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 737d42573cace9db2b5948e540c32beaef80f04153cAndreas Huberbool MatroskaExtractor::isLiveStreaming() const { 738d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return mIsLiveStreaming; 739d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 740d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 741132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kangstatic void addESDSFromCodecPrivate( 742132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang const sp<MetaData> &meta, 743132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang bool isAudio, const void *priv, size_t privSize) { 744093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber static const uint8_t kStaticESDS[] = { 745093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x03, 22, 746093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x00, 0x00, // ES_ID 747093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag 748093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 749093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x04, 17, 750132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang 0x40, // ObjectTypeIndication 751093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x00, 0x00, 0x00, 0x00, 752093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x00, 0x00, 0x00, 0x00, 753093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x00, 0x00, 0x00, 0x00, 754093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 755093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x05, 756132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang // CodecSpecificInfo (with size prefix) follows 757093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber }; 758093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 75982ac8bf2da940c4439786c346f739f4a496864adAndreas Huber // Make sure all sizes can be coded in a single byte. 760132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang CHECK(privSize + 22 - 2 < 128); 761132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang size_t esdsSize = sizeof(kStaticESDS) + privSize + 1; 762093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber uint8_t *esds = new uint8_t[esdsSize]; 763093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber memcpy(esds, kStaticESDS, sizeof(kStaticESDS)); 764093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber uint8_t *ptr = esds + sizeof(kStaticESDS); 765132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang *ptr++ = privSize; 766132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang memcpy(ptr, priv, privSize); 767093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 76882ac8bf2da940c4439786c346f739f4a496864adAndreas Huber // Increment by codecPrivateSize less 2 bytes that are accounted for 76982ac8bf2da940c4439786c346f739f4a496864adAndreas Huber // already in lengths of 22/17 770132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang esds[1] += privSize - 2; 771132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang esds[6] += privSize - 2; 772132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang 773132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang // Set ObjectTypeIndication. 774132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang esds[7] = isAudio ? 0x40 // Audio ISO/IEC 14496-3 775132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang : 0x20; // Visual ISO/IEC 14496-2 77682ac8bf2da940c4439786c346f739f4a496864adAndreas Huber 777093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData(kKeyESDS, 0, esds, esdsSize); 778093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 779093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete[] esds; 780093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber esds = NULL; 781093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 782093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 783093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubervoid addVorbisCodecInfo( 784093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MetaData> &meta, 785093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const void *_codecPrivate, size_t codecPrivateSize) { 786093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber // printf("vorbis private data follows:\n"); 787093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber // hexdump(_codecPrivate, codecPrivateSize); 788093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 789093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(codecPrivateSize >= 3); 790093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 791093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate; 792093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(codecPrivate[0] == 0x02); 793093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 794093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t len1 = codecPrivate[1]; 795093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t len2 = codecPrivate[2]; 796093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 797093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(codecPrivateSize > 3 + len1 + len2); 798093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 799093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(codecPrivate[3] == 0x01); 800093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData(kKeyVorbisInfo, 0, &codecPrivate[3], len1); 801093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 802093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(codecPrivate[len1 + 3] == 0x03); 803093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 804093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(codecPrivate[len1 + len2 + 3] == 0x05); 805093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData( 806093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber kKeyVorbisBooks, 0, &codecPrivate[len1 + len2 + 3], 807093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber codecPrivateSize - len1 - len2 - 3); 808093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 809093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 810093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubervoid MatroskaExtractor::addTracks() { 811093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::Tracks *tracks = mSegment->GetTracks(); 812093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 813093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber for (size_t index = 0; index < tracks->GetTracksCount(); ++index) { 814093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::Track *track = tracks->GetTrackByIndex(index); 815093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 81630ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber if (track == NULL) { 81730ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber // Apparently this is currently valid (if unexpected) behaviour 81830ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber // of the mkv parser lib. 81930ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber continue; 82030ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber } 82130ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber 822093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *const codecID = track->GetCodecId(); 8233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("codec id = %s", codecID); 8243856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("codec name = %s", track->GetCodecNameAsUTF8()); 825093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 826093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t codecPrivateSize; 827093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const unsigned char *codecPrivate = 828ff1df9951d09f1a1a8ae2dbc42b82b0f9c164e5eAndreas Huber track->GetCodecPrivate(codecPrivateSize); 829093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 830093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 }; 831093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 832093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MetaData> meta = new MetaData; 833093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 834093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber switch (track->GetType()) { 835093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber case VIDEO_TRACK: 836093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber { 837093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::VideoTrack *vtrack = 838093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber static_cast<const mkvparser::VideoTrack *>(track); 839093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 840093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { 841093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 842093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); 843132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) { 844132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang if (codecPrivateSize > 0) { 845132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta->setCString( 846132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 847132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang addESDSFromCodecPrivate( 848132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta, false, codecPrivate, codecPrivateSize); 849132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else { 850132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is detected, but does not have configuration.", 851132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang codecID); 852132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang continue; 853132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } 854093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcmp("V_VP8", codecID)) { 855093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VPX); 856093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else { 857132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is not supported.", codecID); 858093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 859093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 860093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 861093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyWidth, vtrack->GetWidth()); 862093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyHeight, vtrack->GetHeight()); 863093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber break; 864093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 865093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 866093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber case AUDIO_TRACK: 867093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber { 868093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::AudioTrack *atrack = 869093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber static_cast<const mkvparser::AudioTrack *>(track); 870093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 871093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcmp("A_AAC", codecID)) { 872093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); 873093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(codecPrivateSize >= 2); 874093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 875132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang addESDSFromCodecPrivate( 876132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta, true, codecPrivate, codecPrivateSize); 877093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcmp("A_VORBIS", codecID)) { 878093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 879093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 880093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber addVorbisCodecInfo(meta, codecPrivate, codecPrivateSize); 881132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else if (!strcmp("A_MPEG/L3", codecID)) { 882132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 883093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else { 884132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is not supported.", codecID); 885093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 886093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 887093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 888093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeySampleRate, atrack->GetSamplingRate()); 889093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyChannelCount, atrack->GetChannels()); 890093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber break; 891093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 892093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 893093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber default: 894093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 895093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 896093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 897093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long durationNs = mSegment->GetDuration(); 898093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt64(kKeyDuration, (durationNs + 500) / 1000); 899093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 900093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mTracks.push(); 901093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1); 902093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber trackInfo->mTrackNum = track->GetNumber(); 903093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber trackInfo->mMeta = meta; 904093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 905093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 906093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9075279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid MatroskaExtractor::findThumbnails() { 9085279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 9095279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber TrackInfo *info = &mTracks.editItemAt(i); 9105279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 9115279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const char *mime; 9125279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber CHECK(info->mMeta->findCString(kKeyMIMEType, &mime)); 9135279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 9145279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (strncasecmp(mime, "video/", 6)) { 9155279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber continue; 9165279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 9175279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 918d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber BlockIterator iter(this, info->mTrackNum); 9195279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int32_t i = 0; 9205279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t thumbnailTimeUs = 0; 9215279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber size_t maxBlockSize = 0; 9225279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber while (!iter.eos() && i < 20) { 9235279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (iter.block()->IsKey()) { 9245279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber ++i; 9255279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 926d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber size_t blockSize = 0; 927d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber for (int i = 0; i < iter.block()->GetFrameCount(); ++i) { 928d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber blockSize += iter.block()->GetFrame(i).len; 929d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 930d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 9315279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (blockSize > maxBlockSize) { 9325279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber maxBlockSize = blockSize; 9335279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber thumbnailTimeUs = iter.blockTimeUs(); 9345279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 9355279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 9365279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber iter.advance(); 9375279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 9385279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 9395279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 9405279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 9415279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 942093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaExtractor::getMetaData() { 943093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MetaData> meta = new MetaData; 9448c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber 9458c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber meta->setCString( 9468c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber kKeyMIMEType, 9478c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA); 948093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 949093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return meta; 950093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 951093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 952d42573cace9db2b5948e540c32beaef80f04153cAndreas Huberuint32_t MatroskaExtractor::flags() const { 953d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber uint32_t x = CAN_PAUSE; 954d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (!isLiveStreaming()) { 955d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK; 956d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 957d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 958d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return x; 959d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 960d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 961093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberbool SniffMatroska( 9625a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 9635a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 964093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader reader(source); 965093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::EBMLHeader ebmlHeader; 966093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long pos; 967093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ebmlHeader.Parse(&reader, pos) < 0) { 968093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return false; 969093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 970093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 971093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA); 972093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *confidence = 0.6; 973093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 974093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return true; 975093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 976093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 977093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} // namespace android 978