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 "HTTPLiveSource" 19 #include <utils/Log.h> 20 21 #include "HTTPLiveSource.h" 22 23 #include "ATSParser.h" 24 #include "AnotherPacketSource.h" 25 #include "LiveDataSource.h" 26 #include "LiveSession.h" 27 28 #include <media/stagefright/foundation/ABuffer.h> 29 #include <media/stagefright/foundation/ADebug.h> 30 #include <media/stagefright/foundation/AMessage.h> 31 #include <media/stagefright/MediaErrors.h> 32 #include <media/stagefright/MetaData.h> 33 34 namespace android { 35 36 NuPlayer::HTTPLiveSource::HTTPLiveSource( 37 const sp<AMessage> ¬ify, 38 const char *url, 39 const KeyedVector<String8, String8> *headers, 40 bool uidValid, uid_t uid) 41 : Source(notify), 42 mURL(url), 43 mUIDValid(uidValid), 44 mUID(uid), 45 mFlags(0), 46 mFinalResult(OK), 47 mOffset(0) { 48 if (headers) { 49 mExtraHeaders = *headers; 50 51 ssize_t index = 52 mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log")); 53 54 if (index >= 0) { 55 mFlags |= kFlagIncognito; 56 57 mExtraHeaders.removeItemsAt(index); 58 } 59 } 60 } 61 62 NuPlayer::HTTPLiveSource::~HTTPLiveSource() { 63 if (mLiveSession != NULL) { 64 mLiveSession->disconnect(); 65 mLiveLooper->stop(); 66 } 67 } 68 69 void NuPlayer::HTTPLiveSource::prepareAsync() { 70 mLiveLooper = new ALooper; 71 mLiveLooper->setName("http live"); 72 mLiveLooper->start(); 73 74 sp<AMessage> notify = new AMessage(kWhatSessionNotify, id()); 75 76 mLiveSession = new LiveSession( 77 notify, 78 (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0, 79 mUIDValid, mUID); 80 81 mLiveLooper->registerHandler(mLiveSession); 82 83 mLiveSession->connect( 84 mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders); 85 86 mTSParser = new ATSParser; 87 } 88 89 void NuPlayer::HTTPLiveSource::start() { 90 } 91 92 sp<MetaData> NuPlayer::HTTPLiveSource::getFormatMeta(bool audio) { 93 ATSParser::SourceType type = 94 audio ? ATSParser::AUDIO : ATSParser::VIDEO; 95 96 sp<AnotherPacketSource> source = 97 static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get()); 98 99 if (source == NULL) { 100 return NULL; 101 } 102 103 return source->getFormat(); 104 } 105 106 status_t NuPlayer::HTTPLiveSource::feedMoreTSData() { 107 if (mFinalResult != OK) { 108 return mFinalResult; 109 } 110 111 sp<LiveDataSource> source = 112 static_cast<LiveDataSource *>(mLiveSession->getDataSource().get()); 113 114 for (int32_t i = 0; i < 50; ++i) { 115 char buffer[188]; 116 ssize_t n = source->readAtNonBlocking(mOffset, buffer, sizeof(buffer)); 117 118 if (n == -EWOULDBLOCK) { 119 break; 120 } else if (n < 0) { 121 if (n != ERROR_END_OF_STREAM) { 122 ALOGI("input data EOS reached, error %ld", n); 123 } else { 124 ALOGI("input data EOS reached."); 125 } 126 mTSParser->signalEOS(n); 127 mFinalResult = n; 128 break; 129 } else { 130 if (buffer[0] == 0x00) { 131 // XXX legacy 132 133 uint8_t type = buffer[1]; 134 135 sp<AMessage> extra = new AMessage; 136 137 if (type & 2) { 138 int64_t mediaTimeUs; 139 memcpy(&mediaTimeUs, &buffer[2], sizeof(mediaTimeUs)); 140 141 extra->setInt64(IStreamListener::kKeyMediaTimeUs, mediaTimeUs); 142 } 143 144 mTSParser->signalDiscontinuity( 145 ((type & 1) == 0) 146 ? ATSParser::DISCONTINUITY_SEEK 147 : ATSParser::DISCONTINUITY_FORMATCHANGE, 148 extra); 149 } else { 150 status_t err = mTSParser->feedTSPacket(buffer, sizeof(buffer)); 151 152 if (err != OK) { 153 ALOGE("TS Parser returned error %d", err); 154 mTSParser->signalEOS(err); 155 mFinalResult = err; 156 break; 157 } 158 } 159 160 mOffset += n; 161 } 162 } 163 164 return OK; 165 } 166 167 status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit( 168 bool audio, sp<ABuffer> *accessUnit) { 169 ATSParser::SourceType type = 170 audio ? ATSParser::AUDIO : ATSParser::VIDEO; 171 172 sp<AnotherPacketSource> source = 173 static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get()); 174 175 if (source == NULL) { 176 return -EWOULDBLOCK; 177 } 178 179 status_t finalResult; 180 if (!source->hasBufferAvailable(&finalResult)) { 181 return finalResult == OK ? -EWOULDBLOCK : finalResult; 182 } 183 184 return source->dequeueAccessUnit(accessUnit); 185 } 186 187 status_t NuPlayer::HTTPLiveSource::getDuration(int64_t *durationUs) { 188 return mLiveSession->getDuration(durationUs); 189 } 190 191 status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) { 192 // We need to make sure we're not seeking until we have seen the very first 193 // PTS timestamp in the whole stream (from the beginning of the stream). 194 while (!mTSParser->PTSTimeDeltaEstablished() && feedMoreTSData() == OK) { 195 usleep(100000); 196 } 197 198 mLiveSession->seekTo(seekTimeUs); 199 200 return OK; 201 } 202 203 void NuPlayer::HTTPLiveSource::onMessageReceived(const sp<AMessage> &msg) { 204 switch (msg->what()) { 205 case kWhatSessionNotify: 206 { 207 onSessionNotify(msg); 208 break; 209 } 210 211 default: 212 Source::onMessageReceived(msg); 213 break; 214 } 215 } 216 217 void NuPlayer::HTTPLiveSource::onSessionNotify(const sp<AMessage> &msg) { 218 int32_t what; 219 CHECK(msg->findInt32("what", &what)); 220 221 switch (what) { 222 case LiveSession::kWhatPrepared: 223 { 224 notifyVideoSizeChanged(0, 0); 225 226 uint32_t flags = FLAG_CAN_PAUSE; 227 if (mLiveSession->isSeekable()) { 228 flags |= FLAG_CAN_SEEK; 229 flags |= FLAG_CAN_SEEK_BACKWARD; 230 flags |= FLAG_CAN_SEEK_FORWARD; 231 } 232 233 if (mLiveSession->hasDynamicDuration()) { 234 flags |= FLAG_DYNAMIC_DURATION; 235 } 236 237 notifyFlagsChanged(flags); 238 239 notifyPrepared(); 240 break; 241 } 242 243 case LiveSession::kWhatPreparationFailed: 244 { 245 status_t err; 246 CHECK(msg->findInt32("err", &err)); 247 248 notifyPrepared(err); 249 break; 250 } 251 252 default: 253 TRESPASS(); 254 } 255 } 256 257 } // namespace android 258 259