MPEG2TSExtractor.cpp revision f1d5aa162c02a16b7195a43a9bcea4d592600ac4
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#include "include/LiveSession.h" 23#include "include/NuCachedSource2.h" 24 25#include <media/stagefright/foundation/ADebug.h> 26#include <media/stagefright/DataSource.h> 27#include <media/stagefright/MediaDefs.h> 28#include <media/stagefright/MediaErrors.h> 29#include <media/stagefright/MediaSource.h> 30#include <media/stagefright/MetaData.h> 31#include <utils/String8.h> 32 33#include "AnotherPacketSource.h" 34#include "ATSParser.h" 35 36namespace android { 37 38static const size_t kTSPacketSize = 188; 39 40struct MPEG2TSSource : public MediaSource { 41 MPEG2TSSource( 42 const sp<MPEG2TSExtractor> &extractor, 43 const sp<AnotherPacketSource> &impl, 44 bool seekable); 45 46 virtual status_t start(MetaData *params = NULL); 47 virtual status_t stop(); 48 virtual sp<MetaData> getFormat(); 49 50 virtual status_t read( 51 MediaBuffer **buffer, const ReadOptions *options = NULL); 52 53private: 54 sp<MPEG2TSExtractor> mExtractor; 55 sp<AnotherPacketSource> mImpl; 56 57 // If there are both audio and video streams, only the video stream 58 // will be seekable, otherwise the single stream will be seekable. 59 bool mSeekable; 60 61 DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSSource); 62}; 63 64MPEG2TSSource::MPEG2TSSource( 65 const sp<MPEG2TSExtractor> &extractor, 66 const sp<AnotherPacketSource> &impl, 67 bool seekable) 68 : mExtractor(extractor), 69 mImpl(impl), 70 mSeekable(seekable) { 71} 72 73status_t MPEG2TSSource::start(MetaData *params) { 74 return mImpl->start(params); 75} 76 77status_t MPEG2TSSource::stop() { 78 return mImpl->stop(); 79} 80 81sp<MetaData> MPEG2TSSource::getFormat() { 82 sp<MetaData> meta = mImpl->getFormat(); 83 84 int64_t durationUs; 85 if (mExtractor->mLiveSession != NULL 86 && mExtractor->mLiveSession->getDuration(&durationUs) == OK) { 87 meta->setInt64(kKeyDuration, durationUs); 88 } 89 90 return meta; 91} 92 93status_t MPEG2TSSource::read( 94 MediaBuffer **out, const ReadOptions *options) { 95 *out = NULL; 96 97 int64_t seekTimeUs; 98 ReadOptions::SeekMode seekMode; 99 if (mSeekable && options && options->getSeekTo(&seekTimeUs, &seekMode)) { 100 mExtractor->seekTo(seekTimeUs); 101 } 102 103 status_t finalResult; 104 while (!mImpl->hasBufferAvailable(&finalResult)) { 105 if (finalResult != OK) { 106 return ERROR_END_OF_STREAM; 107 } 108 109 status_t err = mExtractor->feedMore(); 110 if (err != OK) { 111 mImpl->signalEOS(err); 112 } 113 } 114 115 return mImpl->read(out, options); 116} 117 118//////////////////////////////////////////////////////////////////////////////// 119 120MPEG2TSExtractor::MPEG2TSExtractor(const sp<DataSource> &source) 121 : mDataSource(source), 122 mParser(new ATSParser), 123 mOffset(0) { 124 init(); 125} 126 127size_t MPEG2TSExtractor::countTracks() { 128 return mSourceImpls.size(); 129} 130 131sp<MediaSource> MPEG2TSExtractor::getTrack(size_t index) { 132 if (index >= mSourceImpls.size()) { 133 return NULL; 134 } 135 136 bool seekable = true; 137 if (mSourceImpls.size() > 1) { 138 CHECK_EQ(mSourceImpls.size(), 2u); 139 140 sp<MetaData> meta = mSourceImpls.editItemAt(index)->getFormat(); 141 const char *mime; 142 CHECK(meta->findCString(kKeyMIMEType, &mime)); 143 144 if (!strncasecmp("audio/", mime, 6)) { 145 seekable = false; 146 } 147 } 148 149 return new MPEG2TSSource(this, mSourceImpls.editItemAt(index), seekable); 150} 151 152sp<MetaData> MPEG2TSExtractor::getTrackMetaData( 153 size_t index, uint32_t flags) { 154 return index < mSourceImpls.size() 155 ? mSourceImpls.editItemAt(index)->getFormat() : NULL; 156} 157 158sp<MetaData> MPEG2TSExtractor::getMetaData() { 159 sp<MetaData> meta = new MetaData; 160 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 161 162 return meta; 163} 164 165void MPEG2TSExtractor::init() { 166 bool haveAudio = false; 167 bool haveVideo = false; 168 int numPacketsParsed = 0; 169 170 while (feedMore() == OK) { 171 ATSParser::SourceType type; 172 if (haveAudio && haveVideo) { 173 break; 174 } 175 if (!haveVideo) { 176 sp<AnotherPacketSource> impl = 177 (AnotherPacketSource *)mParser->getSource( 178 ATSParser::VIDEO).get(); 179 180 if (impl != NULL) { 181 haveVideo = true; 182 mSourceImpls.push(impl); 183 } 184 } 185 186 if (!haveAudio) { 187 sp<AnotherPacketSource> impl = 188 (AnotherPacketSource *)mParser->getSource( 189 ATSParser::AUDIO).get(); 190 191 if (impl != NULL) { 192 haveAudio = true; 193 mSourceImpls.push(impl); 194 } 195 } 196 197 if (++numPacketsParsed > 10000) { 198 break; 199 } 200 } 201 202 ALOGI("haveAudio=%d, haveVideo=%d", haveAudio, haveVideo); 203} 204 205status_t MPEG2TSExtractor::feedMore() { 206 Mutex::Autolock autoLock(mLock); 207 208 uint8_t packet[kTSPacketSize]; 209 ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize); 210 211 if (n < (ssize_t)kTSPacketSize) { 212 return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM; 213 } 214 215 mOffset += n; 216 return mParser->feedTSPacket(packet, kTSPacketSize); 217} 218 219void MPEG2TSExtractor::setLiveSession(const sp<LiveSession> &liveSession) { 220 Mutex::Autolock autoLock(mLock); 221 222 mLiveSession = liveSession; 223} 224 225void MPEG2TSExtractor::seekTo(int64_t seekTimeUs) { 226 Mutex::Autolock autoLock(mLock); 227 228 if (mLiveSession == NULL) { 229 return; 230 } 231 232 mLiveSession->seekTo(seekTimeUs); 233} 234 235uint32_t MPEG2TSExtractor::flags() const { 236 Mutex::Autolock autoLock(mLock); 237 238 uint32_t flags = CAN_PAUSE; 239 240 if (mLiveSession != NULL && mLiveSession->isSeekable()) { 241 flags |= CAN_SEEK_FORWARD | CAN_SEEK_BACKWARD | CAN_SEEK; 242 } 243 244 return flags; 245} 246 247//////////////////////////////////////////////////////////////////////////////// 248 249bool SniffMPEG2TS( 250 const sp<DataSource> &source, String8 *mimeType, float *confidence, 251 sp<AMessage> *) { 252 for (int i = 0; i < 5; ++i) { 253 char header; 254 if (source->readAt(kTSPacketSize * i, &header, 1) != 1 255 || header != 0x47) { 256 return false; 257 } 258 } 259 260 *confidence = 0.1f; 261 mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 262 263 return true; 264} 265 266} // namespace android 267