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