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