1cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber/* 2cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * Copyright (C) 2010 The Android Open Source Project 3cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * 4cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * you may not use this file except in compliance with the License. 6cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * You may obtain a copy of the License at 7cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * 8cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * 10cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * Unless required by applicable law or agreed to in writing, software 11cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * See the License for the specific language governing permissions and 14cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber * limitations under the License. 15cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber */ 16cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 17cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber//#define LOG_NDEBUG 0 18cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#define LOG_TAG "MPEG2TSExtractor" 19f748dd8cac87ef0bd1deb78a6c8c71e5a9bbe36bJaesung Chung 20f748dd8cac87ef0bd1deb78a6c8c71e5a9bbe36bJaesung Chung#include <inttypes.h> 21cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <utils/Log.h> 22cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 2375226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen#include "MPEG2TSExtractor.h" 24cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 252a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen#include <media/DataSourceBase.h> 26d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/IStreamSource.h> 273d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen#include <media/MediaTrack.h> 28540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim#include <media/stagefright/foundation/ABuffer.h> 29f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h> 3012a3d2f50dc52d8d05f5d0e932445f368248f520Jaesung Chung#include <media/stagefright/foundation/ALooper.h> 3182e147049625a4cfdcb228a1de7efda594d446c9Robert Shih#include <media/stagefright/foundation/AUtils.h> 3215d02f84351eaca14099bde11cfbf6f124bea71fDongwon Kang#include <media/stagefright/foundation/MediaKeys.h> 33cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MediaDefs.h> 34cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MediaErrors.h> 35cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MetaData.h> 36cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <utils/String8.h> 37cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 3875226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen#include "mpeg2ts/AnotherPacketSource.h" 3975226177f20a176d50e3e53bbb34067cb49112c3Marco Nelissen#include "mpeg2ts/ATSParser.h" 40cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 41d5a416a49d5074e2966f5fe255561cbaaf31a325Chong Zhang#include <hidl/HybridInterface.h> 42d5a416a49d5074e2966f5fe255561cbaaf31a325Chong Zhang#include <android/hardware/cas/1.0/ICas.h> 43d5a416a49d5074e2966f5fe255561cbaaf31a325Chong Zhang 44cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubernamespace android { 45cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 46d5a416a49d5074e2966f5fe255561cbaaf31a325Chong Zhangusing hardware::cas::V1_0::ICas; 47d5a416a49d5074e2966f5fe255561cbaaf31a325Chong Zhang 480da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huberstatic const size_t kTSPacketSize = 188; 4982e147049625a4cfdcb228a1de7efda594d446c9Robert Shihstatic const int kMaxDurationReadSize = 250000LL; 5082e147049625a4cfdcb228a1de7efda594d446c9Robert Shihstatic const int kMaxDurationRetry = 6; 510da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber 523d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstruct MPEG2TSSource : public MediaTrack { 53cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber MPEG2TSSource( 547d880c31d2079299000b036c6ae742dc695a5b19Marco Nelissen MPEG2TSExtractor *extractor, 55bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber const sp<AnotherPacketSource> &impl, 56540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim bool doesSeek); 577d880c31d2079299000b036c6ae742dc695a5b19Marco Nelissen virtual ~MPEG2TSSource(); 58cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 593d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen virtual status_t start(MetaDataBase *params = NULL); 60cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber virtual status_t stop(); 613d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen virtual status_t getFormat(MetaDataBase &); 62cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 63cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber virtual status_t read( 641889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang MediaBufferBase **buffer, const ReadOptions *options = NULL); 65cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 66cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberprivate: 677d880c31d2079299000b036c6ae742dc695a5b19Marco Nelissen MPEG2TSExtractor *mExtractor; 68cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber sp<AnotherPacketSource> mImpl; 69cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 70bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber // If there are both audio and video streams, only the video stream 71540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // will signal seek on the extractor; otherwise the single stream will seek. 72540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim bool mDoesSeek; 73bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber 74cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSSource); 75cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}; 76cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 77cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas HuberMPEG2TSSource::MPEG2TSSource( 787d880c31d2079299000b036c6ae742dc695a5b19Marco Nelissen MPEG2TSExtractor *extractor, 79bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber const sp<AnotherPacketSource> &impl, 80540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim bool doesSeek) 81cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber : mExtractor(extractor), 82bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber mImpl(impl), 83540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim mDoesSeek(doesSeek) { 84cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 85cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 867d880c31d2079299000b036c6ae742dc695a5b19Marco NelissenMPEG2TSSource::~MPEG2TSSource() { 877d880c31d2079299000b036c6ae742dc695a5b19Marco Nelissen} 887d880c31d2079299000b036c6ae742dc695a5b19Marco Nelissen 893d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t MPEG2TSSource::start(MetaDataBase *) { 903d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen return mImpl->start(NULL); // AnotherPacketSource::start() doesn't use its argument 91cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 92cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 93cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstatus_t MPEG2TSSource::stop() { 94cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return mImpl->stop(); 95cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 96cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 973d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t MPEG2TSSource::getFormat(MetaDataBase &meta) { 983d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen sp<MetaData> implMeta = mImpl->getFormat(); 993d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen meta = *implMeta; 1003d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen return OK; 101cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 102cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 103cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstatus_t MPEG2TSSource::read( 1041889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang MediaBufferBase **out, const ReadOptions *options) { 105cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber *out = NULL; 106cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 107540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t seekTimeUs; 108540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ReadOptions::SeekMode seekMode; 109540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (mDoesSeek && options && options->getSeekTo(&seekTimeUs, &seekMode)) { 110540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // seek is needed 111540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err = mExtractor->seek(seekTimeUs, seekMode); 112cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber if (err != OK) { 113540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 114cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 115cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 116cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 117540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (mExtractor->feedUntilBufferAvailable(mImpl) != OK) { 118540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return ERROR_END_OF_STREAM; 1195d7c3eef1985ff15a56920c548cc4e41d6c9627aMarco Nelissen } 1205d7c3eef1985ff15a56920c548cc4e41d6c9627aMarco Nelissen 121cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return mImpl->read(out, options); 122cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 123cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 124cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber//////////////////////////////////////////////////////////////////////////////// 125cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 1262a243f08193fe9ff1afe018e9953f01c44ced9deMarco NelissenMPEG2TSExtractor::MPEG2TSExtractor(DataSourceBase *source) 127cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber : mDataSource(source), 128cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber mParser(new ATSParser), 1299558f6dd733dc450270f38b9a139d384d273ce0aWei Jia mLastSyncEvent(0), 130cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber mOffset(0) { 131cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber init(); 132cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 133cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 134cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersize_t MPEG2TSExtractor::countTracks() { 135cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return mSourceImpls.size(); 136cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 137cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 1383d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco NelissenMediaTrack *MPEG2TSExtractor::getTrack(size_t index) { 139cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber if (index >= mSourceImpls.size()) { 140cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return NULL; 141cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 142cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 143540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // The seek reference track (video if present; audio otherwise) performs 144540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // seek requests, while other tracks ignore requests. 145540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return new MPEG2TSSource(this, mSourceImpls.editItemAt(index), 146540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim (mSeekSyncPoints == &mSyncPoints.editItemAt(index))); 147cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 148cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 1493d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t MPEG2TSExtractor::getTrackMetaData( 1503d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen MetaDataBase &meta, 151d411b4ca2945cd8974a3a78199fce94646950128Andreas Huber size_t index, uint32_t /* flags */) { 1523d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen sp<MetaData> implMeta = index < mSourceImpls.size() 153cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber ? mSourceImpls.editItemAt(index)->getFormat() : NULL; 1543d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen if (implMeta == NULL) { 1553d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen return UNKNOWN_ERROR; 1563d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen } 1573d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen meta = *implMeta; 1583d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen return OK; 159cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 160cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 1613d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenstatus_t MPEG2TSExtractor::getMetaData(MetaDataBase &meta) { 1623d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 163cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 1643d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen return OK; 165cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 166cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 1673b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang//static 1683d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissenbool MPEG2TSExtractor::isScrambledFormat(MetaDataBase &format) { 1693b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang const char *mime; 1703d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen return format.findCString(kKeyMIMEType, &mime) 1713b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang && (!strcasecmp(MEDIA_MIMETYPE_VIDEO_SCRAMBLED, mime) 1723b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang || !strcasecmp(MEDIA_MIMETYPE_AUDIO_SCRAMBLED, mime)); 1733b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 1743b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 175d23ab3ae2248781640e9a10659c9ad0a78941accDongwon Kangstatus_t MPEG2TSExtractor::setMediaCas(const uint8_t* casToken, size_t size) { 176d5a416a49d5074e2966f5fe255561cbaaf31a325Chong Zhang HalToken halToken; 177d23ab3ae2248781640e9a10659c9ad0a78941accDongwon Kang halToken.setToExternal((uint8_t*)casToken, size); 178d5a416a49d5074e2966f5fe255561cbaaf31a325Chong Zhang sp<ICas> cas = ICas::castFrom(retrieveHalInterface(halToken)); 1793b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGD("setMediaCas: %p", cas.get()); 1803b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1813b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang status_t err = mParser->setMediaCas(cas); 1823b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (err == OK) { 1833b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGI("All tracks now have descramblers"); 1843b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang init(); 1853b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1863b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return err; 1873b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 1883b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1893b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangvoid MPEG2TSExtractor::addSource(const sp<AnotherPacketSource> &impl) { 1903b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang bool found = false; 1913b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang for (size_t i = 0; i < mSourceImpls.size(); i++) { 1923b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (mSourceImpls[i] == impl) { 1933b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang found = true; 1943b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang break; 1953b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1963b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1973b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (!found) { 1983b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mSourceImpls.push(impl); 1993b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2003b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 2013b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 202cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubervoid MPEG2TSExtractor::init() { 203cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber bool haveAudio = false; 204cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber bool haveVideo = false; 20512a3d2f50dc52d8d05f5d0e932445f368248f520Jaesung Chung int64_t startTime = ALooper::GetNowUs(); 206cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 2073b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang status_t err; 2083b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang while ((err = feedMore(true /* isInit */)) == OK 2093b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang || err == ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED) { 210cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber if (haveAudio && haveVideo) { 2119558f6dd733dc450270f38b9a139d384d273ce0aWei Jia addSyncPoint_l(mLastSyncEvent); 2129558f6dd733dc450270f38b9a139d384d273ce0aWei Jia mLastSyncEvent.reset(); 213cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber break; 214cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 2150da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (!haveVideo) { 21645d54c6ec48761b75f92cee4618c4fbffa6be24aMarco Nelissen sp<AnotherPacketSource> impl = mParser->getSource(ATSParser::VIDEO); 2170da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber 2180da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (impl != NULL) { 2193b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang sp<MetaData> format = impl->getFormat(); 2203b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (format != NULL) { 2213b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang haveVideo = true; 2223b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang addSource(impl); 2233d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen if (!isScrambledFormat(*(format.get()))) { 2243b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mSyncPoints.push(); 2253b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mSeekSyncPoints = &mSyncPoints.editTop(); 2263b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2273b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2280da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber } 229cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 230cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 2310da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (!haveAudio) { 23245d54c6ec48761b75f92cee4618c4fbffa6be24aMarco Nelissen sp<AnotherPacketSource> impl = mParser->getSource(ATSParser::AUDIO); 2330da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber 2340da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (impl != NULL) { 2353b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang sp<MetaData> format = impl->getFormat(); 2363b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (format != NULL) { 2373b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang haveAudio = true; 2383b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang addSource(impl); 2393d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen if (!isScrambledFormat(*(format.get()))) { 2403b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mSyncPoints.push(); 2413b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (!haveVideo) { 2423b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mSeekSyncPoints = &mSyncPoints.editTop(); 2433b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2443b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 245540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 246cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 2470da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber } 2480da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber 2499558f6dd733dc450270f38b9a139d384d273ce0aWei Jia addSyncPoint_l(mLastSyncEvent); 2509558f6dd733dc450270f38b9a139d384d273ce0aWei Jia mLastSyncEvent.reset(); 2519558f6dd733dc450270f38b9a139d384d273ce0aWei Jia 2523b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang // ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED is returned when the mpeg2ts 2533b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang // is scrambled but we don't have a MediaCas object set. The extraction 2543b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang // will only continue when setMediaCas() is called successfully. 2553b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (err == ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED) { 2563b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGI("stopped parsing scrambled content, " 2573b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang "haveAudio=%d, haveVideo=%d, elaspedTime=%" PRId64, 2583b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang haveAudio, haveVideo, ALooper::GetNowUs() - startTime); 2593b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return; 2603b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2613b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 26212a3d2f50dc52d8d05f5d0e932445f368248f520Jaesung Chung // Wait only for 2 seconds to detect audio/video streams. 26312a3d2f50dc52d8d05f5d0e932445f368248f520Jaesung Chung if (ALooper::GetNowUs() - startTime > 2000000ll) { 2640da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber break; 265cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 266cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 267cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 268540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim off64_t size; 269540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (mDataSource->getSize(&size) == OK && (haveAudio || haveVideo)) { 270540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim sp<AnotherPacketSource> impl = haveVideo 27145d54c6ec48761b75f92cee4618c4fbffa6be24aMarco Nelissen ? mParser->getSource(ATSParser::VIDEO) 27245d54c6ec48761b75f92cee4618c4fbffa6be24aMarco Nelissen : mParser->getSource(ATSParser::AUDIO); 2733d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim size_t prevSyncSize = 1; 274540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t durationUs = -1; 275540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim List<int64_t> durations; 276540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // Estimate duration --- stabilize until you get <500ms deviation. 2773d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim while (feedMore() == OK 2783d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim && ALooper::GetNowUs() - startTime <= 2000000ll) { 2793d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim if (mSeekSyncPoints->size() > prevSyncSize) { 2803d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim prevSyncSize = mSeekSyncPoints->size(); 2813d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim int64_t diffUs = mSeekSyncPoints->keyAt(prevSyncSize - 1) 2823d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim - mSeekSyncPoints->keyAt(0); 2833d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim off64_t diffOffset = mSeekSyncPoints->valueAt(prevSyncSize - 1) 2843d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim - mSeekSyncPoints->valueAt(0); 2850d6c24d4bd42c279af02825f09436e9c3a9cc84fWonsik Kim int64_t currentDurationUs = size * diffUs / diffOffset; 2860d6c24d4bd42c279af02825f09436e9c3a9cc84fWonsik Kim durations.push_back(currentDurationUs); 287540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (durations.size() > 5) { 288540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim durations.erase(durations.begin()); 289540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t min = *durations.begin(); 290540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t max = *durations.begin(); 2910d6c24d4bd42c279af02825f09436e9c3a9cc84fWonsik Kim for (auto duration : durations) { 2920d6c24d4bd42c279af02825f09436e9c3a9cc84fWonsik Kim if (min > duration) { 2930d6c24d4bd42c279af02825f09436e9c3a9cc84fWonsik Kim min = duration; 294540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 2950d6c24d4bd42c279af02825f09436e9c3a9cc84fWonsik Kim if (max < duration) { 2960d6c24d4bd42c279af02825f09436e9c3a9cc84fWonsik Kim max = duration; 297540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 298540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 299540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (max - min < 500 * 1000) { 3000d6c24d4bd42c279af02825f09436e9c3a9cc84fWonsik Kim durationUs = currentDurationUs; 301540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim break; 302540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 303540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 304540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 305540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 3063d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim status_t err; 3073d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim int64_t bufferedDurationUs; 3083d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim bufferedDurationUs = impl->getBufferedDurationUs(&err); 3093d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim if (err == ERROR_END_OF_STREAM) { 3103d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim durationUs = bufferedDurationUs; 3113d83a2089f7000180a1a3ff5a9d376efe92f596cWonsik Kim } 312540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (durationUs > 0) { 313540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim const sp<MetaData> meta = impl->getFormat(); 314540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim meta->setInt64(kKeyDuration, durationUs); 315540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim impl->setFormat(meta); 31682e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } else { 31782e147049625a4cfdcb228a1de7efda594d446c9Robert Shih estimateDurationsFromTimesUsAtEnd(); 318540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 319540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 320540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 321f748dd8cac87ef0bd1deb78a6c8c71e5a9bbe36bJaesung Chung ALOGI("haveAudio=%d, haveVideo=%d, elaspedTime=%" PRId64, 32212a3d2f50dc52d8d05f5d0e932445f368248f520Jaesung Chung haveAudio, haveVideo, ALooper::GetNowUs() - startTime); 323cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 324cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 3259558f6dd733dc450270f38b9a139d384d273ce0aWei Jiastatus_t MPEG2TSExtractor::feedMore(bool isInit) { 326cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber Mutex::Autolock autoLock(mLock); 327cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 328cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber uint8_t packet[kTSPacketSize]; 329cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize); 330cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 331ed8d14f6a934072cd012992c4ef16990a54baa9aAndreas Huber if (n < (ssize_t)kTSPacketSize) { 332be9634d071e79b72a42a4504f64eda9e2a0bceb8Marco Nelissen if (n >= 0) { 333be9634d071e79b72a42a4504f64eda9e2a0bceb8Marco Nelissen mParser->signalEOS(ERROR_END_OF_STREAM); 334be9634d071e79b72a42a4504f64eda9e2a0bceb8Marco Nelissen } 335cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM; 336cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 337cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 338540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ATSParser::SyncEvent event(mOffset); 3392a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber mOffset += n; 340540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err = mParser->feedTSPacket(packet, kTSPacketSize, &event); 3419558f6dd733dc450270f38b9a139d384d273ce0aWei Jia if (event.hasReturnedData()) { 3429558f6dd733dc450270f38b9a139d384d273ce0aWei Jia if (isInit) { 3439558f6dd733dc450270f38b9a139d384d273ce0aWei Jia mLastSyncEvent = event; 3449558f6dd733dc450270f38b9a139d384d273ce0aWei Jia } else { 3459558f6dd733dc450270f38b9a139d384d273ce0aWei Jia addSyncPoint_l(event); 3469558f6dd733dc450270f38b9a139d384d273ce0aWei Jia } 3479558f6dd733dc450270f38b9a139d384d273ce0aWei Jia } 3489558f6dd733dc450270f38b9a139d384d273ce0aWei Jia return err; 3499558f6dd733dc450270f38b9a139d384d273ce0aWei Jia} 3509558f6dd733dc450270f38b9a139d384d273ce0aWei Jia 3519558f6dd733dc450270f38b9a139d384d273ce0aWei Jiavoid MPEG2TSExtractor::addSyncPoint_l(const ATSParser::SyncEvent &event) { 3529558f6dd733dc450270f38b9a139d384d273ce0aWei Jia if (!event.hasReturnedData()) { 3539558f6dd733dc450270f38b9a139d384d273ce0aWei Jia return; 3549558f6dd733dc450270f38b9a139d384d273ce0aWei Jia } 3559558f6dd733dc450270f38b9a139d384d273ce0aWei Jia 3569558f6dd733dc450270f38b9a139d384d273ce0aWei Jia for (size_t i = 0; i < mSourceImpls.size(); ++i) { 3579558f6dd733dc450270f38b9a139d384d273ce0aWei Jia if (mSourceImpls[i].get() == event.getMediaSource().get()) { 3589558f6dd733dc450270f38b9a139d384d273ce0aWei Jia KeyedVector<int64_t, off64_t> *syncPoints = &mSyncPoints.editItemAt(i); 3599558f6dd733dc450270f38b9a139d384d273ce0aWei Jia syncPoints->add(event.getTimeUs(), event.getOffset()); 3609558f6dd733dc450270f38b9a139d384d273ce0aWei Jia // We're keeping the size of the sync points at most 5mb per a track. 3619558f6dd733dc450270f38b9a139d384d273ce0aWei Jia size_t size = syncPoints->size(); 3629558f6dd733dc450270f38b9a139d384d273ce0aWei Jia if (size >= 327680) { 3639558f6dd733dc450270f38b9a139d384d273ce0aWei Jia int64_t firstTimeUs = syncPoints->keyAt(0); 3649558f6dd733dc450270f38b9a139d384d273ce0aWei Jia int64_t lastTimeUs = syncPoints->keyAt(size - 1); 3659558f6dd733dc450270f38b9a139d384d273ce0aWei Jia if (event.getTimeUs() - firstTimeUs > lastTimeUs - event.getTimeUs()) { 3669558f6dd733dc450270f38b9a139d384d273ce0aWei Jia syncPoints->removeItemsAt(0, 4096); 3679558f6dd733dc450270f38b9a139d384d273ce0aWei Jia } else { 3689558f6dd733dc450270f38b9a139d384d273ce0aWei Jia syncPoints->removeItemsAt(size - 4096, 4096); 369faf755df5654c6ea0080e2af39c3d6810c0a2f14Jaesung Chung } 370540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 3719558f6dd733dc450270f38b9a139d384d273ce0aWei Jia break; 372540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 373540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 374cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 375cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 37682e147049625a4cfdcb228a1de7efda594d446c9Robert Shihstatus_t MPEG2TSExtractor::estimateDurationsFromTimesUsAtEnd() { 3772a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen if (!(mDataSource->flags() & DataSourceBase::kIsLocalFileSource)) { 37882e147049625a4cfdcb228a1de7efda594d446c9Robert Shih return ERROR_UNSUPPORTED; 37982e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 38082e147049625a4cfdcb228a1de7efda594d446c9Robert Shih 38182e147049625a4cfdcb228a1de7efda594d446c9Robert Shih off64_t size = 0; 38282e147049625a4cfdcb228a1de7efda594d446c9Robert Shih status_t err = mDataSource->getSize(&size); 38382e147049625a4cfdcb228a1de7efda594d446c9Robert Shih if (err != OK) { 38482e147049625a4cfdcb228a1de7efda594d446c9Robert Shih return err; 38582e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 38682e147049625a4cfdcb228a1de7efda594d446c9Robert Shih 38782e147049625a4cfdcb228a1de7efda594d446c9Robert Shih uint8_t packet[kTSPacketSize]; 38882e147049625a4cfdcb228a1de7efda594d446c9Robert Shih const off64_t zero = 0; 38982e147049625a4cfdcb228a1de7efda594d446c9Robert Shih off64_t offset = max(zero, size - kMaxDurationReadSize); 39082e147049625a4cfdcb228a1de7efda594d446c9Robert Shih if (mDataSource->readAt(offset, &packet, 0) < 0) { 39182e147049625a4cfdcb228a1de7efda594d446c9Robert Shih return ERROR_IO; 39282e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 39382e147049625a4cfdcb228a1de7efda594d446c9Robert Shih 39482e147049625a4cfdcb228a1de7efda594d446c9Robert Shih int retry = 0; 39582e147049625a4cfdcb228a1de7efda594d446c9Robert Shih bool allDurationsFound = false; 39682e147049625a4cfdcb228a1de7efda594d446c9Robert Shih int64_t timeAnchorUs = mParser->getFirstPTSTimeUs(); 39782e147049625a4cfdcb228a1de7efda594d446c9Robert Shih do { 39882e147049625a4cfdcb228a1de7efda594d446c9Robert Shih int bytesRead = 0; 39982e147049625a4cfdcb228a1de7efda594d446c9Robert Shih sp<ATSParser> parser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE); 40082e147049625a4cfdcb228a1de7efda594d446c9Robert Shih ATSParser::SyncEvent ev(0); 40182e147049625a4cfdcb228a1de7efda594d446c9Robert Shih offset = max(zero, size - (kMaxDurationReadSize << retry)); 40282e147049625a4cfdcb228a1de7efda594d446c9Robert Shih offset = (offset / kTSPacketSize) * kTSPacketSize; 40382e147049625a4cfdcb228a1de7efda594d446c9Robert Shih for (;;) { 40482e147049625a4cfdcb228a1de7efda594d446c9Robert Shih if (bytesRead >= kMaxDurationReadSize << max(0, retry - 1)) { 40582e147049625a4cfdcb228a1de7efda594d446c9Robert Shih break; 40682e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 40782e147049625a4cfdcb228a1de7efda594d446c9Robert Shih 40882e147049625a4cfdcb228a1de7efda594d446c9Robert Shih ssize_t n = mDataSource->readAt(offset, packet, kTSPacketSize); 40982e147049625a4cfdcb228a1de7efda594d446c9Robert Shih if (n < 0) { 41082e147049625a4cfdcb228a1de7efda594d446c9Robert Shih return n; 41182e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } else if (n < (ssize_t)kTSPacketSize) { 41282e147049625a4cfdcb228a1de7efda594d446c9Robert Shih break; 41382e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 41482e147049625a4cfdcb228a1de7efda594d446c9Robert Shih 41582e147049625a4cfdcb228a1de7efda594d446c9Robert Shih offset += kTSPacketSize; 41682e147049625a4cfdcb228a1de7efda594d446c9Robert Shih bytesRead += kTSPacketSize; 41782e147049625a4cfdcb228a1de7efda594d446c9Robert Shih err = parser->feedTSPacket(packet, kTSPacketSize, &ev); 41882e147049625a4cfdcb228a1de7efda594d446c9Robert Shih if (err != OK) { 41982e147049625a4cfdcb228a1de7efda594d446c9Robert Shih return err; 42082e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 42182e147049625a4cfdcb228a1de7efda594d446c9Robert Shih 42282e147049625a4cfdcb228a1de7efda594d446c9Robert Shih if (ev.hasReturnedData()) { 42382e147049625a4cfdcb228a1de7efda594d446c9Robert Shih int64_t durationUs = ev.getTimeUs(); 42482e147049625a4cfdcb228a1de7efda594d446c9Robert Shih ATSParser::SourceType type = ev.getType(); 42582e147049625a4cfdcb228a1de7efda594d446c9Robert Shih ev.reset(); 42682e147049625a4cfdcb228a1de7efda594d446c9Robert Shih 42782e147049625a4cfdcb228a1de7efda594d446c9Robert Shih int64_t firstTimeUs; 42845d54c6ec48761b75f92cee4618c4fbffa6be24aMarco Nelissen sp<AnotherPacketSource> src = mParser->getSource(type); 42982e147049625a4cfdcb228a1de7efda594d446c9Robert Shih if (src == NULL || src->nextBufferTime(&firstTimeUs) != OK) { 43082e147049625a4cfdcb228a1de7efda594d446c9Robert Shih continue; 43182e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 43282e147049625a4cfdcb228a1de7efda594d446c9Robert Shih durationUs += src->getEstimatedBufferDurationUs(); 43382e147049625a4cfdcb228a1de7efda594d446c9Robert Shih durationUs -= timeAnchorUs; 43482e147049625a4cfdcb228a1de7efda594d446c9Robert Shih durationUs -= firstTimeUs; 43582e147049625a4cfdcb228a1de7efda594d446c9Robert Shih if (durationUs > 0) { 43682e147049625a4cfdcb228a1de7efda594d446c9Robert Shih int64_t origDurationUs, lastDurationUs; 43782e147049625a4cfdcb228a1de7efda594d446c9Robert Shih const sp<MetaData> meta = src->getFormat(); 43882e147049625a4cfdcb228a1de7efda594d446c9Robert Shih const uint32_t kKeyLastDuration = 'ldur'; 43982e147049625a4cfdcb228a1de7efda594d446c9Robert Shih // Require two consecutive duration calculations to be within 1 sec before 44082e147049625a4cfdcb228a1de7efda594d446c9Robert Shih // updating; use MetaData to store previous duration estimate in per-stream 44182e147049625a4cfdcb228a1de7efda594d446c9Robert Shih // context. 44282e147049625a4cfdcb228a1de7efda594d446c9Robert Shih if (!meta->findInt64(kKeyDuration, &origDurationUs) 44382e147049625a4cfdcb228a1de7efda594d446c9Robert Shih || !meta->findInt64(kKeyLastDuration, &lastDurationUs) 44482e147049625a4cfdcb228a1de7efda594d446c9Robert Shih || (origDurationUs < durationUs 44582e147049625a4cfdcb228a1de7efda594d446c9Robert Shih && abs(durationUs - lastDurationUs) < 60000000)) { 44682e147049625a4cfdcb228a1de7efda594d446c9Robert Shih meta->setInt64(kKeyDuration, durationUs); 44782e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 44882e147049625a4cfdcb228a1de7efda594d446c9Robert Shih meta->setInt64(kKeyLastDuration, durationUs); 44982e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 45082e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 45182e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 45282e147049625a4cfdcb228a1de7efda594d446c9Robert Shih 45382e147049625a4cfdcb228a1de7efda594d446c9Robert Shih if (!allDurationsFound) { 45482e147049625a4cfdcb228a1de7efda594d446c9Robert Shih allDurationsFound = true; 45582e147049625a4cfdcb228a1de7efda594d446c9Robert Shih for (auto t: {ATSParser::VIDEO, ATSParser::AUDIO}) { 45645d54c6ec48761b75f92cee4618c4fbffa6be24aMarco Nelissen sp<AnotherPacketSource> src = mParser->getSource(t); 45782e147049625a4cfdcb228a1de7efda594d446c9Robert Shih if (src == NULL) { 45882e147049625a4cfdcb228a1de7efda594d446c9Robert Shih continue; 45982e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 46082e147049625a4cfdcb228a1de7efda594d446c9Robert Shih int64_t durationUs; 46182e147049625a4cfdcb228a1de7efda594d446c9Robert Shih const sp<MetaData> meta = src->getFormat(); 46282e147049625a4cfdcb228a1de7efda594d446c9Robert Shih if (!meta->findInt64(kKeyDuration, &durationUs)) { 46382e147049625a4cfdcb228a1de7efda594d446c9Robert Shih allDurationsFound = false; 46482e147049625a4cfdcb228a1de7efda594d446c9Robert Shih break; 46582e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 46682e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 46782e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } 46882e147049625a4cfdcb228a1de7efda594d446c9Robert Shih 46982e147049625a4cfdcb228a1de7efda594d446c9Robert Shih ++retry; 47082e147049625a4cfdcb228a1de7efda594d446c9Robert Shih } while(!allDurationsFound && offset > 0 && retry <= kMaxDurationRetry); 47182e147049625a4cfdcb228a1de7efda594d446c9Robert Shih 47282e147049625a4cfdcb228a1de7efda594d446c9Robert Shih return allDurationsFound? OK : ERROR_UNSUPPORTED; 47382e147049625a4cfdcb228a1de7efda594d446c9Robert Shih} 47482e147049625a4cfdcb228a1de7efda594d446c9Robert Shih 475bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huberuint32_t MPEG2TSExtractor::flags() const { 476540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return CAN_PAUSE | CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD; 477540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim} 478540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 479540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kimstatus_t MPEG2TSExtractor::seek(int64_t seekTimeUs, 4803d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen const MediaTrack::ReadOptions::SeekMode &seekMode) { 481540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (mSeekSyncPoints == NULL || mSeekSyncPoints->isEmpty()) { 482540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ALOGW("No sync point to seek to."); 483540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // ... and therefore we have nothing useful to do here. 484540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return OK; 485540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 486540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 487540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // Determine whether we're seeking beyond the known area. 488540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim bool shouldSeekBeyond = 489540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim (seekTimeUs > mSeekSyncPoints->keyAt(mSeekSyncPoints->size() - 1)); 490540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 491540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // Determine the sync point to seek. 492540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim size_t index = 0; 493540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim for (; index < mSeekSyncPoints->size(); ++index) { 494540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t timeUs = mSeekSyncPoints->keyAt(index); 495540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (timeUs > seekTimeUs) { 496540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim break; 497540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 498540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 499540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 500540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim switch (seekMode) { 5013d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen case MediaTrack::ReadOptions::SEEK_NEXT_SYNC: 502540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (index == mSeekSyncPoints->size()) { 503540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ALOGW("Next sync not found; starting from the latest sync."); 504540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim --index; 505540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 506540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim break; 5073d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen case MediaTrack::ReadOptions::SEEK_CLOSEST_SYNC: 5083d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen case MediaTrack::ReadOptions::SEEK_CLOSEST: 509540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ALOGW("seekMode not supported: %d; falling back to PREVIOUS_SYNC", 510540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim seekMode); 511540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // fall-through 5123d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen case MediaTrack::ReadOptions::SEEK_PREVIOUS_SYNC: 513540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (index == 0) { 514540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ALOGW("Previous sync not found; starting from the earliest " 515540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim "sync."); 516540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } else { 517540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim --index; 518540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 519540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim break; 520d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang default: 521d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang return ERROR_UNSUPPORTED; 522540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 523540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (!shouldSeekBeyond || mOffset <= mSeekSyncPoints->valueAt(index)) { 524540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t actualSeekTimeUs = mSeekSyncPoints->keyAt(index); 525540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim mOffset = mSeekSyncPoints->valueAt(index); 526540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err = queueDiscontinuityForSeek(actualSeekTimeUs); 527540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK) { 528540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 529540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 530540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 531540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 532540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (shouldSeekBeyond) { 533540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err = seekBeyond(seekTimeUs); 534540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK) { 535540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 536540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 537540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 538540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 539540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // Fast-forward to sync frame. 540540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim for (size_t i = 0; i < mSourceImpls.size(); ++i) { 541540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim const sp<AnotherPacketSource> &impl = mSourceImpls[i]; 542540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err; 543540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim feedUntilBufferAvailable(impl); 544540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim while (impl->hasBufferAvailable(&err)) { 545540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim sp<AMessage> meta = impl->getMetaAfterLastDequeued(0); 546540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim sp<ABuffer> buffer; 547540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (meta == NULL) { 548540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return UNKNOWN_ERROR; 549540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 550540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int32_t sync; 551540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (meta->findInt32("isSync", &sync) && sync) { 552540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim break; 553540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 554540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim err = impl->dequeueAccessUnit(&buffer); 555540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK) { 556540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 557540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 558540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim feedUntilBufferAvailable(impl); 559540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 560540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 561540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 562540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return OK; 563540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim} 564540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 565540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kimstatus_t MPEG2TSExtractor::queueDiscontinuityForSeek(int64_t actualSeekTimeUs) { 566540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // Signal discontinuity 567540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim sp<AMessage> extra(new AMessage); 56815d02f84351eaca14099bde11cfbf6f124bea71fDongwon Kang extra->setInt64(kATSParserKeyMediaTimeUs, actualSeekTimeUs); 569540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim mParser->signalDiscontinuity(ATSParser::DISCONTINUITY_TIME, extra); 570540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 571540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // After discontinuity, impl should only have discontinuities 572540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // with the last being what we queued. Dequeue them all here. 573540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim for (size_t i = 0; i < mSourceImpls.size(); ++i) { 574540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim const sp<AnotherPacketSource> &impl = mSourceImpls.itemAt(i); 575540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim sp<ABuffer> buffer; 576540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err; 577540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim while (impl->hasBufferAvailable(&err)) { 578540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK) { 579540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 580540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 581540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim err = impl->dequeueAccessUnit(&buffer); 582540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // If the source contains anything but discontinuity, that's 583540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // a programming mistake. 584540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim CHECK(err == INFO_DISCONTINUITY); 585540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 586540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 587540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 588540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // Feed until we have a buffer for each source. 589540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim for (size_t i = 0; i < mSourceImpls.size(); ++i) { 590540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim const sp<AnotherPacketSource> &impl = mSourceImpls.itemAt(i); 591540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim sp<ABuffer> buffer; 592540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err = feedUntilBufferAvailable(impl); 593540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK) { 594540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 595540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 596540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 597540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 598540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return OK; 599540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim} 600540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 601540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kimstatus_t MPEG2TSExtractor::seekBeyond(int64_t seekTimeUs) { 602540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // If we're seeking beyond where we know --- read until we reach there. 603540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim size_t syncPointsSize = mSeekSyncPoints->size(); 604540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 605540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim while (seekTimeUs > mSeekSyncPoints->keyAt( 606540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim mSeekSyncPoints->size() - 1)) { 607540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err; 608540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (syncPointsSize < mSeekSyncPoints->size()) { 609540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim syncPointsSize = mSeekSyncPoints->size(); 610540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t syncTimeUs = mSeekSyncPoints->keyAt(syncPointsSize - 1); 611540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // Dequeue buffers before sync point in order to avoid too much 612540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // cache building up. 613540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim sp<ABuffer> buffer; 614540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim for (size_t i = 0; i < mSourceImpls.size(); ++i) { 615540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim const sp<AnotherPacketSource> &impl = mSourceImpls[i]; 616540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t timeUs; 617540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim while ((err = impl->nextBufferTime(&timeUs)) == OK) { 618540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (timeUs < syncTimeUs) { 619540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim impl->dequeueAccessUnit(&buffer); 620540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } else { 621540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim break; 622540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 623540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 624540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK && err != -EWOULDBLOCK) { 625540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 626540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 627540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 628540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 629540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (feedMore() != OK) { 630540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return ERROR_END_OF_STREAM; 631540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 632540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 633540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 634540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return OK; 635540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim} 636540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 637540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kimstatus_t MPEG2TSExtractor::feedUntilBufferAvailable( 638540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim const sp<AnotherPacketSource> &impl) { 639540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t finalResult; 640540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim while (!impl->hasBufferAvailable(&finalResult)) { 641540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (finalResult != OK) { 642540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return finalResult; 643540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 644540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 645540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err = feedMore(); 646540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK) { 647540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim impl->signalEOS(err); 648540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 649540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 650540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return OK; 651bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber} 652bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber 653cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber//////////////////////////////////////////////////////////////////////////////// 654cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 65517e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kangbool SniffMPEG2TS(DataSourceBase *source, float *confidence) { 6560da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber for (int i = 0; i < 5; ++i) { 6570da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber char header; 6580da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (source->readAt(kTSPacketSize * i, &header, 1) != 1 6590da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber || header != 0x47) { 6600da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber return false; 6610da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber } 662cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 663cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 6640da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber *confidence = 0.1f; 665cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 666cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return true; 667cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 668cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 669cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} // namespace android 670