MPEG2TSExtractor.cpp revision 2a4d22d79e927f2245537921e10fc5fda1c47a29
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" 22cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 23cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/DataSource.h> 24cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MediaDefs.h> 25cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MediaErrors.h> 26cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MediaSource.h> 27cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <media/stagefright/MetaData.h> 28cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include <utils/String8.h> 29cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 30cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include "AnotherPacketSource.h" 31cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include "ATSParser.h" 32cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 33cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubernamespace android { 34cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 350da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huberstatic const size_t kTSPacketSize = 188; 360da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber 37cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstruct MPEG2TSSource : public MediaSource { 38cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber MPEG2TSSource( 39cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber const sp<MPEG2TSExtractor> &extractor, 40cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber const sp<AnotherPacketSource> &impl); 41cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 42cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber virtual status_t start(MetaData *params = NULL); 43cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber virtual status_t stop(); 44cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber virtual sp<MetaData> getFormat(); 45cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 46cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber virtual status_t read( 47cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber MediaBuffer **buffer, const ReadOptions *options = NULL); 48cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 49cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberprivate: 50cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber sp<MPEG2TSExtractor> mExtractor; 51cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber sp<AnotherPacketSource> mImpl; 52cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 53cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSSource); 54cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber}; 55cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 56cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas HuberMPEG2TSSource::MPEG2TSSource( 57cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber const sp<MPEG2TSExtractor> &extractor, 58cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber const sp<AnotherPacketSource> &impl) 59cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber : mExtractor(extractor), 60cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber mImpl(impl) { 61cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 62cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 63cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstatus_t MPEG2TSSource::start(MetaData *params) { 64cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return mImpl->start(params); 65cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 66cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 67cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstatus_t MPEG2TSSource::stop() { 68cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return mImpl->stop(); 69cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 70cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 71cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersp<MetaData> MPEG2TSSource::getFormat() { 72cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return mImpl->getFormat(); 73cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 74cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 75cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstatus_t MPEG2TSSource::read( 76cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber MediaBuffer **out, const ReadOptions *options) { 77cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber *out = NULL; 78cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 79cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber status_t finalResult; 80cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber while (!mImpl->hasBufferAvailable(&finalResult)) { 81cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber if (finalResult != OK) { 82cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return ERROR_END_OF_STREAM; 83cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 84cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 85cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber status_t err = mExtractor->feedMore(); 86cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber if (err != OK) { 87cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber mImpl->signalEOS(err); 88cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 89cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 90cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 91cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return mImpl->read(out, options); 92cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 93cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 94cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber//////////////////////////////////////////////////////////////////////////////// 95cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 96cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas HuberMPEG2TSExtractor::MPEG2TSExtractor(const sp<DataSource> &source) 97cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber : mDataSource(source), 98cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber mParser(new ATSParser), 99cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber mOffset(0) { 100cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber init(); 101cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 102cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 103cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersize_t MPEG2TSExtractor::countTracks() { 104cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return mSourceImpls.size(); 105cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 106cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 107cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersp<MediaSource> MPEG2TSExtractor::getTrack(size_t index) { 108cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber if (index >= mSourceImpls.size()) { 109cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return NULL; 110cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 111cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 112cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return new MPEG2TSSource(this, mSourceImpls.editItemAt(index)); 113cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 114cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 115cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersp<MetaData> MPEG2TSExtractor::getTrackMetaData( 116cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber size_t index, uint32_t flags) { 117cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return index < mSourceImpls.size() 118cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber ? mSourceImpls.editItemAt(index)->getFormat() : NULL; 119cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 120cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 121cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubersp<MetaData> MPEG2TSExtractor::getMetaData() { 122cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber sp<MetaData> meta = new MetaData; 123cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 124cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 125cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return meta; 126cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 127cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 128cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Hubervoid MPEG2TSExtractor::init() { 129cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber bool haveAudio = false; 130cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber bool haveVideo = false; 1310da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber int numPacketsParsed = 0; 132cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 133cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber while (feedMore() == OK) { 134cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber ATSParser::SourceType type; 135cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber if (haveAudio && haveVideo) { 136cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber break; 137cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 1380da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (!haveVideo) { 1390da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber sp<AnotherPacketSource> impl = 1400da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber (AnotherPacketSource *)mParser->getSource( 1410da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber ATSParser::AVC_VIDEO).get(); 1420da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber 1430da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (impl != NULL) { 1440da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber haveVideo = true; 1450da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber mSourceImpls.push(impl); 1460da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber } 147cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 148cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 1490da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (!haveAudio) { 1500da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber sp<AnotherPacketSource> impl = 1510da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber (AnotherPacketSource *)mParser->getSource( 1520da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber ATSParser::MPEG2ADTS_AUDIO).get(); 1530da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber 1540da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (impl != NULL) { 155cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber haveAudio = true; 1560da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber mSourceImpls.push(impl); 157cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 1580da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber } 1590da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber 1606a63a939601645404fd98f58c19cc38ca818d99eAndreas Huber if (++numPacketsParsed > 2500) { 1610da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber break; 162cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 163cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 164cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 165cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber LOGI("haveAudio=%d, haveVideo=%d", haveAudio, haveVideo); 166cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 167cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 1682a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huberstatic bool isDiscontinuity(const uint8_t *data, ssize_t size) { 1692a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber return size == 188 && data[0] == 0x00; 1702a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber} 1712a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber 172cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberstatus_t MPEG2TSExtractor::feedMore() { 173cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber Mutex::Autolock autoLock(mLock); 174cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 175cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber uint8_t packet[kTSPacketSize]; 176cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize); 177cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 1782a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber if (isDiscontinuity(packet, n)) { 1792a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber LOGI("XXX discontinuity detected"); 1802a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber mParser->signalDiscontinuity(); 1812a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } else if (n < (ssize_t)kTSPacketSize) { 182cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM; 1832a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber } else { 1842a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber mParser->feedTSPacket(packet, kTSPacketSize); 185cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 186cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 1872a4d22d79e927f2245537921e10fc5fda1c47a29Andreas Huber mOffset += n; 188cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 189cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return OK; 190cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 191cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 192cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber//////////////////////////////////////////////////////////////////////////////// 193cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 194cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huberbool SniffMPEG2TS( 1955a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 1965a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 1970da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber for (int i = 0; i < 5; ++i) { 1980da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber char header; 1990da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber if (source->readAt(kTSPacketSize * i, &header, 1) != 1 2000da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber || header != 0x47) { 2010da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber return false; 2020da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber } 203cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber } 204cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 2050da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber *confidence = 0.1f; 206cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 207cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 208cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber return true; 209cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} 210cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber 211cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber} // namespace android 212