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 
     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 
     84     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