1 /*
2  * Copyright (C) 2012 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 PLAYLIST_FETCHER_H_
18 
19 #define PLAYLIST_FETCHER_H_
20 
21 #include <media/stagefright/foundation/AHandler.h>
22 
23 #include "mpeg2ts/ATSParser.h"
24 #include "LiveSession.h"
25 
26 namespace android {
27 
28 struct ABuffer;
29 struct AnotherPacketSource;
30 class DataSource;
31 struct HTTPBase;
32 struct LiveDataSource;
33 struct M3UParser;
34 class String8;
35 
36 struct PlaylistFetcher : public AHandler {
37     static const int64_t kMinBufferedDurationUs;
38     static const int32_t kDownloadBlockSize;
39     static const int64_t kFetcherResumeThreshold;
40 
41     enum {
42         kWhatStarted,
43         kWhatPaused,
44         kWhatStopped,
45         kWhatError,
46         kWhatDurationUpdate,
47         kWhatTargetDurationUpdate,
48         kWhatPrepared,
49         kWhatPreparationFailed,
50         kWhatStartedAt,
51         kWhatStopReached,
52         kWhatPlaylistFetched,
53         kWhatMetadataDetected,
54     };
55 
56     PlaylistFetcher(
57             const sp<AMessage> &notify,
58             const sp<LiveSession> &session,
59             const char *uri,
60             int32_t id,
61             int32_t subtitleGeneration);
62 
63     int32_t getFetcherID() const;
64 
65     void startAsync(
66             const sp<AnotherPacketSource> &audioSource,
67             const sp<AnotherPacketSource> &videoSource,
68             const sp<AnotherPacketSource> &subtitleSource,
69             const sp<AnotherPacketSource> &metadataSource,
70             int64_t startTimeUs = -1ll,         // starting timestamps
71             int64_t segmentStartTimeUs = -1ll, // starting position within playlist
72             // startTimeUs!=segmentStartTimeUs only when playlist is live
73             int32_t startDiscontinuitySeq = -1,
74             LiveSession::SeekMode seekMode = LiveSession::kSeekModeExactPosition);
75 
76     void pauseAsync(float thresholdRatio, bool disconnect);
77 
78     void stopAsync(bool clear = true);
79 
80     void resumeUntilAsync(const sp<AMessage> &params);
81 
82     void fetchPlaylistAsync();
83 
getStreamTypeMaskPlaylistFetcher84     uint32_t getStreamTypeMask() const {
85         return mStreamTypeMask;
86     }
87 
88 protected:
89     virtual ~PlaylistFetcher();
90     virtual void onMessageReceived(const sp<AMessage> &msg);
91 
92 private:
93     enum {
94         kMaxNumRetries         = 5,
95     };
96 
97     enum {
98         kWhatStart          = 'strt',
99         kWhatPause          = 'paus',
100         kWhatStop           = 'stop',
101         kWhatMonitorQueue   = 'moni',
102         kWhatResumeUntil    = 'rsme',
103         kWhatDownloadNext   = 'dlnx',
104         kWhatFetchPlaylist  = 'flst'
105     };
106 
107     struct DownloadState;
108 
109     static const int64_t kMaxMonitorDelayUs;
110     static const int32_t kNumSkipFrames;
111 
112     static bool bufferStartsWithTsSyncByte(const sp<ABuffer>& buffer);
113     static bool bufferStartsWithWebVTTMagicSequence(const sp<ABuffer>& buffer);
114 
115     // notifications to mSession
116     sp<AMessage> mNotify;
117     sp<AMessage> mStartTimeUsNotify;
118 
119     sp<HTTPDownloader> mHTTPDownloader;
120     sp<LiveSession> mSession;
121     AString mURI;
122 
123     int32_t mFetcherID;
124 
125     uint32_t mStreamTypeMask;
126     int64_t mStartTimeUs;
127 
128     // Start time relative to the beginning of the first segment in the initial
129     // playlist. It's value is initialized to a non-negative value only when we are
130     // adapting or switching tracks.
131     int64_t mSegmentStartTimeUs;
132 
133     int32_t mDiscontinuitySeq;
134     bool mStartTimeUsRelative;
135     sp<AMessage> mStopParams; // message containing the latest timestamps we should fetch.
136 
137     KeyedVector<LiveSession::StreamType, sp<AnotherPacketSource> >
138         mPacketSources;
139 
140     KeyedVector<AString, sp<ABuffer> > mAESKeyForURI;
141 
142     int64_t mLastPlaylistFetchTimeUs;
143     int64_t mPlaylistTimeUs;
144     sp<M3UParser> mPlaylist;
145     int32_t mSeqNumber;
146     int32_t mNumRetries;
147     bool mStartup;
148     bool mIDRFound;
149     int32_t mSeekMode;
150     bool mTimeChangeSignaled;
151     int64_t mNextPTSTimeUs;
152 
153     int32_t mMonitorQueueGeneration;
154     const int32_t mSubtitleGeneration;
155 
156     int32_t mLastDiscontinuitySeq;
157 
158     enum RefreshState {
159         INITIAL_MINIMUM_RELOAD_DELAY,
160         FIRST_UNCHANGED_RELOAD_ATTEMPT,
161         SECOND_UNCHANGED_RELOAD_ATTEMPT,
162         THIRD_UNCHANGED_RELOAD_ATTEMPT
163     };
164     RefreshState mRefreshState;
165 
166     uint8_t mPlaylistHash[16];
167 
168     sp<ATSParser> mTSParser;
169 
170     bool mFirstPTSValid;
171     int64_t mFirstTimeUs;
172     int64_t mSegmentFirstPTS;
173     sp<AnotherPacketSource> mVideoBuffer;
174 
175     // Stores the initialization vector to decrypt the next block of cipher text, which can
176     // either be derived from the sequence number, read from the manifest, or copied from
177     // the last block of cipher text (cipher-block chaining).
178     unsigned char mAESInitVec[16];
179 
180     Mutex mThresholdLock;
181     float mThresholdRatio;
182 
183     sp<DownloadState> mDownloadState;
184 
185     bool mHasMetadata;
186 
187     // Set first to true if decrypting the first segment of a playlist segment. When
188     // first is true, reset the initialization vector based on the available
189     // information in the manifest; otherwise, use the initialization vector as
190     // updated by the last call to AES_cbc_encrypt.
191     //
192     // For the input to decrypt correctly, decryptBuffer must be called on
193     // consecutive byte ranges on block boundaries, e.g. 0..15, 16..47, 48..63,
194     // and so on.
195     status_t decryptBuffer(
196             size_t playlistIndex, const sp<ABuffer> &buffer,
197             bool first = true);
198     status_t checkDecryptPadding(const sp<ABuffer> &buffer);
199 
200     void postMonitorQueue(int64_t delayUs = 0, int64_t minDelayUs = 0);
201     void cancelMonitorQueue();
202     void setStoppingThreshold(float thresholdRatio, bool disconnect);
203     void resetStoppingThreshold(bool disconnect);
204     float getStoppingThreshold();
205     bool shouldPauseDownload();
206 
207     int64_t delayUsToRefreshPlaylist() const;
208     status_t refreshPlaylist();
209 
210     // Returns the media time in us of the segment specified by seqNumber.
211     // This is computed by summing the durations of all segments before it.
212     int64_t getSegmentStartTimeUs(int32_t seqNumber) const;
213     // Returns the duration time in us of the segment specified.
214     int64_t getSegmentDurationUs(int32_t seqNumber) const;
215 
216     status_t onStart(const sp<AMessage> &msg);
217     void onPause();
218     void onStop(const sp<AMessage> &msg);
219     void onMonitorQueue();
220     void onDownloadNext();
221     bool initDownloadState(
222             AString &uri,
223             sp<AMessage> &itemMeta,
224             int32_t &firstSeqNumberInPlaylist,
225             int32_t &lastSeqNumberInPlaylist);
226 
227     // Resume a fetcher to continue until the stopping point stored in msg.
228     status_t onResumeUntil(const sp<AMessage> &msg);
229 
230     const sp<ABuffer> &setAccessUnitProperties(
231             const sp<ABuffer> &accessUnit,
232             const sp<AnotherPacketSource> &source,
233             bool discard = false);
234     bool isStartTimeReached(int64_t timeUs);
235     status_t extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &buffer);
236 
237     status_t extractAndQueueAccessUnits(
238             const sp<ABuffer> &buffer, const sp<AMessage> &itemMeta);
239 
240     void notifyStopReached();
241     void notifyError(status_t err);
242 
243     void queueDiscontinuity(
244             ATSParser::DiscontinuityType type, const sp<AMessage> &extra);
245 
246     bool adjustSeqNumberWithAnchorTime(int64_t anchorTimeUs);
247     int32_t getSeqNumberForDiscontinuity(size_t discontinuitySeq) const;
248     int32_t getSeqNumberForTime(int64_t timeUs) const;
249 
250     void updateDuration();
251     void updateTargetDuration();
252 
253     DISALLOW_EVIL_CONSTRUCTORS(PlaylistFetcher);
254 };
255 
256 }  // namespace android
257 
258 #endif  // PLAYLIST_FETCHER_H_
259 
260