LiveSession.h revision 98d53011c390ab0c3cb8d5d9e47251876174d5d4
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 LiveSession( 58 const sp<AMessage> ¬ify, 59 uint32_t flags, 60 const sp<IMediaHTTPService> &httpService); 61 62 status_t dequeueAccessUnit(StreamType stream, sp<ABuffer> *accessUnit); 63 64 status_t getStreamFormat(StreamType stream, sp<AMessage> *format); 65 66 void connectAsync( 67 const char *url, 68 const KeyedVector<String8, String8> *headers = NULL); 69 70 status_t disconnect(); 71 72 // Blocks until seek is complete. 73 status_t seekTo(int64_t timeUs); 74 75 status_t getDuration(int64_t *durationUs) const; 76 size_t getTrackCount() const; 77 sp<AMessage> getTrackInfo(size_t trackIndex) const; 78 status_t selectTrack(size_t index, bool select); 79 ssize_t getSelectedTrack(media_track_type /* type */) const; 80 81 bool isSeekable() const; 82 bool hasDynamicDuration() const; 83 84 enum { 85 kWhatStreamsChanged, 86 kWhatError, 87 kWhatPrepared, 88 kWhatPreparationFailed, 89 }; 90 91 // create a format-change discontinuity 92 // 93 // swap: 94 // whether is format-change discontinuity should trigger a buffer swap 95 sp<ABuffer> createFormatChangeBuffer(bool swap = true); 96protected: 97 virtual ~LiveSession(); 98 99 virtual void onMessageReceived(const sp<AMessage> &msg); 100 101private: 102 friend struct PlaylistFetcher; 103 104 enum { 105 kWhatConnect = 'conn', 106 kWhatDisconnect = 'disc', 107 kWhatSeek = 'seek', 108 kWhatFetcherNotify = 'notf', 109 kWhatCheckBandwidth = 'bndw', 110 kWhatChangeConfiguration = 'chC0', 111 kWhatChangeConfiguration2 = 'chC2', 112 kWhatChangeConfiguration3 = 'chC3', 113 kWhatFinishDisconnect2 = 'fin2', 114 kWhatSwapped = 'swap', 115 kWhatPollBuffering = 'poll', 116 }; 117 118 static const size_t kBandwidthHistoryBytes; 119 static const int64_t kHighWaterMark; 120 static const int64_t kMidWaterMark; 121 static const int64_t kLowWaterMark; 122 123 struct BandwidthItem { 124 size_t mPlaylistIndex; 125 unsigned long mBandwidth; 126 }; 127 128 struct FetcherInfo { 129 sp<PlaylistFetcher> mFetcher; 130 int64_t mDurationUs; 131 bool mIsPrepared; 132 bool mToBeRemoved; 133 }; 134 135 struct StreamItem { 136 const char *mType; 137 AString mUri, mNewUri; 138 size_t mCurDiscontinuitySeq; 139 int64_t mLastDequeuedTimeUs; 140 int64_t mLastSampleDurationUs; 141 StreamItem() 142 : mType(""), 143 mCurDiscontinuitySeq(0), 144 mLastDequeuedTimeUs(0), 145 mLastSampleDurationUs(0) {} 146 StreamItem(const char *type) 147 : mType(type), 148 mCurDiscontinuitySeq(0), 149 mLastDequeuedTimeUs(0), 150 mLastSampleDurationUs(0) {} 151 AString uriKey() { 152 AString key(mType); 153 key.append("URI"); 154 return key; 155 } 156 }; 157 StreamItem mStreams[kMaxStreams]; 158 159 sp<AMessage> mNotify; 160 uint32_t mFlags; 161 sp<IMediaHTTPService> mHTTPService; 162 163 bool mInPreparationPhase; 164 bool mBuffering[kMaxStreams]; 165 166 sp<HTTPBase> mHTTPDataSource; 167 KeyedVector<String8, String8> mExtraHeaders; 168 169 AString mMasterURL; 170 171 Vector<BandwidthItem> mBandwidthItems; 172 ssize_t mCurBandwidthIndex; 173 174 sp<M3UParser> mPlaylist; 175 176 sp<ALooper> mFetcherLooper; 177 KeyedVector<AString, FetcherInfo> mFetcherInfos; 178 uint32_t mStreamMask; 179 180 // Masks used during reconfiguration: 181 // mNewStreamMask: streams in the variant playlist we're switching to; 182 // we don't want to immediately overwrite the original value. 183 uint32_t mNewStreamMask; 184 185 // mSwapMask: streams that have started to playback content in the new variant playlist; 186 // we use this to track reconfiguration progress. 187 uint32_t mSwapMask; 188 189 KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources; 190 // A second set of packet sources that buffer content for the variant we're switching to. 191 KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources2; 192 193 // A mutex used to serialize two sets of events: 194 // * the swapping of packet sources in dequeueAccessUnit on the player thread, AND 195 // * a forced bandwidth switch termination in cancelSwitch on the live looper. 196 Mutex mSwapMutex; 197 198 int32_t mCheckBandwidthGeneration; 199 int32_t mSwitchGeneration; 200 int32_t mSubtitleGeneration; 201 202 size_t mContinuationCounter; 203 sp<AMessage> mContinuation; 204 sp<AMessage> mSeekReply; 205 206 int64_t mLastDequeuedTimeUs; 207 int64_t mRealTimeBaseUs; 208 209 bool mReconfigurationInProgress; 210 bool mSwitchInProgress; 211 sp<AReplyToken> mDisconnectReplyID; 212 sp<AReplyToken> mSeekReplyID; 213 214 bool mFirstTimeUsValid; 215 int64_t mFirstTimeUs; 216 int64_t mLastSeekTimeUs; 217 KeyedVector<size_t, int64_t> mDiscontinuityAbsStartTimesUs; 218 KeyedVector<size_t, int64_t> mDiscontinuityOffsetTimesUs; 219 220 int32_t mPollBufferingGeneration; 221 222 sp<PlaylistFetcher> addFetcher(const char *uri); 223 224 void onConnect(const sp<AMessage> &msg); 225 status_t onSeek(const sp<AMessage> &msg); 226 void onFinishDisconnect2(); 227 228 // If given a non-zero block_size (default 0), it is used to cap the number of 229 // bytes read in from the DataSource. If given a non-NULL buffer, new content 230 // is read into the end. 231 // 232 // The DataSource we read from is responsible for signaling error or EOF to help us 233 // break out of the read loop. The DataSource can be returned to the caller, so 234 // that the caller can reuse it for subsequent fetches (within the initially 235 // requested range). 236 // 237 // For reused HTTP sources, the caller must download a file sequentially without 238 // any overlaps or gaps to prevent reconnection. 239 ssize_t fetchFile( 240 const char *url, sp<ABuffer> *out, 241 /* request/open a file starting at range_offset for range_length bytes */ 242 int64_t range_offset = 0, int64_t range_length = -1, 243 /* download block size */ 244 uint32_t block_size = 0, 245 /* reuse DataSource if doing partial fetch */ 246 sp<DataSource> *source = NULL, 247 String8 *actualUrl = NULL); 248 249 sp<M3UParser> fetchPlaylist( 250 const char *url, uint8_t *curPlaylistHash, bool *unchanged); 251 252 size_t getBandwidthIndex(); 253 int64_t latestMediaSegmentStartTimeUs(); 254 255 static int SortByBandwidth(const BandwidthItem *, const BandwidthItem *); 256 static StreamType indexToType(int idx); 257 static ssize_t typeToIndex(int32_t type); 258 259 void changeConfiguration( 260 int64_t timeUs, size_t bandwidthIndex, bool pickTrack = false); 261 void onChangeConfiguration(const sp<AMessage> &msg); 262 void onChangeConfiguration2(const sp<AMessage> &msg); 263 void onChangeConfiguration3(const sp<AMessage> &msg); 264 void onSwapped(const sp<AMessage> &msg); 265 void tryToFinishBandwidthSwitch(); 266 267 // cancelBandwidthSwitch is atomic wrt swapPacketSource; call it to prevent packet sources 268 // from being swapped out on stale discontinuities while manipulating 269 // mPacketSources/mPacketSources2. 270 void cancelBandwidthSwitch(); 271 272 void schedulePollBuffering(); 273 void cancelPollBuffering(); 274 void onPollBuffering(); 275 bool checkBuffering(bool &low, bool &mid, bool &high); 276 void switchBandwidthIfNeeded(bool canSwitchUp); 277 278 void finishDisconnect(); 279 280 void postPrepared(status_t err); 281 282 void swapPacketSource(StreamType stream); 283 284 DISALLOW_EVIL_CONSTRUCTORS(LiveSession); 285}; 286 287} // namespace android 288 289#endif // LIVE_SESSION_H_ 290