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 #ifndef LIVE_SESSION_H_ 18 19 #define LIVE_SESSION_H_ 20 21 #include <media/stagefright/foundation/AHandler.h> 22 #include <media/mediaplayer.h> 23 24 #include <utils/String8.h> 25 26 #include "mpeg2ts/ATSParser.h" 27 28 namespace android { 29 30 struct ABuffer; 31 struct AReplyToken; 32 struct AnotherPacketSource; 33 class DataSource; 34 struct HTTPBase; 35 struct IMediaHTTPService; 36 struct LiveDataSource; 37 struct M3UParser; 38 struct PlaylistFetcher; 39 struct HLSTime; 40 struct HTTPDownloader; 41 42 struct LiveSession : public AHandler { 43 enum Flags { 44 // Don't log any URLs. 45 kFlagIncognito = 1, 46 }; 47 48 enum StreamIndex { 49 kAudioIndex = 0, 50 kVideoIndex = 1, 51 kSubtitleIndex = 2, 52 kMaxStreams = 3, 53 kMetaDataIndex = 3, 54 kNumSources = 4, 55 }; 56 57 enum StreamType { 58 STREAMTYPE_AUDIO = 1 << kAudioIndex, 59 STREAMTYPE_VIDEO = 1 << kVideoIndex, 60 STREAMTYPE_SUBTITLES = 1 << kSubtitleIndex, 61 STREAMTYPE_METADATA = 1 << kMetaDataIndex, 62 }; 63 64 enum SeekMode { 65 kSeekModeExactPosition = 0, // used for seeking 66 kSeekModeNextSample = 1, // used for seamless switching 67 kSeekModeNextSegment = 2, // used for seamless switching 68 }; 69 70 LiveSession( 71 const sp<AMessage> ¬ify, 72 uint32_t flags, 73 const sp<IMediaHTTPService> &httpService); 74 75 int64_t calculateMediaTimeUs(int64_t firstTimeUs, int64_t timeUs, int32_t discontinuitySeq); 76 status_t dequeueAccessUnit(StreamType stream, sp<ABuffer> *accessUnit); 77 78 status_t getStreamFormatMeta(StreamType stream, sp<MetaData> *meta); 79 80 sp<HTTPDownloader> getHTTPDownloader(); 81 82 void connectAsync( 83 const char *url, 84 const KeyedVector<String8, String8> *headers = NULL); 85 86 status_t disconnect(); 87 88 // Blocks until seek is complete. 89 status_t seekTo(int64_t timeUs); 90 91 status_t getDuration(int64_t *durationUs) const; 92 size_t getTrackCount() const; 93 sp<AMessage> getTrackInfo(size_t trackIndex) const; 94 status_t selectTrack(size_t index, bool select); 95 ssize_t getSelectedTrack(media_track_type /* type */) const; 96 97 bool isSeekable() const; 98 bool hasDynamicDuration() const; 99 100 static const char *getKeyForStream(StreamType type); 101 static const char *getNameForStream(StreamType type); 102 static ATSParser::SourceType getSourceTypeForStream(StreamType type); 103 104 enum { 105 kWhatStreamsChanged, 106 kWhatError, 107 kWhatPrepared, 108 kWhatPreparationFailed, 109 kWhatBufferingStart, 110 kWhatBufferingEnd, 111 kWhatBufferingUpdate, 112 kWhatMetadataDetected, 113 }; 114 115 protected: 116 virtual ~LiveSession(); 117 118 virtual void onMessageReceived(const sp<AMessage> &msg); 119 120 private: 121 friend struct PlaylistFetcher; 122 123 enum { 124 kWhatConnect = 'conn', 125 kWhatDisconnect = 'disc', 126 kWhatSeek = 'seek', 127 kWhatFetcherNotify = 'notf', 128 kWhatChangeConfiguration = 'chC0', 129 kWhatChangeConfiguration2 = 'chC2', 130 kWhatChangeConfiguration3 = 'chC3', 131 kWhatPollBuffering = 'poll', 132 }; 133 134 // Bandwidth Switch Mark Defaults 135 static const int64_t kUpSwitchMarkUs; 136 static const int64_t kDownSwitchMarkUs; 137 static const int64_t kUpSwitchMarginUs; 138 static const int64_t kResumeThresholdUs; 139 140 // Buffer Prepare/Ready/Underflow Marks 141 static const int64_t kReadyMarkUs; 142 static const int64_t kPrepareMarkUs; 143 static const int64_t kUnderflowMarkUs; 144 145 struct BandwidthEstimator; 146 struct BandwidthItem { 147 size_t mPlaylistIndex; 148 unsigned long mBandwidth; 149 int64_t mLastFailureUs; 150 }; 151 152 struct FetcherInfo { 153 sp<PlaylistFetcher> mFetcher; 154 int64_t mDurationUs; 155 bool mToBeRemoved; 156 bool mToBeResumed; 157 }; 158 159 struct StreamItem { 160 const char *mType; 161 AString mUri, mNewUri; 162 SeekMode mSeekMode; 163 size_t mCurDiscontinuitySeq; 164 int64_t mLastDequeuedTimeUs; 165 int64_t mLastSampleDurationUs; StreamItemLiveSession::StreamItem166 StreamItem() 167 : StreamItem("") {} StreamItemLiveSession::StreamItem168 StreamItem(const char *type) 169 : mType(type), 170 mSeekMode(kSeekModeExactPosition) { 171 reset(); 172 } resetLiveSession::StreamItem173 void reset() { 174 mCurDiscontinuitySeq = 0; 175 mLastDequeuedTimeUs = -1ll; 176 mLastSampleDurationUs = 0ll; 177 } uriKeyLiveSession::StreamItem178 AString uriKey() { 179 AString key(mType); 180 key.append("URI"); 181 return key; 182 } 183 }; 184 StreamItem mStreams[kMaxStreams]; 185 186 sp<AMessage> mNotify; 187 uint32_t mFlags; 188 sp<IMediaHTTPService> mHTTPService; 189 190 bool mBuffering; 191 bool mInPreparationPhase; 192 int32_t mPollBufferingGeneration; 193 int32_t mPrevBufferPercentage; 194 195 KeyedVector<String8, String8> mExtraHeaders; 196 197 AString mMasterURL; 198 199 Vector<BandwidthItem> mBandwidthItems; 200 ssize_t mCurBandwidthIndex; 201 ssize_t mOrigBandwidthIndex; 202 int32_t mLastBandwidthBps; 203 bool mLastBandwidthStable; 204 sp<BandwidthEstimator> mBandwidthEstimator; 205 206 sp<M3UParser> mPlaylist; 207 int32_t mMaxWidth; 208 int32_t mMaxHeight; 209 210 sp<ALooper> mFetcherLooper; 211 KeyedVector<AString, FetcherInfo> mFetcherInfos; 212 uint32_t mStreamMask; 213 214 // Masks used during reconfiguration: 215 // mNewStreamMask: streams in the variant playlist we're switching to; 216 // we don't want to immediately overwrite the original value. 217 uint32_t mNewStreamMask; 218 219 // mSwapMask: streams that have started to playback content in the new variant playlist; 220 // we use this to track reconfiguration progress. 221 uint32_t mSwapMask; 222 223 KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources; 224 // A second set of packet sources that buffer content for the variant we're switching to. 225 KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources2; 226 227 int32_t mSwitchGeneration; 228 int32_t mSubtitleGeneration; 229 230 size_t mContinuationCounter; 231 sp<AMessage> mContinuation; 232 sp<AMessage> mSeekReply; 233 234 int64_t mLastDequeuedTimeUs; 235 int64_t mRealTimeBaseUs; 236 237 bool mReconfigurationInProgress; 238 bool mSwitchInProgress; 239 int64_t mUpSwitchMark; 240 int64_t mDownSwitchMark; 241 int64_t mUpSwitchMargin; 242 243 sp<AReplyToken> mDisconnectReplyID; 244 sp<AReplyToken> mSeekReplyID; 245 246 bool mFirstTimeUsValid; 247 int64_t mFirstTimeUs; 248 int64_t mLastSeekTimeUs; 249 bool mHasMetadata; 250 251 KeyedVector<size_t, int64_t> mDiscontinuityAbsStartTimesUs; 252 KeyedVector<size_t, int64_t> mDiscontinuityOffsetTimesUs; 253 254 sp<PlaylistFetcher> addFetcher(const char *uri); 255 256 void onConnect(const sp<AMessage> &msg); 257 void onMasterPlaylistFetched(const sp<AMessage> &msg); 258 void onSeek(const sp<AMessage> &msg); 259 260 bool UriIsSameAsIndex( const AString &uri, int32_t index, bool newUri); 261 sp<AnotherPacketSource> getPacketSourceForStreamIndex(size_t trackIndex, bool newUri); 262 sp<AnotherPacketSource> getMetadataSource( 263 sp<AnotherPacketSource> sources[kNumSources], uint32_t streamMask, bool newUri); 264 265 bool resumeFetcher( 266 const AString &uri, uint32_t streamMask, 267 int64_t timeUs = -1ll, bool newUri = false); 268 269 float getAbortThreshold( 270 ssize_t currentBWIndex, ssize_t targetBWIndex) const; 271 void addBandwidthMeasurement(size_t numBytes, int64_t delayUs); 272 size_t getBandwidthIndex(int32_t bandwidthBps); 273 ssize_t getLowestValidBandwidthIndex() const; 274 HLSTime latestMediaSegmentStartTime() const; 275 276 static bool isBandwidthValid(const BandwidthItem &item); 277 static int SortByBandwidth(const BandwidthItem *, const BandwidthItem *); 278 static StreamType indexToType(int idx); 279 static ssize_t typeToIndex(int32_t type); 280 281 void changeConfiguration( 282 int64_t timeUs, ssize_t bwIndex = -1, bool pickTrack = false); 283 void onChangeConfiguration(const sp<AMessage> &msg); 284 void onChangeConfiguration2(const sp<AMessage> &msg); 285 void onChangeConfiguration3(const sp<AMessage> &msg); 286 287 void swapPacketSource(StreamType stream); 288 void tryToFinishBandwidthSwitch(const AString &oldUri); 289 void cancelBandwidthSwitch(bool resume = false); 290 bool checkSwitchProgress( 291 sp<AMessage> &msg, int64_t delayUs, bool *needResumeUntil); 292 293 bool switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow); 294 bool tryBandwidthFallback(); 295 296 void schedulePollBuffering(); 297 void cancelPollBuffering(); 298 void restartPollBuffering(); 299 void onPollBuffering(); 300 bool checkBuffering(bool &underflow, bool &ready, bool &down, bool &up); 301 void startBufferingIfNecessary(); 302 void stopBufferingIfNecessary(); 303 void notifyBufferingUpdate(int32_t percentage); 304 305 void finishDisconnect(); 306 307 void postPrepared(status_t err); 308 void postError(status_t err); 309 310 DISALLOW_EVIL_CONSTRUCTORS(LiveSession); 311 }; 312 313 } // namespace android 314 315 #endif // LIVE_SESSION_H_ 316