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