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