MatroskaExtractor.cpp revision 84333e0475bc911adc16417f4ca327c975cf6c36
1e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard/* 2e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * Copyright (C) 2010 The Android Open Source Project 3e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * 4e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * Licensed under the Apache License, Version 2.0 (the "License"); 5e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * you may not use this file except in compliance with the License. 6e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * You may obtain a copy of the License at 7e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * 8e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * http://www.apache.org/licenses/LICENSE-2.0 9e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * 10e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * Unless required by applicable law or agreed to in writing, software 11e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * distributed under the License is distributed on an "AS IS" BASIS, 12e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * See the License for the specific language governing permissions and 14e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard * limitations under the License. 15e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard */ 16e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 17e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard//#define LOG_NDEBUG 0 18e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#define LOG_TAG "MatroskaExtractor" 19e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <utils/Log.h> 20e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 21956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include "MatroskaExtractor.h" 22956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 23e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include "mkvparser.hpp" 24956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 25956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include <media/stagefright/foundation/ADebug.h> 26956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#include <media/stagefright/foundation/hexdump.h> 27e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <media/stagefright/DataSource.h> 28e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <media/stagefright/MediaBuffer.h> 29e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <media/stagefright/MediaDefs.h> 30e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <media/stagefright/MediaErrors.h> 31e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <media/stagefright/MediaSource.h> 32e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <media/stagefright/MetaData.h> 33e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard#include <media/stagefright/Utils.h> 34b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard#include <utils/String8.h> 35956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 36956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongnamespace android { 37956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 38956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstruct DataSourceReader : public mkvparser::IMkvReader { 39956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong DataSourceReader(const sp<DataSource> &source) 40956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong : mSource(source) { 41956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 42e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 43e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard virtual int Read(long long position, long length, unsigned char* buffer) { 44e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK(position >= 0); 45e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK(length >= 0); 46e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 47e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (length == 0) { 48e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return 0; 49e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 50b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 51e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ssize_t n = mSource->readAt(position, buffer, length); 52e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 53e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (n <= 0) { 54b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard return -1; 55b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard } 56b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 57b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard return 0; 58e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 59e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 60e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard virtual int Length(long long* total, long long* available) { 61b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard off64_t size; 62e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (mSource->getSize(&size) != OK) { 63e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard *total = -1; 64e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard *available = (long long)((1ull << 63) - 1); 65e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 66956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return 0; 67956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 68956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 69956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (total) { 70956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *total = size; 71956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 72e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 73e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (available) { 74e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard *available = size; 75e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 76e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 77b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard return 0; 78b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard } 79e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 80e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardprivate: 81e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard sp<DataSource> mSource; 82e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 83e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard DataSourceReader(const DataSourceReader &); 84e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard DataSourceReader &operator=(const DataSourceReader &); 85e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}; 86e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 87e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard//////////////////////////////////////////////////////////////////////////////// 88e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 89e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstruct BlockIterator { 90e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum); 91e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 92e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard bool eos() const; 93e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 94e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard void advance(); 95e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard void reset(); 96e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 97e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard void seek( 98e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard int64_t seekTimeUs, bool isAudio, 99e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard int64_t *actualFrameTimeUs); 100e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 101e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard const mkvparser::Block *block() const; 102956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t blockTimeUs() const; 103956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 104956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongprivate: 105956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong MatroskaExtractor *mExtractor; 106956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong unsigned long mTrackNum; 107e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 108e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard const mkvparser::Cluster *mCluster; 109e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard const mkvparser::BlockEntry *mBlockEntry; 110e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard long mBlockEntryIndex; 111e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 112e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard void advance_l(); 113e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 114e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard BlockIterator(const BlockIterator &); 115e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard BlockIterator &operator=(const BlockIterator &); 116b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard}; 117e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 118e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstruct MatroskaSource : public MediaSource { 119e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard MatroskaSource( 120e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard const sp<MatroskaExtractor> &extractor, size_t index); 121e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 122e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard virtual status_t start(MetaData *params); 123e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard virtual status_t stop(); 124e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 125e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard virtual sp<MetaData> getFormat(); 126e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 127e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard virtual status_t read( 128e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard MediaBuffer **buffer, const ReadOptions *options); 129e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 130e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardprotected: 131e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard virtual ~MatroskaSource(); 132e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 133e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardprivate: 134e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard enum Type { 135e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard AVC, 136e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard AAC, 137e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard OTHER 138e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard }; 139e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 140e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard sp<MatroskaExtractor> mExtractor; 141e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard size_t mTrackIndex; 142e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Type mType; 143e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard bool mIsAudio; 144e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard BlockIterator mBlockIter; 145e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard size_t mNALSizeLen; // for type AVC 146e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 147e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard List<MediaBuffer *> mPendingFrames; 148e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 149e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard status_t advance(); 150e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 151e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard status_t readBlock(); 152e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard void clearPendingFrames(); 153e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 154e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard MatroskaSource(const MatroskaSource &); 155e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard MatroskaSource &operator=(const MatroskaSource &); 156e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard}; 157e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 158e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardMatroskaSource::MatroskaSource( 159e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard const sp<MatroskaExtractor> &extractor, size_t index) 160e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard : mExtractor(extractor), 161e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mTrackIndex(index), 162e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mType(OTHER), 163e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mIsAudio(false), 164e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mBlockIter(mExtractor.get(), 165e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mExtractor->mTracks.itemAt(index).mTrackNum), 166e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mNALSizeLen(0) { 167e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta; 168e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 169e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard const char *mime; 170e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK(meta->findCString(kKeyMIMEType, &mime)); 171e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 172e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mIsAudio = !strncasecmp("audio/", mime, 6); 173e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 174e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 175e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mType = AVC; 176e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 177e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard uint32_t dummy; 178e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard const uint8_t *avcc; 179e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard size_t avccSize; 180e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK(meta->findData( 181e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)); 182956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 183956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CHECK_GE(avccSize, 5u); 184956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 185956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mNALSizeLen = 1 + (avcc[4] & 3); 186956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ALOGV("mNALSizeLen = %d", mNALSizeLen); 187e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 188e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mType = AAC; 189e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 190e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 191e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 192e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardMatroskaSource::~MatroskaSource() { 193e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard clearPendingFrames(); 194e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 195e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 196e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardstatus_t MatroskaSource::start(MetaData * /* params */) { 197b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard mBlockIter.reset(); 198e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 199e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return OK; 200e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 201e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 202b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgardstatus_t MatroskaSource::stop() { 203e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard clearPendingFrames(); 204e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 205e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return OK; 206b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard} 207e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 208e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardsp<MetaData> MatroskaSource::getFormat() { 209e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return mExtractor->mTracks.itemAt(mTrackIndex).mMeta; 210e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 211b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 212e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard//////////////////////////////////////////////////////////////////////////////// 213b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 214e2e838afcf03e603a41a0455846eaf9614537c16Mans RullgardBlockIterator::BlockIterator( 215e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard MatroskaExtractor *extractor, unsigned long trackNum) 216e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard : mExtractor(extractor), 217e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mTrackNum(trackNum), 218e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mCluster(NULL), 219e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mBlockEntry(NULL), 220e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mBlockEntryIndex(0) { 221e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard reset(); 222e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 223e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 224e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardbool BlockIterator::eos() const { 225e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return mCluster == NULL || mCluster->EOS(); 226b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard} 227e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 228e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid BlockIterator::advance() { 229e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Mutex::Autolock autoLock(mExtractor->mLock); 230e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard advance_l(); 231e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 232e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 233e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid BlockIterator::advance_l() { 234b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard for (;;) { 235e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry); 236e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ALOGV("GetEntry returned %ld", res); 237e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 238e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard long long pos; 239e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard long len; 240e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (res < 0) { 241e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // Need to parse this cluster some more 242e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 243e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL); 244e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 245e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard res = mCluster->Parse(pos, len); 246e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ALOGV("Parse returned %ld", res); 247e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 248e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (res < 0) { 249e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // I/O error 250e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 251e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ALOGE("Cluster::Parse returned result %ld", res); 252e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 253e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mCluster = NULL; 254e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard break; 255e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 256e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 257e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard continue; 258e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } else if (res == 0) { 259e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // We're done with this cluster 260e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 261e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard const mkvparser::Cluster *nextCluster; 262e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard res = mExtractor->mSegment->ParseNext( 263e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mCluster, nextCluster, pos, len); 264e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ALOGV("ParseNext returned %ld", res); 265e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 266e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (res != 0) { 267e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // EOF or error 268e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 269e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mCluster = NULL; 270e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard break; 271e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 272e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 273956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CHECK_EQ(res, 0); 274956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CHECK(nextCluster != NULL); 275956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CHECK(!nextCluster->EOS()); 276956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 277956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mCluster = nextCluster; 278e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 279e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard res = mCluster->Parse(pos, len); 280e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ALOGV("Parse (2) returned %ld", res); 281e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK_GE(res, 0); 282e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 283e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mBlockEntryIndex = 0; 284e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard continue; 285b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard } 286e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 287e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK(mBlockEntry != NULL); 288e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK(mBlockEntry->GetBlock() != NULL); 289e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ++mBlockEntryIndex; 290b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 291b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) { 292b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard break; 293b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard } 294e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 295e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 296e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 297e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid BlockIterator::reset() { 298e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard Mutex::Autolock autoLock(mExtractor->mLock); 299b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 300e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mCluster = mExtractor->mSegment->GetFirst(); 301b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard mBlockEntry = NULL; 302b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard mBlockEntryIndex = 0; 303b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 304e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard do { 305e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard advance_l(); 306e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } while (!eos() && block()->GetTrackNumber() != mTrackNum); 307e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 308956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 309956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongvoid BlockIterator::seek( 310956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t seekTimeUs, bool isAudio, 311956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t *actualFrameTimeUs) { 312956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong Mutex::Autolock autoLock(mExtractor->mLock); 313e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 314e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard *actualFrameTimeUs = -1ll; 315e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 316e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard const int64_t seekTimeNs = seekTimeUs * 1000ll; 317e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 318e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mkvparser::Segment* const pSegment = mExtractor->mSegment; 319e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 320e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // Special case the 0 seek to avoid loading Cues when the application 321e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // extraneously seeks to 0 before playing. 322b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard if (seekTimeNs <= 0) { 323e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ALOGV("Seek to beginning: %lld", seekTimeUs); 324e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mCluster = pSegment->GetFirst(); 325b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard mBlockEntryIndex = 0; 326b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard do { 327b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard advance_l(); 328e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } while (!eos() && block()->GetTrackNumber() != mTrackNum); 329e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return; 330e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 331e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 332e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ALOGV("Seeking to: %lld", seekTimeUs); 333e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 334e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // If the Cues have not been located then find them. 335e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard const mkvparser::Cues* pCues = pSegment->GetCues(); 336b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard const mkvparser::SeekHead* pSH = pSegment->GetSeekHead(); 337b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard if (!pCues && pSH) { 338e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard const size_t count = pSH->GetCount(); 339b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard const mkvparser::SeekHead::Entry* pEntry; 340e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ALOGV("No Cues yet"); 341e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 3428a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo for (size_t index = 0; index < count; index++) { 3438a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo pEntry = pSH->GetEntry(index); 3448a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo 3458a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo if (pEntry->id == 0x0C53BB6B) { // Cues ID 3468a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo long len; long long pos; 3478a3b3707a6e320ba75f4ecd47fdc001f16c15cb8Martin Storsjo pSegment->ParseCues(pEntry->pos, pos, len); 348e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard pCues = pSegment->GetCues(); 349e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ALOGV("Cues found"); 350e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard break; 351956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 352956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 353956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 354956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (!pCues) { 355956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ALOGE("No Cues in file"); 356e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return; 357e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 358e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 359e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard else if (!pSH) { 360e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ALOGE("No SeekHead"); 361e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return; 362b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard } 363e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 364e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard const mkvparser::CuePoint* pCP; 365b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard while (!pCues->DoneParsing()) { 366e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard pCues->LoadCuePoint(); 367e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard pCP = pCues->GetLast(); 368e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 369956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (pCP->GetTime(pSegment) >= seekTimeNs) { 370956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ALOGV("Parsed past relevant Cue"); 371956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong break; 372b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard } 373956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 374e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 375e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard // The Cue index is built around video keyframes 376e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mkvparser::Tracks const *pTracks = pSegment->GetTracks(); 377e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard const mkvparser::Track *pTrack = NULL; 378e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard for (size_t index = 0; index < pTracks->GetTracksCount(); ++index) { 379e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard pTrack = pTracks->GetTrackByIndex(index); 380b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard if (pTrack && pTrack->GetType() == 1) { // VIDEO_TRACK 381b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ALOGV("Video track located at %d", index); 382e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard break; 383b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard } 384e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 385956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 386956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // Always *search* based on the video track, but finalize based on mTrackNum 387956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const mkvparser::CuePoint::TrackPosition* pTP; 388956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (pTrack && pTrack->GetType() == 1) { 389956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong pCues->Find(seekTimeNs, pTrack, pCP, pTP); 390956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } else { 391b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ALOGE("Did not locate the video track for seeking"); 392956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return; 393956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 394956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 395956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mCluster = pSegment->FindOrPreloadCluster(pTP->m_pos); 396956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 397956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CHECK(mCluster); 398956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CHECK(!mCluster->EOS()); 399956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 400956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // mBlockEntryIndex starts at 0 but m_block starts at 1 401956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CHECK_GT(pTP->m_block, 0); 402956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mBlockEntryIndex = pTP->m_block - 1; 403956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 404956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (;;) { 405956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong advance_l(); 406956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 407956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (eos()) break; 408956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 409956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (isAudio || block()->IsKey()) { 410956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // Accept the first key frame 411956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *actualFrameTimeUs = (block()->GetTime(mCluster) + 500LL) / 1000LL; 412956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ALOGV("Requested seek point: %lld actual: %lld", 413956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong seekTimeUs, *actualFrameTimeUs); 414956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong break; 415956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 416956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 417956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 418b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 419956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongconst mkvparser::Block *BlockIterator::block() const { 420956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CHECK(!eos()); 421956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 422956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return mBlockEntry->GetBlock(); 423956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 424956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 425956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongint64_t BlockIterator::blockTimeUs() const { 426956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll; 427956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 428e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 429e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard//////////////////////////////////////////////////////////////////////////////// 430e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 431956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic unsigned U24_AT(const uint8_t *ptr) { 432956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; 433956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 434956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 435956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatic size_t clz(uint8_t x) { 436956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong size_t numLeadingZeroes = 0; 437e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 438e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard while (!(x & 0x80)) { 439e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ++numLeadingZeroes; 440e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard x = x << 1; 441e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 442e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 443e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard return numLeadingZeroes; 444e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard} 445e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 446e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgardvoid MatroskaSource::clearPendingFrames() { 447e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard while (!mPendingFrames.empty()) { 448e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard MediaBuffer *frame = *mPendingFrames.begin(); 449e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard mPendingFrames.erase(mPendingFrames.begin()); 450e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 451e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard frame->release(); 452e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard frame = NULL; 453956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 454956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 455956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 456956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatus_t MatroskaSource::readBlock() { 457956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CHECK(mPendingFrames.empty()); 458956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 459956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (mBlockIter.eos()) { 460956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return ERROR_END_OF_STREAM; 461956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 462956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 463956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const mkvparser::Block *block = mBlockIter.block(); 464956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 465956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t timeUs = mBlockIter.blockTimeUs(); 466956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 467956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (int i = 0; i < block->GetFrameCount(); ++i) { 468956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const mkvparser::Block::Frame &frame = block->GetFrame(i); 469956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 470956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong MediaBuffer *mbuf = new MediaBuffer(frame.len); 471956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mbuf->meta_data()->setInt64(kKeyTime, timeUs); 472956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey()); 473e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 474e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data()); 475956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (n != 0) { 476956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mPendingFrames.clear(); 477956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 478b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard mBlockIter.advance(); 479956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return ERROR_IO; 480b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard } 481b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 482956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mPendingFrames.push_back(mbuf); 483956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 484956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 485956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mBlockIter.advance(); 486956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 487956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return OK; 488956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 489956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 490956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dongstatus_t MatroskaSource::read( 491b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard MediaBuffer **out, const ReadOptions *options) { 492956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *out = NULL; 493956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 494956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t targetSampleTimeUs = -1ll; 495b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 496956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t seekTimeUs; 497956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ReadOptions::SeekMode mode; 498956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (options && options->getSeekTo(&seekTimeUs, &mode) 499b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard && !mExtractor->isLiveStreaming()) { 500956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong clearPendingFrames(); 501956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 502956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // The audio we want is located by using the Cues to seek the video 503956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // stream to find the target Cluster then iterating to finalize for 504956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // audio. 505956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t actualFrameTimeUs; 506956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mBlockIter.seek(seekTimeUs, mIsAudio, &actualFrameTimeUs); 507b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 508956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (mode == ReadOptions::SEEK_CLOSEST) { 509b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard targetSampleTimeUs = actualFrameTimeUs; 510956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 511956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 512956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 513b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard while (mPendingFrames.empty()) { 514956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong status_t err = readBlock(); 515b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 516956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (err != OK) { 517956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong clearPendingFrames(); 518956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 519956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return err; 520956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 521956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 522b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 523956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong MediaBuffer *frame = *mPendingFrames.begin(); 524956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mPendingFrames.erase(mPendingFrames.begin()); 525e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 526e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard if (mType != AVC) { 527956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (targetSampleTimeUs >= 0ll) { 528b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard frame->meta_data()->setInt64( 529956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong kKeyTargetTime, targetSampleTimeUs); 530b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard } 531956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 532956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *out = frame; 533956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 534956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return OK; 535956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 536956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 537956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // Each input frame contains one or more NAL fragments, each fragment 538956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // is prefixed by mNALSizeLen bytes giving the fragment length, 539956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // followed by a corresponding number of bytes containing the fragment. 540956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // We output all these fragments into a single large buffer separated 541b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard // by startcodes (0x00 0x00 0x00 0x01). 542956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 543956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const uint8_t *srcPtr = 544956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (const uint8_t *)frame->data() + frame->range_offset(); 545956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 546956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong size_t srcSize = frame->range_length(); 547956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 548956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong size_t dstSize = 0; 549956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong MediaBuffer *buffer = NULL; 550956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong uint8_t *dstPtr = NULL; 551e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 552956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong for (int32_t pass = 0; pass < 2; ++pass) { 553b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard size_t srcOffset = 0; 554956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong size_t dstOffset = 0; 555b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard while (srcOffset + mNALSizeLen <= srcSize) { 556b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard size_t NALsize; 557956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong switch (mNALSizeLen) { 558b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard case 1: NALsize = srcPtr[srcOffset]; break; 559956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong case 2: NALsize = U16_AT(srcPtr + srcOffset); break; 560b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard case 3: NALsize = U24_AT(srcPtr + srcOffset); break; 561956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong case 4: NALsize = U32_AT(srcPtr + srcOffset); break; 562956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong default: 563956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong TRESPASS(); 564b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard } 565956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 566956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (srcOffset + mNALSizeLen + NALsize > srcSize) { 567956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong break; 568956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 569956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 570956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (pass == 1) { 571956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4); 572e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 573956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong memcpy(&dstPtr[dstOffset + 4], 574956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong &srcPtr[srcOffset + mNALSizeLen], 575956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong NALsize); 576956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 577956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 578956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong dstOffset += 4; // 0x00 00 00 01 579956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong dstOffset += NALsize; 580b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 581956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong srcOffset += mNALSizeLen + NALsize; 582956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 583956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 584956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (srcOffset < srcSize) { 585956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // There were trailing bytes or not enough data to complete 586956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong // a fragment. 587956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 588b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard frame->release(); 589956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong frame = NULL; 590b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 591956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return ERROR_MALFORMED; 592956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 593956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 594b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard if (pass == 0) { 595956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong dstSize = dstOffset; 596b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 597956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong buffer = new MediaBuffer(dstSize); 598956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 599956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int64_t timeUs; 600b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs)); 601956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong int32_t isSync; 602956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)); 603956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 604956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong buffer->meta_data()->setInt64(kKeyTime, timeUs); 605956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync); 606956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 607956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong dstPtr = (uint8_t *)buffer->data(); 608e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard } 609956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 610b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 611956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong frame->release(); 612b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard frame = NULL; 613956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 614956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (targetSampleTimeUs >= 0ll) { 615956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong buffer->meta_data()->setInt64( 616b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard kKeyTargetTime, targetSampleTimeUs); 617956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 618956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 619956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong *out = buffer; 620956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 621956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return OK; 622956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong} 623e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 624e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard//////////////////////////////////////////////////////////////////////////////// 625956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 626b676a05348e4c516fa8b57e33b10548e6142c3f8Mans RullgardMatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source) 627956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong : mDataSource(source), 628956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mReader(new DataSourceReader(mDataSource)), 629956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mSegment(NULL), 630956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mExtractedThumbnails(false), 631b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard mIsWebm(false) { 632956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong off64_t size; 633956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mIsLiveStreaming = 634956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong (mDataSource->flags() 635956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong & (DataSource::kWantsPrefetching 636b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard | DataSource::kIsCachingDataSource)) 637956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong && mDataSource->getSize(&size) != OK; 638956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 639b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard mkvparser::EBMLHeader ebmlHeader; 640b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard long long pos; 641956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ebmlHeader.Parse(mReader, pos) < 0) { 642956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return; 643956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 644b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 645b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) { 646956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mIsWebm = true; 647956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 648956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 649956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong long long ret = 650956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mkvparser::Segment::CreateInstance(mReader, pos, mSegment); 651956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 652956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ret) { 653e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK(mSegment == NULL); 654b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard return; 655956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 656956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 657956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong ret = mSegment->ParseHeaders(); 658956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong CHECK_EQ(ret, 0); 659e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 660e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard long len; 661e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard ret = mSegment->LoadCluster(pos, len); 662e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard CHECK_EQ(ret, 0); 663e2e838afcf03e603a41a0455846eaf9614537c16Mans Rullgard 664956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong if (ret < 0) { 665956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong delete mSegment; 666956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong mSegment = NULL; 667956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong return; 668956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong } 669b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard 670956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#if 0 671956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong const mkvparser::SegmentInfo *info = mSegment->GetInfo(); 672b676a05348e4c516fa8b57e33b10548e6142c3f8Mans Rullgard ALOGI("muxing app: %s, writing app: %s", 673956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong info->GetMuxingAppAsUTF8(), 674956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong info->GetWritingAppAsUTF8()); 675956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong#endif 676956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong 677956c553ab0ce72f8074ad0fda2ffd66a0305700cJames Dong addTracks(); 678} 679 680MatroskaExtractor::~MatroskaExtractor() { 681 delete mSegment; 682 mSegment = NULL; 683 684 delete mReader; 685 mReader = NULL; 686} 687 688size_t MatroskaExtractor::countTracks() { 689 return mTracks.size(); 690} 691 692sp<MediaSource> MatroskaExtractor::getTrack(size_t index) { 693 if (index >= mTracks.size()) { 694 return NULL; 695 } 696 697 return new MatroskaSource(this, index); 698} 699 700sp<MetaData> MatroskaExtractor::getTrackMetaData( 701 size_t index, uint32_t flags) { 702 if (index >= mTracks.size()) { 703 return NULL; 704 } 705 706 if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails 707 && !isLiveStreaming()) { 708 findThumbnails(); 709 mExtractedThumbnails = true; 710 } 711 712 return mTracks.itemAt(index).mMeta; 713} 714 715bool MatroskaExtractor::isLiveStreaming() const { 716 return mIsLiveStreaming; 717} 718 719static int bytesForSize(size_t size) { 720 // use at most 28 bits (4 times 7) 721 CHECK(size <= 0xfffffff); 722 723 if (size > 0x1fffff) { 724 return 4; 725 } else if (size > 0x3fff) { 726 return 3; 727 } else if (size > 0x7f) { 728 return 2; 729 } 730 return 1; 731} 732 733static void storeSize(uint8_t *data, size_t &idx, size_t size) { 734 int numBytes = bytesForSize(size); 735 idx += numBytes; 736 737 data += idx; 738 size_t next = 0; 739 while (numBytes--) { 740 *--data = (size & 0x7f) | next; 741 size >>= 7; 742 next = 0x80; 743 } 744} 745 746static void addESDSFromCodecPrivate( 747 const sp<MetaData> &meta, 748 bool isAudio, const void *priv, size_t privSize) { 749 750 int privSizeBytesRequired = bytesForSize(privSize); 751 int esdsSize2 = 14 + privSizeBytesRequired + privSize; 752 int esdsSize2BytesRequired = bytesForSize(esdsSize2); 753 int esdsSize1 = 4 + esdsSize2BytesRequired + esdsSize2; 754 int esdsSize1BytesRequired = bytesForSize(esdsSize1); 755 size_t esdsSize = 1 + esdsSize1BytesRequired + esdsSize1; 756 uint8_t *esds = new uint8_t[esdsSize]; 757 758 size_t idx = 0; 759 esds[idx++] = 0x03; 760 storeSize(esds, idx, esdsSize1); 761 esds[idx++] = 0x00; // ES_ID 762 esds[idx++] = 0x00; // ES_ID 763 esds[idx++] = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag 764 esds[idx++] = 0x04; 765 storeSize(esds, idx, esdsSize2); 766 esds[idx++] = isAudio ? 0x40 // Audio ISO/IEC 14496-3 767 : 0x20; // Visual ISO/IEC 14496-2 768 for (int i = 0; i < 12; i++) { 769 esds[idx++] = 0x00; 770 } 771 esds[idx++] = 0x05; 772 storeSize(esds, idx, privSize); 773 memcpy(esds + idx, priv, privSize); 774 775 meta->setData(kKeyESDS, 0, esds, esdsSize); 776 777 delete[] esds; 778 esds = NULL; 779} 780 781status_t addVorbisCodecInfo( 782 const sp<MetaData> &meta, 783 const void *_codecPrivate, size_t codecPrivateSize) { 784 // hexdump(_codecPrivate, codecPrivateSize); 785 786 if (codecPrivateSize < 1) { 787 return ERROR_MALFORMED; 788 } 789 790 const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate; 791 792 if (codecPrivate[0] != 0x02) { 793 return ERROR_MALFORMED; 794 } 795 796 // codecInfo starts with two lengths, len1 and len2, that are 797 // "Xiph-style-lacing encoded"... 798 799 size_t offset = 1; 800 size_t len1 = 0; 801 while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 802 len1 += 0xff; 803 ++offset; 804 } 805 if (offset >= codecPrivateSize) { 806 return ERROR_MALFORMED; 807 } 808 len1 += codecPrivate[offset++]; 809 810 size_t len2 = 0; 811 while (offset < codecPrivateSize && codecPrivate[offset] == 0xff) { 812 len2 += 0xff; 813 ++offset; 814 } 815 if (offset >= codecPrivateSize) { 816 return ERROR_MALFORMED; 817 } 818 len2 += codecPrivate[offset++]; 819 820 if (codecPrivateSize < offset + len1 + len2) { 821 return ERROR_MALFORMED; 822 } 823 824 if (codecPrivate[offset] != 0x01) { 825 return ERROR_MALFORMED; 826 } 827 meta->setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1); 828 829 offset += len1; 830 if (codecPrivate[offset] != 0x03) { 831 return ERROR_MALFORMED; 832 } 833 834 offset += len2; 835 if (codecPrivate[offset] != 0x05) { 836 return ERROR_MALFORMED; 837 } 838 839 meta->setData( 840 kKeyVorbisBooks, 0, &codecPrivate[offset], 841 codecPrivateSize - offset); 842 843 return OK; 844} 845 846void MatroskaExtractor::addTracks() { 847 const mkvparser::Tracks *tracks = mSegment->GetTracks(); 848 849 for (size_t index = 0; index < tracks->GetTracksCount(); ++index) { 850 const mkvparser::Track *track = tracks->GetTrackByIndex(index); 851 852 if (track == NULL) { 853 // Apparently this is currently valid (if unexpected) behaviour 854 // of the mkv parser lib. 855 continue; 856 } 857 858 const char *const codecID = track->GetCodecId(); 859 ALOGV("codec id = %s", codecID); 860 ALOGV("codec name = %s", track->GetCodecNameAsUTF8()); 861 862 size_t codecPrivateSize; 863 const unsigned char *codecPrivate = 864 track->GetCodecPrivate(codecPrivateSize); 865 866 enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 }; 867 868 sp<MetaData> meta = new MetaData; 869 870 status_t err = OK; 871 872 switch (track->GetType()) { 873 case VIDEO_TRACK: 874 { 875 const mkvparser::VideoTrack *vtrack = 876 static_cast<const mkvparser::VideoTrack *>(track); 877 878 if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { 879 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 880 meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); 881 } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) { 882 if (codecPrivateSize > 0) { 883 meta->setCString( 884 kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 885 addESDSFromCodecPrivate( 886 meta, false, codecPrivate, codecPrivateSize); 887 } else { 888 ALOGW("%s is detected, but does not have configuration.", 889 codecID); 890 continue; 891 } 892 } else if (!strcmp("V_VP8", codecID)) { 893 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8); 894 } else if (!strcmp("V_VP9", codecID)) { 895 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9); 896 } else { 897 ALOGW("%s is not supported.", codecID); 898 continue; 899 } 900 901 meta->setInt32(kKeyWidth, vtrack->GetWidth()); 902 meta->setInt32(kKeyHeight, vtrack->GetHeight()); 903 break; 904 } 905 906 case AUDIO_TRACK: 907 { 908 const mkvparser::AudioTrack *atrack = 909 static_cast<const mkvparser::AudioTrack *>(track); 910 911 if (!strcmp("A_AAC", codecID)) { 912 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); 913 CHECK(codecPrivateSize >= 2); 914 915 addESDSFromCodecPrivate( 916 meta, true, codecPrivate, codecPrivateSize); 917 } else if (!strcmp("A_VORBIS", codecID)) { 918 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 919 920 err = addVorbisCodecInfo( 921 meta, codecPrivate, codecPrivateSize); 922 } else if (!strcmp("A_MPEG/L3", codecID)) { 923 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 924 } else { 925 ALOGW("%s is not supported.", codecID); 926 continue; 927 } 928 929 meta->setInt32(kKeySampleRate, atrack->GetSamplingRate()); 930 meta->setInt32(kKeyChannelCount, atrack->GetChannels()); 931 break; 932 } 933 934 default: 935 continue; 936 } 937 938 if (err != OK) { 939 ALOGE("skipping track, codec specific data was malformed."); 940 continue; 941 } 942 943 long long durationNs = mSegment->GetDuration(); 944 meta->setInt64(kKeyDuration, (durationNs + 500) / 1000); 945 946 mTracks.push(); 947 TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1); 948 trackInfo->mTrackNum = track->GetNumber(); 949 trackInfo->mMeta = meta; 950 } 951} 952 953void MatroskaExtractor::findThumbnails() { 954 for (size_t i = 0; i < mTracks.size(); ++i) { 955 TrackInfo *info = &mTracks.editItemAt(i); 956 957 const char *mime; 958 CHECK(info->mMeta->findCString(kKeyMIMEType, &mime)); 959 960 if (strncasecmp(mime, "video/", 6)) { 961 continue; 962 } 963 964 BlockIterator iter(this, info->mTrackNum); 965 int32_t j = 0; 966 int64_t thumbnailTimeUs = 0; 967 size_t maxBlockSize = 0; 968 while (!iter.eos() && j < 20) { 969 if (iter.block()->IsKey()) { 970 ++j; 971 972 size_t blockSize = 0; 973 for (int k = 0; k < iter.block()->GetFrameCount(); ++k) { 974 blockSize += iter.block()->GetFrame(k).len; 975 } 976 977 if (blockSize > maxBlockSize) { 978 maxBlockSize = blockSize; 979 thumbnailTimeUs = iter.blockTimeUs(); 980 } 981 } 982 iter.advance(); 983 } 984 info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 985 } 986} 987 988sp<MetaData> MatroskaExtractor::getMetaData() { 989 sp<MetaData> meta = new MetaData; 990 991 meta->setCString( 992 kKeyMIMEType, 993 mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA); 994 995 return meta; 996} 997 998uint32_t MatroskaExtractor::flags() const { 999 uint32_t x = CAN_PAUSE; 1000 if (!isLiveStreaming()) { 1001 x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK; 1002 } 1003 1004 return x; 1005} 1006 1007bool SniffMatroska( 1008 const sp<DataSource> &source, String8 *mimeType, float *confidence, 1009 sp<AMessage> *) { 1010 DataSourceReader reader(source); 1011 mkvparser::EBMLHeader ebmlHeader; 1012 long long pos; 1013 if (ebmlHeader.Parse(&reader, pos) < 0) { 1014 return false; 1015 } 1016 1017 mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA); 1018 *confidence = 0.6; 1019 1020 return true; 1021} 1022 1023} // namespace android 1024