MPEG2TSExtractor.cpp revision 6a63a939601645404fd98f58c19cc38ca818d99e
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "MPEG2TSExtractor" 19#include <utils/Log.h> 20 21#include "include/MPEG2TSExtractor.h" 22 23#include <media/stagefright/DataSource.h> 24#include <media/stagefright/MediaDefs.h> 25#include <media/stagefright/MediaErrors.h> 26#include <media/stagefright/MediaSource.h> 27#include <media/stagefright/MetaData.h> 28#include <utils/String8.h> 29 30#include "AnotherPacketSource.h" 31#include "ATSParser.h" 32 33namespace android { 34 35static const size_t kTSPacketSize = 188; 36 37struct MPEG2TSSource : public MediaSource { 38 MPEG2TSSource( 39 const sp<MPEG2TSExtractor> &extractor, 40 const sp<AnotherPacketSource> &impl); 41 42 virtual status_t start(MetaData *params = NULL); 43 virtual status_t stop(); 44 virtual sp<MetaData> getFormat(); 45 46 virtual status_t read( 47 MediaBuffer **buffer, const ReadOptions *options = NULL); 48 49private: 50 sp<MPEG2TSExtractor> mExtractor; 51 sp<AnotherPacketSource> mImpl; 52 53 DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSSource); 54}; 55 56MPEG2TSSource::MPEG2TSSource( 57 const sp<MPEG2TSExtractor> &extractor, 58 const sp<AnotherPacketSource> &impl) 59 : mExtractor(extractor), 60 mImpl(impl) { 61} 62 63status_t MPEG2TSSource::start(MetaData *params) { 64 return mImpl->start(params); 65} 66 67status_t MPEG2TSSource::stop() { 68 return mImpl->stop(); 69} 70 71sp<MetaData> MPEG2TSSource::getFormat() { 72 return mImpl->getFormat(); 73} 74 75status_t MPEG2TSSource::read( 76 MediaBuffer **out, const ReadOptions *options) { 77 *out = NULL; 78 79 status_t finalResult; 80 while (!mImpl->hasBufferAvailable(&finalResult)) { 81 if (finalResult != OK) { 82 return ERROR_END_OF_STREAM; 83 } 84 85 status_t err = mExtractor->feedMore(); 86 if (err != OK) { 87 mImpl->signalEOS(err); 88 } 89 } 90 91 return mImpl->read(out, options); 92} 93 94//////////////////////////////////////////////////////////////////////////////// 95 96MPEG2TSExtractor::MPEG2TSExtractor(const sp<DataSource> &source) 97 : mDataSource(source), 98 mParser(new ATSParser), 99 mOffset(0) { 100 init(); 101} 102 103size_t MPEG2TSExtractor::countTracks() { 104 return mSourceImpls.size(); 105} 106 107sp<MediaSource> MPEG2TSExtractor::getTrack(size_t index) { 108 if (index >= mSourceImpls.size()) { 109 return NULL; 110 } 111 112 return new MPEG2TSSource(this, mSourceImpls.editItemAt(index)); 113} 114 115sp<MetaData> MPEG2TSExtractor::getTrackMetaData( 116 size_t index, uint32_t flags) { 117 return index < mSourceImpls.size() 118 ? mSourceImpls.editItemAt(index)->getFormat() : NULL; 119} 120 121sp<MetaData> MPEG2TSExtractor::getMetaData() { 122 sp<MetaData> meta = new MetaData; 123 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 124 125 return meta; 126} 127 128void MPEG2TSExtractor::init() { 129 bool haveAudio = false; 130 bool haveVideo = false; 131 int numPacketsParsed = 0; 132 133 while (feedMore() == OK) { 134 ATSParser::SourceType type; 135 if (haveAudio && haveVideo) { 136 break; 137 } 138 if (!haveVideo) { 139 sp<AnotherPacketSource> impl = 140 (AnotherPacketSource *)mParser->getSource( 141 ATSParser::AVC_VIDEO).get(); 142 143 if (impl != NULL) { 144 haveVideo = true; 145 mSourceImpls.push(impl); 146 } 147 } 148 149 if (!haveAudio) { 150 sp<AnotherPacketSource> impl = 151 (AnotherPacketSource *)mParser->getSource( 152 ATSParser::MPEG2ADTS_AUDIO).get(); 153 154 if (impl != NULL) { 155 haveAudio = true; 156 mSourceImpls.push(impl); 157 } 158 } 159 160 if (++numPacketsParsed > 2500) { 161 break; 162 } 163 } 164 165 LOGI("haveAudio=%d, haveVideo=%d", haveAudio, haveVideo); 166} 167 168status_t MPEG2TSExtractor::feedMore() { 169 Mutex::Autolock autoLock(mLock); 170 171 uint8_t packet[kTSPacketSize]; 172 ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize); 173 174 if (n < (ssize_t)kTSPacketSize) { 175 return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM; 176 } 177 178 mOffset += kTSPacketSize; 179 mParser->feedTSPacket(packet, kTSPacketSize); 180 181 return OK; 182} 183 184//////////////////////////////////////////////////////////////////////////////// 185 186bool SniffMPEG2TS( 187 const sp<DataSource> &source, String8 *mimeType, float *confidence, 188 sp<AMessage> *) { 189 for (int i = 0; i < 5; ++i) { 190 char header; 191 if (source->readAt(kTSPacketSize * i, &header, 1) != 1 192 || header != 0x47) { 193 return false; 194 } 195 } 196 197 *confidence = 0.1f; 198 mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 199 200 return true; 201} 202 203} // namespace android 204