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