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/DataSource.h> 26 #include <media/stagefright/MediaDebug.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 36 namespace android { 37 38 static const size_t kTSPacketSize = 188; 39 40 struct 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 53 private: 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 64 MPEG2TSSource::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 73 status_t MPEG2TSSource::start(MetaData *params) { 74 return mImpl->start(params); 75 } 76 77 status_t MPEG2TSSource::stop() { 78 return mImpl->stop(); 79 } 80 81 sp<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 93 status_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 120 MPEG2TSExtractor::MPEG2TSExtractor(const sp<DataSource> &source) 121 : mDataSource(source), 122 mParser(new ATSParser), 123 mOffset(0) { 124 init(); 125 } 126 127 size_t MPEG2TSExtractor::countTracks() { 128 return mSourceImpls.size(); 129 } 130 131 sp<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 152 sp<MetaData> MPEG2TSExtractor::getTrackMetaData( 153 size_t index, uint32_t flags) { 154 return index < mSourceImpls.size() 155 ? mSourceImpls.editItemAt(index)->getFormat() : NULL; 156 } 157 158 sp<MetaData> MPEG2TSExtractor::getMetaData() { 159 sp<MetaData> meta = new MetaData; 160 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 161 162 return meta; 163 } 164 165 void 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 LOGI("haveAudio=%d, haveVideo=%d", haveAudio, haveVideo); 203 } 204 205 status_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 219 void MPEG2TSExtractor::setLiveSession(const sp<LiveSession> &liveSession) { 220 Mutex::Autolock autoLock(mLock); 221 222 mLiveSession = liveSession; 223 } 224 225 void 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 235 uint32_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 249 bool 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