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