Home | History | Annotate | Download | only in httplive
      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> &notify,
     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> &params);
     82 
     83     void fetchPlaylistAsync();
     84 
     85     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     bool mStartup;
    149     bool mIDRFound;
    150     int32_t mSeekMode;
    151     bool mTimeChangeSignaled;
    152     int64_t mNextPTSTimeUs;
    153 
    154     int32_t mMonitorQueueGeneration;
    155     const int32_t mSubtitleGeneration;
    156 
    157     int32_t mLastDiscontinuitySeq;
    158 
    159     enum RefreshState {
    160         INITIAL_MINIMUM_RELOAD_DELAY,
    161         FIRST_UNCHANGED_RELOAD_ATTEMPT,
    162         SECOND_UNCHANGED_RELOAD_ATTEMPT,
    163         THIRD_UNCHANGED_RELOAD_ATTEMPT
    164     };
    165     RefreshState mRefreshState;
    166 
    167     uint8_t mPlaylistHash[16];
    168 
    169     sp<ATSParser> mTSParser;
    170 
    171     bool mFirstPTSValid;
    172     int64_t mFirstTimeUs;
    173     int64_t mSegmentFirstPTS;
    174     sp<AnotherPacketSource> mVideoBuffer;
    175 
    176     // Stores the initialization vector to decrypt the next block of cipher text, which can
    177     // either be derived from the sequence number, read from the manifest, or copied from
    178     // the last block of cipher text (cipher-block chaining).
    179     unsigned char mAESInitVec[AES_BLOCK_SIZE];
    180     unsigned char mKeyData[AES_BLOCK_SIZE];
    181     bool mSampleAesKeyItemChanged;
    182     sp<AMessage> mSampleAesKeyItem;
    183 
    184     Mutex mThresholdLock;
    185     float mThresholdRatio;
    186 
    187     sp<DownloadState> mDownloadState;
    188 
    189     bool mHasMetadata;
    190 
    191     // Set first to true if decrypting the first segment of a playlist segment. When
    192     // first is true, reset the initialization vector based on the available
    193     // information in the manifest; otherwise, use the initialization vector as
    194     // updated by the last call to AES_cbc_encrypt.
    195     //
    196     // For the input to decrypt correctly, decryptBuffer must be called on
    197     // consecutive byte ranges on block boundaries, e.g. 0..15, 16..47, 48..63,
    198     // and so on.
    199     status_t decryptBuffer(
    200             size_t playlistIndex, const sp<ABuffer> &buffer,
    201             bool first = true);
    202     status_t checkDecryptPadding(const sp<ABuffer> &buffer);
    203 
    204     void postMonitorQueue(int64_t delayUs = 0, int64_t minDelayUs = 0);
    205     void cancelMonitorQueue();
    206     void setStoppingThreshold(float thresholdRatio, bool disconnect);
    207     void resetStoppingThreshold(bool disconnect);
    208     float getStoppingThreshold();
    209     bool shouldPauseDownload();
    210 
    211     int64_t delayUsToRefreshPlaylist() const;
    212     status_t refreshPlaylist();
    213 
    214     // Returns the media time in us of the segment specified by seqNumber.
    215     // This is computed by summing the durations of all segments before it.
    216     int64_t getSegmentStartTimeUs(int32_t seqNumber) const;
    217     // Returns the duration time in us of the segment specified.
    218     int64_t getSegmentDurationUs(int32_t seqNumber) const;
    219 
    220     status_t onStart(const sp<AMessage> &msg);
    221     void onPause();
    222     void onStop(const sp<AMessage> &msg);
    223     void onMonitorQueue();
    224     void onDownloadNext();
    225     void initSeqNumberForLiveStream(
    226             int32_t &firstSeqNumberInPlaylist,
    227             int32_t &lastSeqNumberInPlaylist);
    228     bool initDownloadState(
    229             AString &uri,
    230             sp<AMessage> &itemMeta,
    231             int32_t &firstSeqNumberInPlaylist,
    232             int32_t &lastSeqNumberInPlaylist);
    233 
    234     // Resume a fetcher to continue until the stopping point stored in msg.
    235     status_t onResumeUntil(const sp<AMessage> &msg);
    236 
    237     const sp<ABuffer> &setAccessUnitProperties(
    238             const sp<ABuffer> &accessUnit,
    239             const sp<AnotherPacketSource> &source,
    240             bool discard = false);
    241     bool isStartTimeReached(int64_t timeUs);
    242     status_t extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &buffer);
    243 
    244     status_t extractAndQueueAccessUnits(
    245             const sp<ABuffer> &buffer, const sp<AMessage> &itemMeta);
    246 
    247     void notifyStopReached();
    248     void notifyError(status_t err);
    249 
    250     void queueDiscontinuity(
    251             ATSParser::DiscontinuityType type, const sp<AMessage> &extra);
    252 
    253     bool adjustSeqNumberWithAnchorTime(int64_t anchorTimeUs);
    254     int32_t getSeqNumberForDiscontinuity(size_t discontinuitySeq) const;
    255     int32_t getSeqNumberForTime(int64_t timeUs) const;
    256 
    257     void updateDuration();
    258     void updateTargetDuration();
    259 
    260     DISALLOW_EVIL_CONSTRUCTORS(PlaylistFetcher);
    261 };
    262 
    263 }  // namespace android
    264 
    265 #endif  // PLAYLIST_FETCHER_H_
    266 
    267