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