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
28namespace android {
29
30struct ABuffer;
31struct AReplyToken;
32struct AnotherPacketSource;
33class DataSource;
34struct HTTPBase;
35struct IMediaHTTPService;
36struct LiveDataSource;
37struct M3UParser;
38struct PlaylistFetcher;
39struct HLSTime;
40struct HTTPDownloader;
41
42struct 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 getStreamFormat(StreamType stream, sp<AMessage> *format);
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
115protected:
116    virtual ~LiveSession();
117
118    virtual void onMessageReceived(const sp<AMessage> &msg);
119
120private:
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;
166        StreamItem()
167            : StreamItem("") {}
168        StreamItem(const char *type)
169            : mType(type),
170              mSeekMode(kSeekModeExactPosition) {
171                  reset();
172              }
173        void reset() {
174            mCurDiscontinuitySeq = 0;
175            mLastDequeuedTimeUs = -1ll;
176            mLastSampleDurationUs = 0ll;
177        }
178        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