MPEG2TSExtractor.cpp revision 540006666b4191cd78391378f1c66c21bcf0c4cd
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" 19cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <utils/Log.h> 20cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 21cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include "include/MPEG2TSExtractor.h" 22bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber#include "include/NuCachedSource2.h" 23cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 24540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim#include <media/stagefright/foundation/ABuffer.h> 25f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h> 26cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/DataSource.h> 27cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MediaDefs.h> 28cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MediaErrors.h> 29cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MediaSource.h> 30cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MetaData.h> 31540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim#include <media/IStreamSource.h> 32cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <utils/String8.h> 33cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 34cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include "AnotherPacketSource.h" 35cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include "ATSParser.h" 36cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 37cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubernamespace android { 38cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 390da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huberstatic const size_t kTSPacketSize = 188; 400da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber 41cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstruct MPEG2TSSource : public MediaSource { 42cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber MPEG2TSSource( 43cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber const sp<MPEG2TSExtractor> &extractor, 44bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber const sp<AnotherPacketSource> &impl, 45540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim bool doesSeek); 46cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 47cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber virtual status_t start(MetaData *params = NULL); 48cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber virtual status_t stop(); 49cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber virtual sp<MetaData> getFormat(); 50cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 51cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber virtual status_t read( 52cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber MediaBuffer **buffer, const ReadOptions *options = NULL); 53cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 54cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberprivate: 55cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber sp<MPEG2TSExtractor> mExtractor; 56cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber sp<AnotherPacketSource> mImpl; 57cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 58bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber // If there are both audio and video streams, only the video stream 59540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // will signal seek on the extractor; otherwise the single stream will seek. 60540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim bool mDoesSeek; 61bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber 62cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSSource); 63cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}; 64cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 65cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas HuberMPEG2TSSource::MPEG2TSSource( 66cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber const sp<MPEG2TSExtractor> &extractor, 67bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber const sp<AnotherPacketSource> &impl, 68540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim bool doesSeek) 69cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber : mExtractor(extractor), 70bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber mImpl(impl), 71540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim mDoesSeek(doesSeek) { 72cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 73cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 74cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstatus_t MPEG2TSSource::start(MetaData *params) { 75cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return mImpl->start(params); 76cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 77cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 78cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstatus_t MPEG2TSSource::stop() { 79cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return mImpl->stop(); 80cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 81cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 82cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersp<MetaData> MPEG2TSSource::getFormat() { 8314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber return mImpl->getFormat(); 84cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 85cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 86cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstatus_t MPEG2TSSource::read( 87cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber MediaBuffer **out, const ReadOptions *options) { 88cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber *out = NULL; 89cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 90540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t seekTimeUs; 91540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ReadOptions::SeekMode seekMode; 92540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (mDoesSeek && options && options->getSeekTo(&seekTimeUs, &seekMode)) { 93540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // seek is needed 94540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err = mExtractor->seek(seekTimeUs, seekMode); 95cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber if (err != OK) { 96540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 97cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 98cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 99cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 100540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (mExtractor->feedUntilBufferAvailable(mImpl) != OK) { 101540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return ERROR_END_OF_STREAM; 1025d7c3eef1985ff15a56920c548cc4e41d6c9627aMarco Nelissen } 1035d7c3eef1985ff15a56920c548cc4e41d6c9627aMarco Nelissen 104cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return mImpl->read(out, options); 105cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 106cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 107cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber//////////////////////////////////////////////////////////////////////////////// 108cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 109cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas HuberMPEG2TSExtractor::MPEG2TSExtractor(const sp<DataSource> &source) 110cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber : mDataSource(source), 111cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber mParser(new ATSParser), 112cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber mOffset(0) { 113cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber init(); 114cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 115cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 116cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersize_t MPEG2TSExtractor::countTracks() { 117cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return mSourceImpls.size(); 118cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 119cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 120cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersp<MediaSource> MPEG2TSExtractor::getTrack(size_t index) { 121cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber if (index >= mSourceImpls.size()) { 122cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return NULL; 123cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 124cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 125540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // The seek reference track (video if present; audio otherwise) performs 126540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // seek requests, while other tracks ignore requests. 127540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return new MPEG2TSSource(this, mSourceImpls.editItemAt(index), 128540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim (mSeekSyncPoints == &mSyncPoints.editItemAt(index))); 129cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 130cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 131cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersp<MetaData> MPEG2TSExtractor::getTrackMetaData( 132d411b4ca2945cd8974a3a78199fce94646950128Andreas Huber size_t index, uint32_t /* flags */) { 133cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return index < mSourceImpls.size() 134cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber ? mSourceImpls.editItemAt(index)->getFormat() : NULL; 135cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 136cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 137cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersp<MetaData> MPEG2TSExtractor::getMetaData() { 138cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber sp<MetaData> meta = new MetaData; 139cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 140cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 141cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return meta; 142cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 143cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 144cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubervoid MPEG2TSExtractor::init() { 145cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber bool haveAudio = false; 146cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber bool haveVideo = false; 1470da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber int numPacketsParsed = 0; 148cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 149cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber while (feedMore() == OK) { 150cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber if (haveAudio && haveVideo) { 151cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber break; 152cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 1530da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (!haveVideo) { 1540da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber sp<AnotherPacketSource> impl = 1550da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber (AnotherPacketSource *)mParser->getSource( 156386d609dc513e838c7e7c4c46c604493ccd560beAndreas Huber ATSParser::VIDEO).get(); 1570da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber 1580da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (impl != NULL) { 1590da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber haveVideo = true; 1600da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber mSourceImpls.push(impl); 161540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim mSyncPoints.push(); 162540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim mSeekSyncPoints = &mSyncPoints.editTop(); 1630da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber } 164cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 165cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 1660da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (!haveAudio) { 1670da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber sp<AnotherPacketSource> impl = 1680da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber (AnotherPacketSource *)mParser->getSource( 169386d609dc513e838c7e7c4c46c604493ccd560beAndreas Huber ATSParser::AUDIO).get(); 1700da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber 1710da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (impl != NULL) { 172cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber haveAudio = true; 1730da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber mSourceImpls.push(impl); 174540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim mSyncPoints.push(); 175540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (!haveVideo) { 176540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim mSeekSyncPoints = &mSyncPoints.editTop(); 177540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 178cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 1790da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber } 1800da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber 181386d609dc513e838c7e7c4c46c604493ccd560beAndreas Huber if (++numPacketsParsed > 10000) { 1820da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber break; 183cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 184cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 185cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 186540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim off64_t size; 187540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (mDataSource->getSize(&size) == OK && (haveAudio || haveVideo)) { 188540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim sp<AnotherPacketSource> impl = haveVideo 189540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ? (AnotherPacketSource *)mParser->getSource( 190540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ATSParser::VIDEO).get() 191540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim : (AnotherPacketSource *)mParser->getSource( 192540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ATSParser::AUDIO).get(); 193540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t prevBufferedDurationUs = 0; 194540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t durationUs = -1; 195540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim List<int64_t> durations; 196540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // Estimate duration --- stabilize until you get <500ms deviation. 197540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim for (; feedMore() == OK && numPacketsParsed <= 10000; 198540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ++numPacketsParsed) { 199540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err; 200540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t bufferedDurationUs = impl->getBufferedDurationUs(&err); 201540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK) { 202540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim break; 203540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 204540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (bufferedDurationUs != prevBufferedDurationUs) { 205540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim durationUs = size * bufferedDurationUs / mOffset; 206540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim durations.push_back(durationUs); 207540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (durations.size() > 5) { 208540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim durations.erase(durations.begin()); 209540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t min = *durations.begin(); 210540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t max = *durations.begin(); 211540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim for (List<int64_t>::iterator i = durations.begin(); 212540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim i != durations.end(); 213540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ++i) { 214540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (min > *i) { 215540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim min = *i; 216540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 217540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (max < *i) { 218540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim max = *i; 219540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 220540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 221540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (max - min < 500 * 1000) { 222540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim break; 223540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 224540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 225540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim prevBufferedDurationUs = bufferedDurationUs; 226540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 227540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 228540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (durationUs > 0) { 229540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim const sp<MetaData> meta = impl->getFormat(); 230540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim meta->setInt64(kKeyDuration, durationUs); 231540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim impl->setFormat(meta); 232540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 233540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 234540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 235df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("haveAudio=%d, haveVideo=%d", haveAudio, haveVideo); 236cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 237cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 238cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstatus_t MPEG2TSExtractor::feedMore() { 239cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber Mutex::Autolock autoLock(mLock); 240cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 241cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber uint8_t packet[kTSPacketSize]; 242cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize); 243cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 244ed8d14f6a934072cd012992c4ef16990a54baa9aAndreas Huber if (n < (ssize_t)kTSPacketSize) { 245be9634d071e79b72a42a4504f64eda9e2a0bceb8Marco Nelissen if (n >= 0) { 246be9634d071e79b72a42a4504f64eda9e2a0bceb8Marco Nelissen mParser->signalEOS(ERROR_END_OF_STREAM); 247be9634d071e79b72a42a4504f64eda9e2a0bceb8Marco Nelissen } 248cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM; 249cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 250cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 251540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ATSParser::SyncEvent event(mOffset); 2522a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber mOffset += n; 253540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err = mParser->feedTSPacket(packet, kTSPacketSize, &event); 254540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (event.isInit()) { 255540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim for (size_t i = 0; i < mSourceImpls.size(); ++i) { 256540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (mSourceImpls[i].get() == event.getMediaSource().get()) { 257540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim mSyncPoints.editItemAt(i).add( 258540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim event.getTimeUs(), event.getOffset()); 259540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim break; 260540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 261540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 262540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 263540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 264cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 265cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 266bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huberuint32_t MPEG2TSExtractor::flags() const { 267540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return CAN_PAUSE | CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD; 268540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim} 269540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 270540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kimstatus_t MPEG2TSExtractor::seek(int64_t seekTimeUs, 271540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim const MediaSource::ReadOptions::SeekMode &seekMode) { 272540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (mSeekSyncPoints == NULL || mSeekSyncPoints->isEmpty()) { 273540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ALOGW("No sync point to seek to."); 274540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // ... and therefore we have nothing useful to do here. 275540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return OK; 276540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 277540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 278540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // Determine whether we're seeking beyond the known area. 279540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim bool shouldSeekBeyond = 280540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim (seekTimeUs > mSeekSyncPoints->keyAt(mSeekSyncPoints->size() - 1)); 281540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 282540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // Determine the sync point to seek. 283540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim size_t index = 0; 284540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim for (; index < mSeekSyncPoints->size(); ++index) { 285540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t timeUs = mSeekSyncPoints->keyAt(index); 286540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (timeUs > seekTimeUs) { 287540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim break; 288540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 289540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 290540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 291540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim switch (seekMode) { 292540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim case MediaSource::ReadOptions::SEEK_NEXT_SYNC: 293540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (index == mSeekSyncPoints->size()) { 294540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ALOGW("Next sync not found; starting from the latest sync."); 295540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim --index; 296540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 297540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim break; 298540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC: 299540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim case MediaSource::ReadOptions::SEEK_CLOSEST: 300540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ALOGW("seekMode not supported: %d; falling back to PREVIOUS_SYNC", 301540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim seekMode); 302540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // fall-through 303540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC: 304540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (index == 0) { 305540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim ALOGW("Previous sync not found; starting from the earliest " 306540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim "sync."); 307540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } else { 308540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim --index; 309540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 310540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim break; 311540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 312540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (!shouldSeekBeyond || mOffset <= mSeekSyncPoints->valueAt(index)) { 313540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t actualSeekTimeUs = mSeekSyncPoints->keyAt(index); 314540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim mOffset = mSeekSyncPoints->valueAt(index); 315540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err = queueDiscontinuityForSeek(actualSeekTimeUs); 316540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK) { 317540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 318540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 319540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 320540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 321540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (shouldSeekBeyond) { 322540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err = seekBeyond(seekTimeUs); 323540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK) { 324540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 325540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 326540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 327540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 328540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // Fast-forward to sync frame. 329540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim for (size_t i = 0; i < mSourceImpls.size(); ++i) { 330540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim const sp<AnotherPacketSource> &impl = mSourceImpls[i]; 331540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err; 332540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim feedUntilBufferAvailable(impl); 333540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim while (impl->hasBufferAvailable(&err)) { 334540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim sp<AMessage> meta = impl->getMetaAfterLastDequeued(0); 335540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim sp<ABuffer> buffer; 336540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (meta == NULL) { 337540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return UNKNOWN_ERROR; 338540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 339540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int32_t sync; 340540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (meta->findInt32("isSync", &sync) && sync) { 341540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim break; 342540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 343540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim err = impl->dequeueAccessUnit(&buffer); 344540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK) { 345540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 346540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 347540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim feedUntilBufferAvailable(impl); 348540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 349540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 350540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 351540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return OK; 352540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim} 353540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 354540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kimstatus_t MPEG2TSExtractor::queueDiscontinuityForSeek(int64_t actualSeekTimeUs) { 355540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // Signal discontinuity 356540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim sp<AMessage> extra(new AMessage); 357540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim extra->setInt64(IStreamListener::kKeyMediaTimeUs, actualSeekTimeUs); 358540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim mParser->signalDiscontinuity(ATSParser::DISCONTINUITY_TIME, extra); 359540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 360540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // After discontinuity, impl should only have discontinuities 361540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // with the last being what we queued. Dequeue them all here. 362540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim for (size_t i = 0; i < mSourceImpls.size(); ++i) { 363540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim const sp<AnotherPacketSource> &impl = mSourceImpls.itemAt(i); 364540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim sp<ABuffer> buffer; 365540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err; 366540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim while (impl->hasBufferAvailable(&err)) { 367540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK) { 368540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 369540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 370540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim err = impl->dequeueAccessUnit(&buffer); 371540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // If the source contains anything but discontinuity, that's 372540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // a programming mistake. 373540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim CHECK(err == INFO_DISCONTINUITY); 374540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 375540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 376540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 377540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // Feed until we have a buffer for each source. 378540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim for (size_t i = 0; i < mSourceImpls.size(); ++i) { 379540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim const sp<AnotherPacketSource> &impl = mSourceImpls.itemAt(i); 380540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim sp<ABuffer> buffer; 381540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err = feedUntilBufferAvailable(impl); 382540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK) { 383540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 384540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 385540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 386540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 387540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return OK; 388540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim} 389540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 390540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kimstatus_t MPEG2TSExtractor::seekBeyond(int64_t seekTimeUs) { 391540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // If we're seeking beyond where we know --- read until we reach there. 392540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim size_t syncPointsSize = mSeekSyncPoints->size(); 393540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 394540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim while (seekTimeUs > mSeekSyncPoints->keyAt( 395540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim mSeekSyncPoints->size() - 1)) { 396540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err; 397540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (syncPointsSize < mSeekSyncPoints->size()) { 398540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim syncPointsSize = mSeekSyncPoints->size(); 399540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t syncTimeUs = mSeekSyncPoints->keyAt(syncPointsSize - 1); 400540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // Dequeue buffers before sync point in order to avoid too much 401540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim // cache building up. 402540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim sp<ABuffer> buffer; 403540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim for (size_t i = 0; i < mSourceImpls.size(); ++i) { 404540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim const sp<AnotherPacketSource> &impl = mSourceImpls[i]; 405540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim int64_t timeUs; 406540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim while ((err = impl->nextBufferTime(&timeUs)) == OK) { 407540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (timeUs < syncTimeUs) { 408540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim impl->dequeueAccessUnit(&buffer); 409540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } else { 410540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim break; 411540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 412540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 413540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK && err != -EWOULDBLOCK) { 414540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return err; 415540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 416540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 417540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 418540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (feedMore() != OK) { 419540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return ERROR_END_OF_STREAM; 420540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 421540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 422540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 423540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return OK; 424540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim} 425540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 426540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kimstatus_t MPEG2TSExtractor::feedUntilBufferAvailable( 427540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim const sp<AnotherPacketSource> &impl) { 428540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t finalResult; 429540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim while (!impl->hasBufferAvailable(&finalResult)) { 430540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (finalResult != OK) { 431540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return finalResult; 432540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 433540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim 434540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim status_t err = feedMore(); 435540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim if (err != OK) { 436540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim impl->signalEOS(err); 437540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 438540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim } 439540006666b4191cd78391378f1c66c21bcf0c4cdWonsik Kim return OK; 440bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber} 441bff07d0b22a5ee2d9f044f6cb5e4be1532017ab0Andreas Huber 442cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber//////////////////////////////////////////////////////////////////////////////// 443cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 444cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberbool SniffMPEG2TS( 4455a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 4465a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 4470da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber for (int i = 0; i < 5; ++i) { 4480da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber char header; 4490da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (source->readAt(kTSPacketSize * i, &header, 1) != 1 4500da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber || header != 0x47) { 4510da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber return false; 4520da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber } 453cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 454cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 4550da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber *confidence = 0.1f; 456cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 457cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 458cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return true; 459cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 460cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 461cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} // namespace android 462