MatroskaExtractor.cpp revision e467ef084b75b074d0081616080b54212a7024c8
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( 98f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann int64_t seekTimeUs, bool isAudio, 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 266e467ef084b75b074d0081616080b54212a7024c8Lajos Molnar if (res != 0) { 267e467ef084b75b074d0081616080b54212a7024c8Lajos Molnar // EOF or error 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( 310f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann int64_t seekTimeUs, bool isAudio, 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 375f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // The Cue index is built around video keyframes 37610f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mkvparser::Tracks const *pTracks = pSegment->GetTracks(); 37710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::Track *pTrack = NULL; 37810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann for (size_t index = 0; index < pTracks->GetTracksCount(); ++index) { 37910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pTrack = pTracks->GetTrackByIndex(index); 38010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann if (pTrack && pTrack->GetType() == 1) { // VIDEO_TRACK 38110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ALOGV("Video track located at %d", index); 38210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann break; 38310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 38410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 38510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 386f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // Always *search* based on the video track, but finalize based on mTrackNum 38710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann const mkvparser::CuePoint::TrackPosition* pTP; 388f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann if (pTrack && pTrack->GetType() == 1) { 38910f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann pCues->Find(seekTimeNs, pTrack, pCP, pTP); 39010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } else { 391f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann ALOGE("Did not locate the video track for seeking"); 39210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann return; 39310f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann } 39410f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann 39510f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos); 3965279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 397f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK(mCluster); 398f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK(!mCluster->EOS()); 399f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann 400f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // mBlockEntryIndex starts at 0 but m_block starts at 1 401f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann CHECK_GT(pTP->m_block, 0); 402f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann mBlockEntryIndex = pTP->m_block - 1; 4035ec58d925520e6913fba3fc54413881af751c610Andreas Huber 4045ec58d925520e6913fba3fc54413881af751c610Andreas Huber for (;;) { 405d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber advance_l(); 4065279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 407f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann if (eos()) break; 4085ec58d925520e6913fba3fc54413881af751c610Andreas Huber 409f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann if (isAudio || block()->IsKey()) { 410f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // Accept the first key frame 411f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann *actualFrameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL; 412f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann ALOGV("Requested seek point: %lld actual: %lld", 413f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann seekTimeUs, actualFrameTimeUs); 4145ec58d925520e6913fba3fc54413881af751c610Andreas Huber break; 41574a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber } 4165279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 417093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 418093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 4195279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberconst mkvparser::Block *BlockIterator::block() const { 4205279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber CHECK(!eos()); 4215279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 4225279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return mBlockEntry->GetBlock(); 4235279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 4245279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 4255279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huberint64_t BlockIterator::blockTimeUs() const { 4265279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll; 4275279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 4285279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 4295279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber//////////////////////////////////////////////////////////////////////////////// 4305279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 431b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huberstatic unsigned U24_AT(const uint8_t *ptr) { 432b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; 433b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber} 434b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 43550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatic size_t clz(uint8_t x) { 43650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber size_t numLeadingZeroes = 0; 437093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 43850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (!(x & 0x80)) { 43950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber ++numLeadingZeroes; 44050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber x = x << 1; 441093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 442093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 44350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return numLeadingZeroes; 44450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 44550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 44650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Hubervoid MatroskaSource::clearPendingFrames() { 44750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (!mPendingFrames.empty()) { 44850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer *frame = *mPendingFrames.begin(); 44950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.erase(mPendingFrames.begin()); 45050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 45150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber frame->release(); 45250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber frame = NULL; 45350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 45450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 45550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 45650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatus_t MatroskaSource::readBlock() { 45750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber CHECK(mPendingFrames.empty()); 45850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 4595279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (mBlockIter.eos()) { 460093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return ERROR_END_OF_STREAM; 461093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 462093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 4635279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const mkvparser::Block *block = mBlockIter.block(); 46450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 4655279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t timeUs = mBlockIter.blockTimeUs(); 466093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 467d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber for (int i = 0; i < block->GetFrameCount(); ++i) { 468d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber const mkvparser::Block::Frame &frame = block->GetFrame(i); 469b10f3669a9b73cd024662c2b70f5155bc0c2cd21Andreas Huber 470d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber MediaBuffer *mbuf = new MediaBuffer(frame.len); 471d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mbuf->meta_data()->setInt64(kKeyTime, timeUs); 472d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey()); 473093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 474d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data()); 475d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (n != 0) { 476d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mPendingFrames.clear(); 47750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 478d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter.advance(); 479d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return ERROR_IO; 48050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 48150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 48250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.push_back(mbuf); 48350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 48450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 485d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mBlockIter.advance(); 48650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 48750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return OK; 48850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber} 48950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 49050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huberstatus_t MatroskaSource::read( 49150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer **out, const ReadOptions *options) { 49250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = NULL; 49350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 4945ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t targetSampleTimeUs = -1ll; 4955ec58d925520e6913fba3fc54413881af751c610Andreas Huber 49650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber int64_t seekTimeUs; 49750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber ReadOptions::SeekMode mode; 498d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode) 499d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && !mExtractor->isLiveStreaming()) { 50050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 50174a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 502f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // The audio we want is located by using the Cues to seek the video 503f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // stream to find the target Cluster then iterating to finalize for 504f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann // audio. 5055ec58d925520e6913fba3fc54413881af751c610Andreas Huber int64_t actualFrameTimeUs; 506f02a7f5c42db707d20e59ff28f32d1eaebcc5429Johann mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs); 5075ec58d925520e6913fba3fc54413881af751c610Andreas Huber 5085ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 5095ec58d925520e6913fba3fc54413881af751c610Andreas Huber targetSampleTimeUs = actualFrameTimeUs; 5105ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 51150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 51250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 51350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber while (mPendingFrames.empty()) { 51450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber status_t err = readBlock(); 51550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 51650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber if (err != OK) { 51750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber clearPendingFrames(); 51850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 51950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return err; 52050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 52150c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 52250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 52350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber MediaBuffer *frame = *mPendingFrames.begin(); 52450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber mPendingFrames.erase(mPendingFrames.begin()); 52550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 52650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber if (mType != AVC) { 5275ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (targetSampleTimeUs >= 0ll) { 5285ec58d925520e6913fba3fc54413881af751c610Andreas Huber frame->meta_data()->setInt64( 5295ec58d925520e6913fba3fc54413881af751c610Andreas Huber kKeyTargetTime, targetSampleTimeUs); 5305ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 5315ec58d925520e6913fba3fc54413881af751c610Andreas Huber 53250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = frame; 53350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 53450c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber return OK; 53550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 53650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 537792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // Each input frame contains one or more NAL fragments, each fragment 538792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // is prefixed by mNALSizeLen bytes giving the fragment length, 539792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // followed by a corresponding number of bytes containing the fragment. 540792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // We output all these fragments into a single large buffer separated 541792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // by startcodes (0x00 0x00 0x00 0x01). 542792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 543792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber const uint8_t *srcPtr = 544792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber (const uint8_t *)frame->data() + frame->range_offset(); 545792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 546792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t srcSize = frame->range_length(); 547792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 548792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t dstSize = 0; 549792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber MediaBuffer *buffer = NULL; 550792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber uint8_t *dstPtr = NULL; 551792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber 552792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber for (int32_t pass = 0; pass < 2; ++pass) { 553792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t srcOffset = 0; 554792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t dstOffset = 0; 555792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber while (srcOffset + mNALSizeLen <= srcSize) { 556792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber size_t NALsize; 557792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber switch (mNALSizeLen) { 558792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 1: NALsize = srcPtr[srcOffset]; break; 559792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 2: NALsize = U16_AT(srcPtr + srcOffset); break; 560792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 3: NALsize = U24_AT(srcPtr + srcOffset); break; 561792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber case 4: NALsize = U32_AT(srcPtr + srcOffset); break; 562792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber default: 563792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber TRESPASS(); 564792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 56550c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 566792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (srcOffset + mNALSizeLen + NALsize > srcSize) { 567792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber break; 568792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 56950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 570792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (pass == 1) { 571792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4); 57250c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 573792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber memcpy(&dstPtr[dstOffset + 4], 574792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber &srcPtr[srcOffset + mNALSizeLen], 575792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber NALsize); 576792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 57750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 578792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstOffset += 4; // 0x00 00 00 01 579792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstOffset += NALsize; 58050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 581792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber srcOffset += mNALSizeLen + NALsize; 582792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 58350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 584792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (srcOffset < srcSize) { 585792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // There were trailing bytes or not enough data to complete 586792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber // a fragment. 58750c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 588792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame->release(); 589792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame = NULL; 59050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 591792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber return ERROR_MALFORMED; 592792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 59350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 594792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber if (pass == 0) { 595792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstSize = dstOffset; 59650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 597792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer = new MediaBuffer(dstSize); 59850c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 599792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber int64_t timeUs; 600792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs)); 601792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber int32_t isSync; 602792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)); 60350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 604792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 605792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync); 60650c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 607792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber dstPtr = (uint8_t *)buffer->data(); 608792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber } 60950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber } 61050c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 611792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame->release(); 612792e33fd19e57e0d615d401a54ab567d04f16251Andreas Huber frame = NULL; 61350c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber 6145ec58d925520e6913fba3fc54413881af751c610Andreas Huber if (targetSampleTimeUs >= 0ll) { 6155ec58d925520e6913fba3fc54413881af751c610Andreas Huber buffer->meta_data()->setInt64( 6165ec58d925520e6913fba3fc54413881af751c610Andreas Huber kKeyTargetTime, targetSampleTimeUs); 6175ec58d925520e6913fba3fc54413881af751c610Andreas Huber } 6185ec58d925520e6913fba3fc54413881af751c610Andreas Huber 61950c8bea8fba2fcafb14696399028bdbc094dc995Andreas Huber *out = buffer; 620093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 621093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return OK; 622093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 623093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 624093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber//////////////////////////////////////////////////////////////////////////////// 625093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 626093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source) 627093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber : mDataSource(source), 628093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mReader(new DataSourceReader(mDataSource)), 6295279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mSegment(NULL), 6308c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mExtractedThumbnails(false), 6318c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mIsWebm(false) { 632d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber off64_t size; 633d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber mIsLiveStreaming = 634d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber (mDataSource->flags() 635d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber & (DataSource::kWantsPrefetching 636d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber | DataSource::kIsCachingDataSource)) 637d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && mDataSource->getSize(&size) != OK; 638d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 639093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::EBMLHeader ebmlHeader; 640093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long pos; 641093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ebmlHeader.Parse(mReader, pos) < 0) { 642093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 643093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 644093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 6458c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) { 6468c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mIsWebm = true; 6478c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber } 6488c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber 649093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long ret = 650093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::Segment::CreateInstance(mReader, pos, mSegment); 651093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 652093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ret) { 653093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(mSegment == NULL); 654093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 655093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 656093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 65710f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ret = mSegment->ParseHeaders(); 65810f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann CHECK_EQ(ret, 0); 659d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 66010f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann long len; 66110f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann ret = mSegment->LoadCluster(pos, len); 66210f0fe7bcd60bdb0eceb905e84ac11555e8c1b9dJohann CHECK_EQ(ret, 0); 663093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 664093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ret < 0) { 665093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mSegment; 666093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mSegment = NULL; 667093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return; 668093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 669093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 67074a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber#if 0 67174a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber const mkvparser::SegmentInfo *info = mSegment->GetInfo(); 672df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("muxing app: %s, writing app: %s", 67374a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber info->GetMuxingAppAsUTF8(), 67474a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber info->GetWritingAppAsUTF8()); 67574a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber#endif 67674a0a0d7f766d63330a00c3fa8f133c44c1d5be6Andreas Huber 677093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber addTracks(); 678093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 679093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 680093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas HuberMatroskaExtractor::~MatroskaExtractor() { 681093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mSegment; 682093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mSegment = NULL; 683093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 684093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete mReader; 685093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mReader = NULL; 686093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 687093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 688093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersize_t MatroskaExtractor::countTracks() { 689093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mTracks.size(); 690093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 691093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 692093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MediaSource> MatroskaExtractor::getTrack(size_t index) { 693093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (index >= mTracks.size()) { 694093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return NULL; 695093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 696093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 697093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return new MatroskaSource(this, index); 698093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 699093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 700093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaExtractor::getTrackMetaData( 701093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t index, uint32_t flags) { 702093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (index >= mTracks.size()) { 703093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return NULL; 704093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 705093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 706d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails 707d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber && !isLiveStreaming()) { 7085279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber findThumbnails(); 7095279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber mExtractedThumbnails = true; 7105279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 7115279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 712093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return mTracks.itemAt(index).mMeta; 713093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 714093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 715d42573cace9db2b5948e540c32beaef80f04153cAndreas Huberbool MatroskaExtractor::isLiveStreaming() const { 716d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return mIsLiveStreaming; 717d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 718d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 719132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kangstatic void addESDSFromCodecPrivate( 720132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang const sp<MetaData> &meta, 721132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang bool isAudio, const void *priv, size_t privSize) { 722093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber static const uint8_t kStaticESDS[] = { 723093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x03, 22, 724093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x00, 0x00, // ES_ID 725093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag 726093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 727093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x04, 17, 728132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang 0x40, // ObjectTypeIndication 729093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x00, 0x00, 0x00, 0x00, 730093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x00, 0x00, 0x00, 0x00, 731093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x00, 0x00, 0x00, 0x00, 732093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 733093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 0x05, 734132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang // CodecSpecificInfo (with size prefix) follows 735093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber }; 736093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 73782ac8bf2da940c4439786c346f739f4a496864adAndreas Huber // Make sure all sizes can be coded in a single byte. 738132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang CHECK(privSize + 22 - 2 < 128); 739132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang size_t esdsSize = sizeof(kStaticESDS) + privSize + 1; 740093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber uint8_t *esds = new uint8_t[esdsSize]; 741093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber memcpy(esds, kStaticESDS, sizeof(kStaticESDS)); 742093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber uint8_t *ptr = esds + sizeof(kStaticESDS); 743132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang *ptr++ = privSize; 744132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang memcpy(ptr, priv, privSize); 745093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 74682ac8bf2da940c4439786c346f739f4a496864adAndreas Huber // Increment by codecPrivateSize less 2 bytes that are accounted for 74782ac8bf2da940c4439786c346f739f4a496864adAndreas Huber // already in lengths of 22/17 748132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang esds[1] += privSize - 2; 749132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang esds[6] += privSize - 2; 750132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang 751132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang // Set ObjectTypeIndication. 752132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang esds[7] = isAudio ? 0x40 // Audio ISO/IEC 14496-3 753132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang : 0x20; // Visual ISO/IEC 14496-2 75482ac8bf2da940c4439786c346f739f4a496864adAndreas Huber 755093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData(kKeyESDS, 0, esds, esdsSize); 756093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 757093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber delete[] esds; 758093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber esds = NULL; 759093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 760093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 7615ce181568da90c78ba7fad3e084c8479041545dfAndreas Huberstatus_t addVorbisCodecInfo( 762093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const sp<MetaData> &meta, 763093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const void *_codecPrivate, size_t codecPrivateSize) { 764093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber // hexdump(_codecPrivate, codecPrivateSize); 765093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 7665ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivateSize < 1) { 7675ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 7685ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 769093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 770093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate; 771093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 7725ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[0] != 0x02) { 7735ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 7745ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 775093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 7765ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber // codecInfo starts with two lengths, len1 and len2, that are 7775ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber // "Xiph-style-lacing encoded"... 778093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 7795ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t offset = 1; 7805ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t len1 = 0; 7815ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 7825ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len1 += 0xff; 7835ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ++offset; 7845ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 7855ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (offset >= codecPrivateSize) { 7865ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 7875ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 7885ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len1 += codecPrivate[offset++]; 789093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 7905ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber size_t len2 = 0; 7915ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 7925ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len2 += 0xff; 7935ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ++offset; 7945ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 7955ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (offset >= codecPrivateSize) { 7965ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 7975ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 7985ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber len2 += codecPrivate[offset++]; 7995ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 8005ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivateSize < offset + len1 + len2) { 8015ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 8025ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 8035ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 8045ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x01) { 8055ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 8065ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 8075ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1); 8085ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 8095ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber offset += len1; 8105ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x03) { 8115ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 8125ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 8135ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 8145ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber offset += len2; 8155ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (codecPrivate[offset] != 0x05) { 8165ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return ERROR_MALFORMED; 8175ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 818093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 819093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData( 8205ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber kKeyVorbisBooks, 0, &codecPrivate[offset], 8215ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber codecPrivateSize - offset); 8225ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 8235ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber return OK; 824093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 825093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 826093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubervoid MatroskaExtractor::addTracks() { 827093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::Tracks *tracks = mSegment->GetTracks(); 828093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 829093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber for (size_t index = 0; index < tracks->GetTracksCount(); ++index) { 830093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::Track *track = tracks->GetTrackByIndex(index); 831093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 83230ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber if (track == NULL) { 83330ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber // Apparently this is currently valid (if unexpected) behaviour 83430ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber // of the mkv parser lib. 83530ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber continue; 83630ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber } 83730ae68bccd8de6f0ab2acd22a6d661ace514343eAndreas Huber 838093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *const codecID = track->GetCodecId(); 8393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("codec id = %s", codecID); 8403856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("codec name = %s", track->GetCodecNameAsUTF8()); 841093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 842093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber size_t codecPrivateSize; 843093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const unsigned char *codecPrivate = 844ff1df9951d09f1a1a8ae2dbc42b82b0f9c164e5eAndreas Huber track->GetCodecPrivate(codecPrivateSize); 845093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 846093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 }; 847093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 848093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MetaData> meta = new MetaData; 849093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8505ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber status_t err = OK; 8515ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 852093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber switch (track->GetType()) { 853093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber case VIDEO_TRACK: 854093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber { 855093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::VideoTrack *vtrack = 856093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber static_cast<const mkvparser::VideoTrack *>(track); 857093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 858093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { 859093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 860093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); 861132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) { 862132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang if (codecPrivateSize > 0) { 863132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta->setCString( 864132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 865132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang addESDSFromCodecPrivate( 866132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta, false, codecPrivate, codecPrivateSize); 867132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else { 868132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is detected, but does not have configuration.", 869132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang codecID); 870132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang continue; 871132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } 872093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcmp("V_VP8", codecID)) { 873093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VPX); 874093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else { 875132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is not supported.", codecID); 876093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 877093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 878093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 879093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyWidth, vtrack->GetWidth()); 880093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyHeight, vtrack->GetHeight()); 881093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber break; 882093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 883093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 884093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber case AUDIO_TRACK: 885093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber { 886093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const mkvparser::AudioTrack *atrack = 887093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber static_cast<const mkvparser::AudioTrack *>(track); 888093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 889093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcmp("A_AAC", codecID)) { 890093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); 891093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(codecPrivateSize >= 2); 892093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 893132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang addESDSFromCodecPrivate( 894132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta, true, codecPrivate, codecPrivateSize); 895093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else if (!strcmp("A_VORBIS", codecID)) { 896093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 897093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 8985ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber err = addVorbisCodecInfo( 8995ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber meta, codecPrivate, codecPrivateSize); 900132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang } else if (!strcmp("A_MPEG/L3", codecID)) { 901132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 902093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } else { 903132e88ee86e4f11d1b649c336cd2d6eb5980c3fcDongwon Kang ALOGW("%s is not supported.", codecID); 904093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 905093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 906093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 907093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeySampleRate, atrack->GetSamplingRate()); 908093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt32(kKeyChannelCount, atrack->GetChannels()); 909093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber break; 910093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 911093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 912093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber default: 913093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber continue; 914093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 915093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9165ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber if (err != OK) { 9175ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber ALOGE("skipping track, codec specific data was malformed."); 9185ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber continue; 9195ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber } 9205ce181568da90c78ba7fad3e084c8479041545dfAndreas Huber 921093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long durationNs = mSegment->GetDuration(); 922093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber meta->setInt64(kKeyDuration, (durationNs + 500) / 1000); 923093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 924093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mTracks.push(); 925093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1); 926093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber trackInfo->mTrackNum = track->GetNumber(); 927093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber trackInfo->mMeta = meta; 928093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 929093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 930093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 9315279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Hubervoid MatroskaExtractor::findThumbnails() { 9325279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 9335279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber TrackInfo *info = &mTracks.editItemAt(i); 9345279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 9355279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber const char *mime; 9365279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber CHECK(info->mMeta->findCString(kKeyMIMEType, &mime)); 9375279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 9385279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (strncasecmp(mime, "video/", 6)) { 9395279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber continue; 9405279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 9415279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 942d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber BlockIterator iter(this, info->mTrackNum); 9434719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer int32_t j = 0; 9445279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber int64_t thumbnailTimeUs = 0; 9455279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber size_t maxBlockSize = 0; 9464719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer while (!iter.eos() && j < 20) { 9475279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (iter.block()->IsKey()) { 9484719fa8ae1259d6a94ba5b5ecdaa01e69f553996Bernhard Rosenkraenzer ++j; 9495279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 950d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber size_t blockSize = 0; 951cba4ed0039c8b8fac01b3193d19fc2364f934506Tareq A. Siraj for (int k = 0; k < iter.block()->GetFrameCount(); ++k) { 952cba4ed0039c8b8fac01b3193d19fc2364f934506Tareq A. Siraj blockSize += iter.block()->GetFrame(k).len; 953d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 954d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 9555279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber if (blockSize > maxBlockSize) { 9565279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber maxBlockSize = blockSize; 9575279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber thumbnailTimeUs = iter.blockTimeUs(); 9585279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 9595279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 9605279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber iter.advance(); 9615279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 9625279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 9635279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber } 9645279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber} 9655279d1d8c19e5fdbb177805db0da8e8aadac3079Andreas Huber 966093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Hubersp<MetaData> MatroskaExtractor::getMetaData() { 967093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MetaData> meta = new MetaData; 9688c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber 9698c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber meta->setCString( 9708c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber kKeyMIMEType, 9718c32b164d00d3e4d73764d06956331f09693ef43Andreas Huber mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA); 972093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 973093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return meta; 974093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 975093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 976d42573cace9db2b5948e540c32beaef80f04153cAndreas Huberuint32_t MatroskaExtractor::flags() const { 977d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber uint32_t x = CAN_PAUSE; 978d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber if (!isLiveStreaming()) { 979d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK; 980d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber } 981d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 982d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber return x; 983d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber} 984d42573cace9db2b5948e540c32beaef80f04153cAndreas Huber 985093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huberbool SniffMatroska( 9865a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 9875a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 988093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber DataSourceReader reader(source); 989093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mkvparser::EBMLHeader ebmlHeader; 990093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber long long pos; 991093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (ebmlHeader.Parse(&reader, pos) < 0) { 992093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return false; 993093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 994093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 995093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA); 996093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber *confidence = 0.6; 997093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 998093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber return true; 999093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} 1000093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 1001093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber} // namespace android 1002