LiveSession.h revision a1151185c7eb3b4c483f7067deba1775fd0a2510
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
26namespace android {
27
28struct ABuffer;
29struct AReplyToken;
30struct AnotherPacketSource;
31struct DataSource;
32struct HTTPBase;
33struct IMediaHTTPService;
34struct LiveDataSource;
35struct M3UParser;
36struct PlaylistFetcher;
37struct HLSTime;
38
39struct LiveSession : public AHandler {
40    enum Flags {
41        // Don't log any URLs.
42        kFlagIncognito = 1,
43    };
44
45    enum StreamIndex {
46        kAudioIndex    = 0,
47        kVideoIndex    = 1,
48        kSubtitleIndex = 2,
49        kMaxStreams    = 3,
50    };
51
52    enum StreamType {
53        STREAMTYPE_AUDIO        = 1 << kAudioIndex,
54        STREAMTYPE_VIDEO        = 1 << kVideoIndex,
55        STREAMTYPE_SUBTITLES    = 1 << kSubtitleIndex,
56    };
57
58    enum SeekMode {
59        kSeekModeExactPosition = 0, // used for seeking
60        kSeekModeNextSample    = 1, // used for seamless switching
61        kSeekModeNextSegment   = 2, // used for seamless switching
62    };
63
64    LiveSession(
65            const sp<AMessage> &notify,
66            uint32_t flags,
67            const sp<IMediaHTTPService> &httpService);
68
69    status_t dequeueAccessUnit(StreamType stream, sp<ABuffer> *accessUnit);
70
71    status_t getStreamFormat(StreamType stream, sp<AMessage> *format);
72
73    sp<HTTPBase> getHTTPDataSource();
74
75    void connectAsync(
76            const char *url,
77            const KeyedVector<String8, String8> *headers = NULL);
78
79    status_t disconnect();
80
81    // Blocks until seek is complete.
82    status_t seekTo(int64_t timeUs);
83
84    status_t getDuration(int64_t *durationUs) const;
85    size_t getTrackCount() const;
86    sp<AMessage> getTrackInfo(size_t trackIndex) const;
87    status_t selectTrack(size_t index, bool select);
88    ssize_t getSelectedTrack(media_track_type /* type */) const;
89
90    bool isSeekable() const;
91    bool hasDynamicDuration() const;
92
93    static const char *getKeyForStream(StreamType type);
94    static const char *getNameForStream(StreamType type);
95
96    enum {
97        kWhatStreamsChanged,
98        kWhatError,
99        kWhatPrepared,
100        kWhatPreparationFailed,
101        kWhatBufferingStart,
102        kWhatBufferingEnd,
103        kWhatBufferingUpdate,
104    };
105
106protected:
107    virtual ~LiveSession();
108
109    virtual void onMessageReceived(const sp<AMessage> &msg);
110
111private:
112    friend struct PlaylistFetcher;
113
114    enum {
115        kWhatConnect                    = 'conn',
116        kWhatDisconnect                 = 'disc',
117        kWhatSeek                       = 'seek',
118        kWhatFetcherNotify              = 'notf',
119        kWhatChangeConfiguration        = 'chC0',
120        kWhatChangeConfiguration2       = 'chC2',
121        kWhatChangeConfiguration3       = 'chC3',
122        kWhatFinishDisconnect2          = 'fin2',
123        kWhatPollBuffering              = 'poll',
124    };
125
126    // Bandwidth Switch Mark Defaults
127    static const int64_t kUpSwitchMarkUs;
128    static const int64_t kDownSwitchMarkUs;
129    static const int64_t kUpSwitchMarginUs;
130    static const int64_t kResumeThresholdUs;
131
132    // Buffer Prepare/Ready/Underflow Marks
133    static const int64_t kReadyMarkUs;
134    static const int64_t kPrepareMarkUs;
135    static const int64_t kUnderflowMarkUs;
136
137    struct BandwidthEstimator;
138    struct BandwidthItem {
139        size_t mPlaylistIndex;
140        unsigned long mBandwidth;
141    };
142
143    struct FetcherInfo {
144        sp<PlaylistFetcher> mFetcher;
145        int64_t mDurationUs;
146        bool mToBeRemoved;
147        bool mToBeResumed;
148    };
149
150    struct StreamItem {
151        const char *mType;
152        AString mUri, mNewUri;
153        SeekMode mSeekMode;
154        size_t mCurDiscontinuitySeq;
155        int64_t mLastDequeuedTimeUs;
156        int64_t mLastSampleDurationUs;
157        StreamItem()
158            : StreamItem("") {}
159        StreamItem(const char *type)
160            : mType(type),
161              mSeekMode(kSeekModeExactPosition),
162              mCurDiscontinuitySeq(0),
163              mLastDequeuedTimeUs(0),
164              mLastSampleDurationUs(0) {}
165        AString uriKey() {
166            AString key(mType);
167            key.append("URI");
168            return key;
169        }
170    };
171    StreamItem mStreams[kMaxStreams];
172
173    sp<AMessage> mNotify;
174    uint32_t mFlags;
175    sp<IMediaHTTPService> mHTTPService;
176
177    bool mBuffering;
178    bool mInPreparationPhase;
179    int32_t mPollBufferingGeneration;
180    int32_t mPrevBufferPercentage;
181
182    sp<HTTPBase> mHTTPDataSource;
183    KeyedVector<String8, String8> mExtraHeaders;
184
185    AString mMasterURL;
186
187    Vector<BandwidthItem> mBandwidthItems;
188    ssize_t mCurBandwidthIndex;
189    ssize_t mOrigBandwidthIndex;
190    int32_t mLastBandwidthBps;
191    sp<BandwidthEstimator> mBandwidthEstimator;
192
193    sp<M3UParser> mPlaylist;
194
195    sp<ALooper> mFetcherLooper;
196    KeyedVector<AString, FetcherInfo> mFetcherInfos;
197    uint32_t mStreamMask;
198
199    // Masks used during reconfiguration:
200    // mNewStreamMask: streams in the variant playlist we're switching to;
201    // we don't want to immediately overwrite the original value.
202    uint32_t mNewStreamMask;
203
204    // mSwapMask: streams that have started to playback content in the new variant playlist;
205    // we use this to track reconfiguration progress.
206    uint32_t mSwapMask;
207
208    KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources;
209    // A second set of packet sources that buffer content for the variant we're switching to.
210    KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources2;
211
212    int32_t mSwitchGeneration;
213    int32_t mSubtitleGeneration;
214
215    size_t mContinuationCounter;
216    sp<AMessage> mContinuation;
217    sp<AMessage> mSeekReply;
218
219    int64_t mLastDequeuedTimeUs;
220    int64_t mRealTimeBaseUs;
221
222    bool mReconfigurationInProgress;
223    bool mSwitchInProgress;
224    int64_t mUpSwitchMark;
225    int64_t mDownSwitchMark;
226    int64_t mUpSwitchMargin;
227
228    sp<AReplyToken> mDisconnectReplyID;
229    sp<AReplyToken> mSeekReplyID;
230
231    bool mFirstTimeUsValid;
232    int64_t mFirstTimeUs;
233    int64_t mLastSeekTimeUs;
234    KeyedVector<size_t, int64_t> mDiscontinuityAbsStartTimesUs;
235    KeyedVector<size_t, int64_t> mDiscontinuityOffsetTimesUs;
236
237    sp<PlaylistFetcher> addFetcher(const char *uri);
238
239    void onConnect(const sp<AMessage> &msg);
240    void onSeek(const sp<AMessage> &msg);
241    void onFinishDisconnect2();
242
243    // If given a non-zero block_size (default 0), it is used to cap the number of
244    // bytes read in from the DataSource. If given a non-NULL buffer, new content
245    // is read into the end.
246    //
247    // The DataSource we read from is responsible for signaling error or EOF to help us
248    // break out of the read loop. The DataSource can be returned to the caller, so
249    // that the caller can reuse it for subsequent fetches (within the initially
250    // requested range).
251    //
252    // For reused HTTP sources, the caller must download a file sequentially without
253    // any overlaps or gaps to prevent reconnection.
254    ssize_t fetchFile(
255            const char *url, sp<ABuffer> *out,
256            /* request/open a file starting at range_offset for range_length bytes */
257            int64_t range_offset = 0, int64_t range_length = -1,
258            /* download block size */
259            uint32_t block_size = 0,
260            /* reuse DataSource if doing partial fetch */
261            sp<DataSource> *source = NULL,
262            String8 *actualUrl = NULL,
263            /* force connect http even when resuing DataSource */
264            bool forceConnectHTTP = false);
265
266    sp<M3UParser> fetchPlaylist(
267            const char *url, uint8_t *curPlaylistHash, bool *unchanged);
268
269    bool resumeFetcher(
270            const AString &uri, uint32_t streamMask,
271            int64_t timeUs = -1ll, bool newUri = false);
272
273    float getAbortThreshold(
274            ssize_t currentBWIndex, ssize_t targetBWIndex) const;
275    void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
276    size_t getBandwidthIndex(int32_t bandwidthBps);
277    HLSTime latestMediaSegmentStartTime() const;
278
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    void switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow);
296
297    void schedulePollBuffering();
298    void cancelPollBuffering();
299    void restartPollBuffering();
300    void onPollBuffering();
301    bool checkBuffering(bool &underflow, bool &ready, bool &down, bool &up);
302    void startBufferingIfNecessary();
303    void stopBufferingIfNecessary();
304    void notifyBufferingUpdate(int32_t percentage);
305
306    void finishDisconnect();
307
308    void postPrepared(status_t err);
309    void postError(status_t err);
310
311    DISALLOW_EVIL_CONSTRUCTORS(LiveSession);
312};
313
314}  // namespace android
315
316#endif  // LIVE_SESSION_H_
317