Home | History | Annotate | Download | only in httplive
      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 namespace android {
     27 
     28 struct ABuffer;
     29 struct AnotherPacketSource;
     30 struct DataSource;
     31 struct HTTPBase;
     32 struct IMediaHTTPService;
     33 struct LiveDataSource;
     34 struct M3UParser;
     35 struct PlaylistFetcher;
     36 struct Parcel;
     37 
     38 struct LiveSession : public AHandler {
     39     enum Flags {
     40         // Don't log any URLs.
     41         kFlagIncognito = 1,
     42     };
     43     LiveSession(
     44             const sp<AMessage> &notify,
     45             uint32_t flags,
     46             const sp<IMediaHTTPService> &httpService);
     47 
     48     enum StreamIndex {
     49         kAudioIndex    = 0,
     50         kVideoIndex    = 1,
     51         kSubtitleIndex = 2,
     52         kMaxStreams    = 3,
     53     };
     54 
     55     enum StreamType {
     56         STREAMTYPE_AUDIO        = 1 << kAudioIndex,
     57         STREAMTYPE_VIDEO        = 1 << kVideoIndex,
     58         STREAMTYPE_SUBTITLES    = 1 << kSubtitleIndex,
     59     };
     60     status_t dequeueAccessUnit(StreamType stream, sp<ABuffer> *accessUnit);
     61 
     62     status_t getStreamFormat(StreamType stream, sp<AMessage> *format);
     63 
     64     void connectAsync(
     65             const char *url,
     66             const KeyedVector<String8, String8> *headers = NULL);
     67 
     68     status_t disconnect();
     69 
     70     // Blocks until seek is complete.
     71     status_t seekTo(int64_t timeUs);
     72 
     73     status_t getDuration(int64_t *durationUs) const;
     74     size_t getTrackCount() const;
     75     sp<AMessage> getTrackInfo(size_t trackIndex) const;
     76     status_t selectTrack(size_t index, bool select);
     77     ssize_t getSelectedTrack(media_track_type /* type */) const;
     78 
     79     bool isSeekable() const;
     80     bool hasDynamicDuration() const;
     81 
     82     enum {
     83         kWhatStreamsChanged,
     84         kWhatError,
     85         kWhatPrepared,
     86         kWhatPreparationFailed,
     87     };
     88 
     89     // create a format-change discontinuity
     90     //
     91     // swap:
     92     //   whether is format-change discontinuity should trigger a buffer swap
     93     sp<ABuffer> createFormatChangeBuffer(bool swap = true);
     94 protected:
     95     virtual ~LiveSession();
     96 
     97     virtual void onMessageReceived(const sp<AMessage> &msg);
     98 
     99 private:
    100     friend struct PlaylistFetcher;
    101 
    102     enum {
    103         kWhatConnect                    = 'conn',
    104         kWhatDisconnect                 = 'disc',
    105         kWhatSeek                       = 'seek',
    106         kWhatFetcherNotify              = 'notf',
    107         kWhatCheckBandwidth             = 'bndw',
    108         kWhatChangeConfiguration        = 'chC0',
    109         kWhatChangeConfiguration2       = 'chC2',
    110         kWhatChangeConfiguration3       = 'chC3',
    111         kWhatFinishDisconnect2          = 'fin2',
    112         kWhatSwapped                    = 'swap',
    113         kWhatCheckSwitchDown            = 'ckSD',
    114         kWhatSwitchDown                 = 'sDwn',
    115     };
    116 
    117     static const size_t kBandwidthHistoryBytes;
    118 
    119     struct BandwidthItem {
    120         size_t mPlaylistIndex;
    121         unsigned long mBandwidth;
    122     };
    123 
    124     struct FetcherInfo {
    125         sp<PlaylistFetcher> mFetcher;
    126         int64_t mDurationUs;
    127         bool mIsPrepared;
    128         bool mToBeRemoved;
    129     };
    130 
    131     struct StreamItem {
    132         const char *mType;
    133         AString mUri, mNewUri;
    134         size_t mCurDiscontinuitySeq;
    135         int64_t mLastDequeuedTimeUs;
    136         int64_t mLastSampleDurationUs;
    137         StreamItem()
    138             : mType(""),
    139               mCurDiscontinuitySeq(0),
    140               mLastDequeuedTimeUs(0),
    141               mLastSampleDurationUs(0) {}
    142         StreamItem(const char *type)
    143             : mType(type),
    144               mCurDiscontinuitySeq(0),
    145               mLastDequeuedTimeUs(0),
    146               mLastSampleDurationUs(0) {}
    147         AString uriKey() {
    148             AString key(mType);
    149             key.append("URI");
    150             return key;
    151         }
    152     };
    153     StreamItem mStreams[kMaxStreams];
    154 
    155     sp<AMessage> mNotify;
    156     uint32_t mFlags;
    157     sp<IMediaHTTPService> mHTTPService;
    158 
    159     bool mInPreparationPhase;
    160     bool mBuffering[kMaxStreams];
    161 
    162     sp<HTTPBase> mHTTPDataSource;
    163     KeyedVector<String8, String8> mExtraHeaders;
    164 
    165     AString mMasterURL;
    166 
    167     Vector<BandwidthItem> mBandwidthItems;
    168     ssize_t mCurBandwidthIndex;
    169 
    170     sp<M3UParser> mPlaylist;
    171 
    172     KeyedVector<AString, FetcherInfo> mFetcherInfos;
    173     uint32_t mStreamMask;
    174 
    175     // Masks used during reconfiguration:
    176     // mNewStreamMask: streams in the variant playlist we're switching to;
    177     // we don't want to immediately overwrite the original value.
    178     uint32_t mNewStreamMask;
    179 
    180     // mSwapMask: streams that have started to playback content in the new variant playlist;
    181     // we use this to track reconfiguration progress.
    182     uint32_t mSwapMask;
    183 
    184     KeyedVector<StreamType, sp<AnotherPacketSource> > mDiscontinuities;
    185     KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources;
    186     // A second set of packet sources that buffer content for the variant we're switching to.
    187     KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources2;
    188 
    189     // A mutex used to serialize two sets of events:
    190     // * the swapping of packet sources in dequeueAccessUnit on the player thread, AND
    191     // * a forced bandwidth switch termination in cancelSwitch on the live looper.
    192     Mutex mSwapMutex;
    193 
    194     int32_t mCheckBandwidthGeneration;
    195     int32_t mSwitchGeneration;
    196     int32_t mSubtitleGeneration;
    197 
    198     size_t mContinuationCounter;
    199     sp<AMessage> mContinuation;
    200     sp<AMessage> mSeekReply;
    201 
    202     int64_t mLastDequeuedTimeUs;
    203     int64_t mRealTimeBaseUs;
    204 
    205     bool mReconfigurationInProgress;
    206     bool mSwitchInProgress;
    207     uint32_t mDisconnectReplyID;
    208     uint32_t mSeekReplyID;
    209 
    210     bool mFirstTimeUsValid;
    211     int64_t mFirstTimeUs;
    212     int64_t mLastSeekTimeUs;
    213     sp<AMessage> mSwitchDownMonitor;
    214     KeyedVector<size_t, int64_t> mDiscontinuityAbsStartTimesUs;
    215     KeyedVector<size_t, int64_t> mDiscontinuityOffsetTimesUs;
    216 
    217     sp<PlaylistFetcher> addFetcher(const char *uri);
    218 
    219     void onConnect(const sp<AMessage> &msg);
    220     status_t onSeek(const sp<AMessage> &msg);
    221     void onFinishDisconnect2();
    222 
    223     // If given a non-zero block_size (default 0), it is used to cap the number of
    224     // bytes read in from the DataSource. If given a non-NULL buffer, new content
    225     // is read into the end.
    226     //
    227     // The DataSource we read from is responsible for signaling error or EOF to help us
    228     // break out of the read loop. The DataSource can be returned to the caller, so
    229     // that the caller can reuse it for subsequent fetches (within the initially
    230     // requested range).
    231     //
    232     // For reused HTTP sources, the caller must download a file sequentially without
    233     // any overlaps or gaps to prevent reconnection.
    234     ssize_t fetchFile(
    235             const char *url, sp<ABuffer> *out,
    236             /* request/open a file starting at range_offset for range_length bytes */
    237             int64_t range_offset = 0, int64_t range_length = -1,
    238             /* download block size */
    239             uint32_t block_size = 0,
    240             /* reuse DataSource if doing partial fetch */
    241             sp<DataSource> *source = NULL,
    242             String8 *actualUrl = NULL);
    243 
    244     sp<M3UParser> fetchPlaylist(
    245             const char *url, uint8_t *curPlaylistHash, bool *unchanged);
    246 
    247     size_t getBandwidthIndex();
    248     int64_t latestMediaSegmentStartTimeUs();
    249 
    250     static int SortByBandwidth(const BandwidthItem *, const BandwidthItem *);
    251     static StreamType indexToType(int idx);
    252     static ssize_t typeToIndex(int32_t type);
    253 
    254     void changeConfiguration(
    255             int64_t timeUs, size_t bandwidthIndex, bool pickTrack = false);
    256     void onChangeConfiguration(const sp<AMessage> &msg);
    257     void onChangeConfiguration2(const sp<AMessage> &msg);
    258     void onChangeConfiguration3(const sp<AMessage> &msg);
    259     void onSwapped(const sp<AMessage> &msg);
    260     void onCheckSwitchDown();
    261     void onSwitchDown();
    262     void tryToFinishBandwidthSwitch();
    263 
    264     void scheduleCheckBandwidthEvent();
    265     void cancelCheckBandwidthEvent();
    266 
    267     // cancelBandwidthSwitch is atomic wrt swapPacketSource; call it to prevent packet sources
    268     // from being swapped out on stale discontinuities while manipulating
    269     // mPacketSources/mPacketSources2.
    270     void cancelBandwidthSwitch();
    271 
    272     bool canSwitchBandwidthTo(size_t bandwidthIndex);
    273     void onCheckBandwidth(const sp<AMessage> &msg);
    274 
    275     void finishDisconnect();
    276 
    277     void postPrepared(status_t err);
    278 
    279     void swapPacketSource(StreamType stream);
    280     bool canSwitchUp();
    281 
    282     DISALLOW_EVIL_CONSTRUCTORS(LiveSession);
    283 };
    284 
    285 }  // namespace android
    286 
    287 #endif  // LIVE_SESSION_H_
    288