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