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