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