MPEG2TSExtractor.cpp revision e71d10e7ad55ccbcb0756c007caef1c959090384
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 35struct MPEG2TSSource : public MediaSource { 36 MPEG2TSSource( 37 const sp<MPEG2TSExtractor> &extractor, 38 const sp<AnotherPacketSource> &impl); 39 40 virtual status_t start(MetaData *params = NULL); 41 virtual status_t stop(); 42 virtual sp<MetaData> getFormat(); 43 44 virtual status_t read( 45 MediaBuffer **buffer, const ReadOptions *options = NULL); 46 47private: 48 sp<MPEG2TSExtractor> mExtractor; 49 sp<AnotherPacketSource> mImpl; 50 51 DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSSource); 52}; 53 54MPEG2TSSource::MPEG2TSSource( 55 const sp<MPEG2TSExtractor> &extractor, 56 const sp<AnotherPacketSource> &impl) 57 : mExtractor(extractor), 58 mImpl(impl) { 59} 60 61status_t MPEG2TSSource::start(MetaData *params) { 62 return mImpl->start(params); 63} 64 65status_t MPEG2TSSource::stop() { 66 return mImpl->stop(); 67} 68 69sp<MetaData> MPEG2TSSource::getFormat() { 70 return mImpl->getFormat(); 71} 72 73status_t MPEG2TSSource::read( 74 MediaBuffer **out, const ReadOptions *options) { 75 *out = NULL; 76 77 status_t finalResult; 78 while (!mImpl->hasBufferAvailable(&finalResult)) { 79 if (finalResult != OK) { 80 return ERROR_END_OF_STREAM; 81 } 82 83 status_t err = mExtractor->feedMore(); 84 if (err != OK) { 85 mImpl->signalEOS(err); 86 } 87 } 88 89 return mImpl->read(out, options); 90} 91 92//////////////////////////////////////////////////////////////////////////////// 93 94MPEG2TSExtractor::MPEG2TSExtractor(const sp<DataSource> &source) 95 : mDataSource(source), 96 mParser(new ATSParser), 97 mOffset(0) { 98 init(); 99} 100 101size_t MPEG2TSExtractor::countTracks() { 102 return mSourceImpls.size(); 103} 104 105sp<MediaSource> MPEG2TSExtractor::getTrack(size_t index) { 106 if (index >= mSourceImpls.size()) { 107 return NULL; 108 } 109 110 return new MPEG2TSSource(this, mSourceImpls.editItemAt(index)); 111} 112 113sp<MetaData> MPEG2TSExtractor::getTrackMetaData( 114 size_t index, uint32_t flags) { 115 return index < mSourceImpls.size() 116 ? mSourceImpls.editItemAt(index)->getFormat() : NULL; 117} 118 119sp<MetaData> MPEG2TSExtractor::getMetaData() { 120 sp<MetaData> meta = new MetaData; 121 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 122 123 return meta; 124} 125 126void MPEG2TSExtractor::init() { 127 bool haveAudio = false; 128 bool haveVideo = false; 129 130 while (feedMore() == OK) { 131 ATSParser::SourceType type; 132 if (haveAudio && haveVideo) { 133 break; 134 } 135 if (haveVideo) { 136 type = ATSParser::MPEG2ADTS_AUDIO; 137 } else { 138 type = ATSParser::AVC_VIDEO; 139 } 140 sp<AnotherPacketSource> impl = 141 (AnotherPacketSource *)mParser->getSource(type).get(); 142 143 if (impl != NULL) { 144 if (type == ATSParser::MPEG2ADTS_AUDIO) { 145 haveAudio = true; 146 } else { 147 haveVideo = true; 148 } 149 mSourceImpls.push(impl); 150 } 151 } 152 153 LOGI("haveAudio=%d, haveVideo=%d", haveAudio, haveVideo); 154} 155 156status_t MPEG2TSExtractor::feedMore() { 157 Mutex::Autolock autoLock(mLock); 158 159 static const size_t kTSPacketSize = 188; 160 161 uint8_t packet[kTSPacketSize]; 162 ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize); 163 164 if (n < (ssize_t)kTSPacketSize) { 165 return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM; 166 } 167 168 mOffset += kTSPacketSize; 169 mParser->feedTSPacket(packet, kTSPacketSize); 170 171 return OK; 172} 173 174//////////////////////////////////////////////////////////////////////////////// 175 176bool SniffMPEG2TS( 177 const sp<DataSource> &source, String8 *mimeType, float *confidence) { 178#if 0 179 char header; 180 if (source->readAt(0, &header, 1) != 1 || header != 0x47) { 181 return false; 182 } 183 184 *confidence = 0.05f; 185 mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 186 187 return true; 188#else 189 // For now we're going to never identify this type of stream, since we'd 190 // just base our decision on a single byte... 191 // Instead you can instantiate an MPEG2TSExtractor by explicitly stating 192 // its proper mime type in the call to MediaExtractor::Create(...). 193 return false; 194#endif 195} 196 197} // namespace android 198