LiveSession.h revision 5abbd3dcbb0bb32a3d4b90dddbcf90458967eb6f
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    };
150
151    struct FetcherInfo {
152        sp<PlaylistFetcher> mFetcher;
153        int64_t mDurationUs;
154        bool mToBeRemoved;
155        bool mToBeResumed;
156    };
157
158    struct StreamItem {
159        const char *mType;
160        AString mUri, mNewUri;
161        SeekMode mSeekMode;
162        size_t mCurDiscontinuitySeq;
163        int64_t mLastDequeuedTimeUs;
164        int64_t mLastSampleDurationUs;
165        StreamItem()
166            : StreamItem("") {}
167        StreamItem(const char *type)
168            : mType(type),
169              mSeekMode(kSeekModeExactPosition) {
170                  reset();
171              }
172        void reset() {
173            mCurDiscontinuitySeq = 0;
174            mLastDequeuedTimeUs = -1ll;
175            mLastSampleDurationUs = 0ll;
176        }
177        AString uriKey() {
178            AString key(mType);
179            key.append("URI");
180            return key;
181        }
182    };
183    StreamItem mStreams[kMaxStreams];
184
185    sp<AMessage> mNotify;
186    uint32_t mFlags;
187    sp<IMediaHTTPService> mHTTPService;
188
189    bool mBuffering;
190    bool mInPreparationPhase;
191    int32_t mPollBufferingGeneration;
192    int32_t mPrevBufferPercentage;
193
194    KeyedVector<String8, String8> mExtraHeaders;
195
196    AString mMasterURL;
197
198    Vector<BandwidthItem> mBandwidthItems;
199    ssize_t mCurBandwidthIndex;
200    ssize_t mOrigBandwidthIndex;
201    int32_t mLastBandwidthBps;
202    sp<BandwidthEstimator> mBandwidthEstimator;
203
204    sp<M3UParser> mPlaylist;
205    int32_t mMaxWidth;
206    int32_t mMaxHeight;
207
208    sp<ALooper> mFetcherLooper;
209    KeyedVector<AString, FetcherInfo> mFetcherInfos;
210    uint32_t mStreamMask;
211
212    // Masks used during reconfiguration:
213    // mNewStreamMask: streams in the variant playlist we're switching to;
214    // we don't want to immediately overwrite the original value.
215    uint32_t mNewStreamMask;
216
217    // mSwapMask: streams that have started to playback content in the new variant playlist;
218    // we use this to track reconfiguration progress.
219    uint32_t mSwapMask;
220
221    KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources;
222    // A second set of packet sources that buffer content for the variant we're switching to.
223    KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources2;
224
225    int32_t mSwitchGeneration;
226    int32_t mSubtitleGeneration;
227
228    size_t mContinuationCounter;
229    sp<AMessage> mContinuation;
230    sp<AMessage> mSeekReply;
231
232    int64_t mLastDequeuedTimeUs;
233    int64_t mRealTimeBaseUs;
234
235    bool mReconfigurationInProgress;
236    bool mSwitchInProgress;
237    int64_t mUpSwitchMark;
238    int64_t mDownSwitchMark;
239    int64_t mUpSwitchMargin;
240
241    sp<AReplyToken> mDisconnectReplyID;
242    sp<AReplyToken> mSeekReplyID;
243
244    bool mFirstTimeUsValid;
245    int64_t mFirstTimeUs;
246    int64_t mLastSeekTimeUs;
247    bool mHasMetadata;
248
249    KeyedVector<size_t, int64_t> mDiscontinuityAbsStartTimesUs;
250    KeyedVector<size_t, int64_t> mDiscontinuityOffsetTimesUs;
251
252    sp<PlaylistFetcher> addFetcher(const char *uri);
253
254    void onConnect(const sp<AMessage> &msg);
255    void onMasterPlaylistFetched(const sp<AMessage> &msg);
256    void onSeek(const sp<AMessage> &msg);
257
258    bool UriIsSameAsIndex( const AString &uri, int32_t index, bool newUri);
259    sp<AnotherPacketSource> getPacketSourceForStreamIndex(size_t trackIndex, bool newUri);
260    sp<AnotherPacketSource> getMetadataSource(
261            sp<AnotherPacketSource> sources[kNumSources], uint32_t streamMask, bool newUri);
262
263    bool resumeFetcher(
264            const AString &uri, uint32_t streamMask,
265            int64_t timeUs = -1ll, bool newUri = false);
266
267    float getAbortThreshold(
268            ssize_t currentBWIndex, ssize_t targetBWIndex) const;
269    void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
270    size_t getBandwidthIndex(int32_t bandwidthBps);
271    HLSTime latestMediaSegmentStartTime() const;
272
273    static int SortByBandwidth(const BandwidthItem *, const BandwidthItem *);
274    static StreamType indexToType(int idx);
275    static ssize_t typeToIndex(int32_t type);
276
277    void changeConfiguration(
278            int64_t timeUs, ssize_t bwIndex = -1, bool pickTrack = false);
279    void onChangeConfiguration(const sp<AMessage> &msg);
280    void onChangeConfiguration2(const sp<AMessage> &msg);
281    void onChangeConfiguration3(const sp<AMessage> &msg);
282
283    void swapPacketSource(StreamType stream);
284    void tryToFinishBandwidthSwitch(const AString &oldUri);
285    void cancelBandwidthSwitch(bool resume = false);
286    bool checkSwitchProgress(
287            sp<AMessage> &msg, int64_t delayUs, bool *needResumeUntil);
288
289    bool switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow);
290
291    void schedulePollBuffering();
292    void cancelPollBuffering();
293    void restartPollBuffering();
294    void onPollBuffering();
295    bool checkBuffering(bool &underflow, bool &ready, bool &down, bool &up);
296    void startBufferingIfNecessary();
297    void stopBufferingIfNecessary();
298    void notifyBufferingUpdate(int32_t percentage);
299
300    void finishDisconnect();
301
302    void postPrepared(status_t err);
303    void postError(status_t err);
304
305    DISALLOW_EVIL_CONSTRUCTORS(LiveSession);
306};
307
308}  // namespace android
309
310#endif  // LIVE_SESSION_H_
311