LCOV - code coverage report
Current view: top level - dom/media - MediaCache.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 15 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 11 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef MediaCache_h_
       8             : #define MediaCache_h_
       9             : 
      10             : #include "Intervals.h"
      11             : #include "mozilla/UniquePtr.h"
      12             : #include "nsCOMPtr.h"
      13             : #include "nsHashKeys.h"
      14             : #include "nsTArray.h"
      15             : #include "nsTHashtable.h"
      16             : 
      17             : class nsIPrincipal;
      18             : 
      19             : namespace mozilla {
      20             : // defined in MediaResource.h
      21             : class ChannelMediaResource;
      22             : typedef media::IntervalSet<int64_t> MediaByteRangeSet;
      23             : class MediaResource;
      24             : class ReentrantMonitorAutoEnter;
      25             : 
      26             : /**
      27             :  * Media applications want fast, "on demand" random access to media data,
      28             :  * for pausing, seeking, etc. But we are primarily interested
      29             :  * in transporting media data using HTTP over the Internet, which has
      30             :  * high latency to open a connection, requires a new connection for every
      31             :  * seek, may not even support seeking on some connections (especially
      32             :  * live streams), and uses a push model --- data comes from the server
      33             :  * and you don't have much control over the rate. Also, transferring data
      34             :  * over the Internet can be slow and/or unpredictable, so we want to read
      35             :  * ahead to buffer and cache as much data as possible.
      36             :  *
      37             :  * The job of the media cache is to resolve this impedance mismatch.
      38             :  * The media cache reads data from Necko channels into file-backed storage,
      39             :  * and offers a random-access file-like API to the stream data
      40             :  * (MediaCacheStream). Along the way it solves several problems:
      41             :  * -- The cache intelligently reads ahead to prefetch data that may be
      42             :  * needed in the future
      43             :  * -- The size of the cache is bounded so that we don't fill up
      44             :  * storage with read-ahead data
      45             :  * -- Cache replacement is managed globally so that the most valuable
      46             :  * data (across all streams) is retained
      47             :  * -- The cache can suspend Necko channels temporarily when their data is
      48             :  * not wanted (yet)
      49             :  * -- The cache translates file-like seek requests to HTTP seeks,
      50             :  * including optimizations like not triggering a new seek if it would
      51             :  * be faster to just keep reading until we reach the seek point. The
      52             :  * "seek to EOF" idiom to determine file size is also handled efficiently
      53             :  * (seeking to EOF and then seeking back to the previous offset does not
      54             :  * trigger any Necko activity)
      55             :  * -- The cache also handles the case where the server does not support
      56             :  * seeking
      57             :  * -- Necko can only send data to the main thread, but MediaCacheStream
      58             :  * can distribute data to any thread
      59             :  * -- The cache exposes APIs so clients can detect what data is
      60             :  * currently held
      61             :  *
      62             :  * Note that although HTTP is the most important transport and we only
      63             :  * support transport-level seeking via HTTP byte-ranges, the media cache
      64             :  * works with any kind of Necko channels and provides random access to
      65             :  * cached data even for, e.g., FTP streams.
      66             :  *
      67             :  * The media cache is not persistent. It does not currently allow
      68             :  * data from one load to be used by other loads, either within the same
      69             :  * browser session or across browser sessions. The media cache file
      70             :  * is marked "delete on close" so it will automatically disappear in the
      71             :  * event of a browser crash or shutdown.
      72             :  *
      73             :  * The media cache is block-based. Streams are divided into blocks of a
      74             :  * fixed size (currently 4K) and we cache blocks. A single cache contains
      75             :  * blocks for all streams.
      76             :  *
      77             :  * The cache size is controlled by the media.cache_size preference
      78             :  * (which is in KB). The default size is 500MB.
      79             :  *
      80             :  * The replacement policy predicts a "time of next use" for each block
      81             :  * in the cache. When we need to free a block, the block with the latest
      82             :  * "time of next use" will be evicted. Blocks are divided into
      83             :  * different classes, each class having its own predictor:
      84             :  * FREE_BLOCK: these blocks are effectively infinitely far in the future;
      85             :  * a free block will always be chosen for replacement before other classes
      86             :  * of blocks.
      87             :  * METADATA_BLOCK: these are blocks that contain data that has been read
      88             :  * by the decoder in "metadata mode", e.g. while the decoder is searching
      89             :  * the stream during a seek operation. These blocks are managed with an
      90             :  * LRU policy; the "time of next use" is predicted to be as far in the
      91             :  * future as the last use was in the past.
      92             :  * PLAYED_BLOCK: these are blocks that have not been read in "metadata
      93             :  * mode", and contain data behind the current decoder read point. (They
      94             :  * may not actually have been read by the decoder, if the decoder seeked
      95             :  * forward.) These blocks are managed with an LRU policy except that we add
      96             :  * REPLAY_DELAY seconds of penalty to their predicted "time of next use",
      97             :  * to reflect the uncertainty about whether replay will actually happen
      98             :  * or not.
      99             :  * READAHEAD_BLOCK: these are blocks that have not been read in
     100             :  * "metadata mode" and that are entirely ahead of the current decoder
     101             :  * read point. (They may actually have been read by the decoder in the
     102             :  * past if the decoder has since seeked backward.) We predict the
     103             :  * time of next use for these blocks by assuming steady playback and
     104             :  * dividing the number of bytes between the block and the current decoder
     105             :  * read point by the decoder's estimate of its playback rate in bytes
     106             :  * per second. This ensures that the blocks farthest ahead are considered
     107             :  * least valuable.
     108             :  * For efficient prediction of the "latest time of next use", we maintain
     109             :  * linked lists of blocks in each class, ordering blocks by time of
     110             :  * next use. READAHEAD_BLOCKS have one linked list per stream, since their
     111             :  * time of next use depends on stream parameters, but the other lists
     112             :  * are global.
     113             :  *
     114             :  * A block containing a current decoder read point can contain data
     115             :  * both behind and ahead of the read point. It will be classified as a
     116             :  * PLAYED_BLOCK but we will give it special treatment so it is never
     117             :  * evicted --- it actually contains the highest-priority readahead data
     118             :  * as well as played data.
     119             :  *
     120             :  * "Time of next use" estimates are also used for flow control. When
     121             :  * reading ahead we can predict the time of next use for the data that
     122             :  * will be read. If the predicted time of next use is later then the
     123             :  * prediction for all currently cached blocks, and the cache is full, then
     124             :  * we should suspend reading from the Necko channel.
     125             :  *
     126             :  * Unfortunately suspending the Necko channel can't immediately stop the
     127             :  * flow of data from the server. First our desire to suspend has to be
     128             :  * transmitted to the server (in practice, Necko stops reading from the
     129             :  * socket, which causes the kernel to shrink its advertised TCP receive
     130             :  * window size to zero). Then the server can stop sending the data, but
     131             :  * we will receive data roughly corresponding to the product of the link
     132             :  * bandwidth multiplied by the round-trip latency. We deal with this by
     133             :  * letting the cache overflow temporarily and then trimming it back by
     134             :  * moving overflowing blocks back into the body of the cache, replacing
     135             :  * less valuable blocks as they become available. We try to avoid simply
     136             :  * discarding overflowing readahead data.
     137             :  *
     138             :  * All changes to the actual contents of the cache happen on the main
     139             :  * thread, since that's where Necko's notifications happen.
     140             :  *
     141             :  * The media cache maintains at most one Necko channel for each stream.
     142             :  * (In the future it might be advantageous to relax this, e.g. so that a
     143             :  * seek to near the end of the file can happen without disturbing
     144             :  * the loading of data from the beginning of the file.) The Necko channel
     145             :  * is managed through ChannelMediaResource; MediaCache does not
     146             :  * depend on Necko directly.
     147             :  *
     148             :  * Every time something changes that might affect whether we want to
     149             :  * read from a Necko channel, or whether we want to seek on the Necko
     150             :  * channel --- such as data arriving or data being consumed by the
     151             :  * decoder --- we asynchronously trigger MediaCache::Update on the main
     152             :  * thread. That method implements most cache policy. It evaluates for
     153             :  * each stream whether we want to suspend or resume the stream and what
     154             :  * offset we should seek to, if any. It is also responsible for trimming
     155             :  * back the cache size to its desired limit by moving overflowing blocks
     156             :  * into the main part of the cache.
     157             :  *
     158             :  * Streams can be opened in non-seekable mode. In non-seekable mode,
     159             :  * the cache will only call ChannelMediaResource::CacheClientSeek with
     160             :  * a 0 offset. The cache tries hard not to discard readahead data
     161             :  * for non-seekable streams, since that could trigger a potentially
     162             :  * disastrous re-read of the entire stream. It's up to cache clients
     163             :  * to try to avoid requesting seeks on such streams.
     164             :  *
     165             :  * MediaCache has a single internal monitor for all synchronization.
     166             :  * This is treated as the lowest level monitor in the media code. So,
     167             :  * we must not acquire any MediaDecoder locks or MediaResource locks
     168             :  * while holding the MediaCache lock. But it's OK to hold those locks
     169             :  * and then get the MediaCache lock.
     170             :  *
     171             :  * MediaCache associates a principal with each stream. CacheClientSeek
     172             :  * can trigger new HTTP requests; due to redirects to other domains,
     173             :  * each HTTP load can return data with a different principal. This
     174             :  * principal must be passed to NotifyDataReceived, and MediaCache
     175             :  * will detect when different principals are associated with data in the
     176             :  * same stream, and replace them with a null principal.
     177             :  */
     178             : class MediaCache;
     179             : 
     180             : /**
     181             :  * If the cache fails to initialize then Init will fail, so nonstatic
     182             :  * methods of this class can assume gMediaCache is non-null.
     183             :  *
     184             :  * This class can be directly embedded as a value.
     185             :  */
     186             : class MediaCacheStream {
     187             : public:
     188             :   // This needs to be a power of two
     189             :   static const int64_t BLOCK_SIZE = 32768;
     190             : 
     191             :   enum ReadMode {
     192             :     MODE_METADATA,
     193             :     MODE_PLAYBACK
     194             :   };
     195             : 
     196             :   // aClient provides the underlying transport that cache will use to read
     197             :   // data for this stream.
     198             :   MediaCacheStream(ChannelMediaResource* aClient, bool aIsPrivateBrowsing);
     199             :   ~MediaCacheStream();
     200             : 
     201             :   // Set up this stream with the cache. Can fail on OOM.
     202             :   // aContentLength is the content length if known, otherwise -1.
     203             :   // Exactly one of InitAsClone or Init must be called before any other method
     204             :   // on this class. Does nothing if already initialized.
     205             :   nsresult Init(int64_t aContentLength);
     206             : 
     207             :   // Set up this stream with the cache, assuming it's for the same data
     208             :   // as the aOriginal stream. Can fail on OOM.
     209             :   // Exactly one of InitAsClone or Init must be called before any other method
     210             :   // on this class. Does nothing if already initialized.
     211             :   nsresult InitAsClone(MediaCacheStream* aOriginal);
     212             : 
     213             :   // These are called on the main thread.
     214             :   // Tell us whether the stream is seekable or not. Non-seekable streams
     215             :   // will always pass 0 for aOffset to CacheClientSeek. This should only
     216             :   // be called while the stream is at channel offset 0. Seekability can
     217             :   // change during the lifetime of the MediaCacheStream --- every time
     218             :   // we do an HTTP load the seekability may be different (and sometimes
     219             :   // is, in practice, due to the effects of caching proxies).
     220             :   void SetTransportSeekable(bool aIsTransportSeekable);
     221             :   // This must be called (and return) before the ChannelMediaResource
     222             :   // used to create this MediaCacheStream is deleted.
     223             :   void Close();
     224             :   // This returns true when the stream has been closed
     225           0 :   bool IsClosed() const { return mClosed; }
     226             :   // Returns true when this stream is can be shared by a new resource load
     227           0 :   bool IsAvailableForSharing() const
     228             :   {
     229           0 :     return !mClosed && !mIsPrivateBrowsing &&
     230           0 :       (!mDidNotifyDataEnded || NS_SUCCEEDED(mNotifyDataEndedStatus));
     231             :   }
     232             :   // Get the principal for this stream. Anything accessing the contents of
     233             :   // this stream must have a principal that subsumes this principal.
     234           0 :   nsIPrincipal* GetCurrentPrincipal() { return mPrincipal; }
     235             :   // Ensure a global media cache update has run with this stream present.
     236             :   // This ensures the cache has had a chance to suspend or unsuspend this stream.
     237             :   // Called only on main thread. This can change the state of streams, fire
     238             :   // notifications, etc.
     239             :   void EnsureCacheUpdate();
     240             : 
     241             :   // These callbacks are called on the main thread by the client
     242             :   // when data has been received via the channel.
     243             :   // Tells the cache what the server said the data length is going to be.
     244             :   // The actual data length may be greater (we receive more data than
     245             :   // specified) or smaller (the stream ends before we reach the given
     246             :   // length), because servers can lie. The server's reported data length
     247             :   // *and* the actual data length can even vary over time because a
     248             :   // misbehaving server may feed us a different stream after each seek
     249             :   // operation. So this is really just a hint. The cache may however
     250             :   // stop reading (suspend the channel) when it thinks we've read all the
     251             :   // data available based on an incorrect reported length. Seeks relative
     252             :   // EOF also depend on the reported length if we haven't managed to
     253             :   // read the whole stream yet.
     254             :   void NotifyDataLength(int64_t aLength);
     255             :   // Notifies the cache that a load has begun. We pass the offset
     256             :   // because in some cases the offset might not be what the cache
     257             :   // requested. In particular we might unexpectedly start providing
     258             :   // data at offset 0. This need not be called if the offset is the
     259             :   // offset that the cache requested in
     260             :   // ChannelMediaResource::CacheClientSeek. This can be called at any
     261             :   // time by the client, not just after a CacheClientSeek.
     262             :   void NotifyDataStarted(int64_t aOffset);
     263             :   // Notifies the cache that data has been received. The stream already
     264             :   // knows the offset because data is received in sequence and
     265             :   // the starting offset is known via NotifyDataStarted or because
     266             :   // the cache requested the offset in
     267             :   // ChannelMediaResource::CacheClientSeek, or because it defaulted to 0.
     268             :   // We pass in the principal that was used to load this data.
     269             :   void NotifyDataReceived(int64_t aSize, const char* aData,
     270             :                           nsIPrincipal* aPrincipal);
     271             :   // Notifies the cache that the current bytes should be written to disk.
     272             :   // Called on the main thread.
     273             :   void FlushPartialBlock();
     274             :   // Notifies the cache that the channel has closed with the given status.
     275             :   void NotifyDataEnded(nsresult aStatus);
     276             : 
     277             :   // Notifies the stream that the channel is reopened. The stream should
     278             :   // reset variables such as |mDidNotifyDataEnded|.
     279             :   void NotifyChannelRecreated();
     280             : 
     281             :   // These methods can be called on any thread.
     282             :   // Cached blocks associated with this stream will not be evicted
     283             :   // while the stream is pinned.
     284             :   void Pin();
     285             :   void Unpin();
     286             :   // See comments above for NotifyDataLength about how the length
     287             :   // can vary over time. Returns -1 if no length is known. Returns the
     288             :   // reported length if we haven't got any better information. If
     289             :   // the stream ended normally we return the length we actually got.
     290             :   // If we've successfully read data beyond the originally reported length,
     291             :   // we return the end of the data we've read.
     292             :   int64_t GetLength();
     293             :   // Returns the unique resource ID. Call only on the main thread or while
     294             :   // holding the media cache lock.
     295           0 :   int64_t GetResourceID() { return mResourceID; }
     296             :   // Returns the end of the bytes starting at the given offset
     297             :   // which are in cache.
     298             :   int64_t GetCachedDataEnd(int64_t aOffset);
     299             :   // Returns the offset of the first byte of cached data at or after aOffset,
     300             :   // or -1 if there is no such cached data.
     301             :   int64_t GetNextCachedData(int64_t aOffset);
     302             :   // Fills aRanges with the ByteRanges representing the data which is currently
     303             :   // cached. Locks the media cache while running, to prevent any ranges
     304             :   // growing. The stream should be pinned while this runs and while its results
     305             :   // are used, to ensure no data is evicted.
     306             :   nsresult GetCachedRanges(MediaByteRangeSet& aRanges);
     307             : 
     308             :   // Reads from buffered data only. Will fail if not all data to be read is
     309             :   // in the cache. Will not mark blocks as read. Can be called from the main
     310             :   // thread. It's the caller's responsibility to wrap the call in a pin/unpin,
     311             :   // and also to check that the range they want is cached before calling this.
     312             :   nsresult ReadFromCache(char* aBuffer,
     313             :                          int64_t aOffset,
     314             :                          int64_t aCount);
     315             : 
     316             :   // IsDataCachedToEndOfStream returns true if all the data from
     317             :   // aOffset to the end of the stream (the server-reported end, if the
     318             :   // real end is not known) is in cache. If we know nothing about the
     319             :   // end of the stream, this returns false.
     320             :   bool IsDataCachedToEndOfStream(int64_t aOffset);
     321             :   // The mode is initially MODE_PLAYBACK.
     322             :   void SetReadMode(ReadMode aMode);
     323             :   // This is the client's estimate of the playback rate assuming
     324             :   // the media plays continuously. The cache can't guess this itself
     325             :   // because it doesn't know when the decoder was paused, buffering, etc.
     326             :   // Do not pass zero.
     327             :   void SetPlaybackRate(uint32_t aBytesPerSecond);
     328             :   // Returns the last set value of SetTransportSeekable.
     329             :   bool IsTransportSeekable();
     330             : 
     331             :   // Returns true when all streams for this resource are suspended or their
     332             :   // channel has ended.
     333             :   bool AreAllStreamsForResourceSuspended();
     334             : 
     335             :   // These methods must be called on a different thread from the main
     336             :   // thread. They should always be called on the same thread for a given
     337             :   // stream.
     338             :   // This can fail when aWhence is NS_SEEK_END and no stream length
     339             :   // is known.
     340             :   nsresult Seek(int32_t aWhence, int64_t aOffset);
     341             :   int64_t Tell();
     342             :   // *aBytes gets the number of bytes that were actually read. This can
     343             :   // be less than aCount. If the first byte of data is not in the cache,
     344             :   // this will block until the data is available or the stream is
     345             :   // closed, otherwise it won't block.
     346             :   nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes);
     347             :   // Seeks to aOffset in the stream then performs a Read operation. See
     348             :   // 'Read' for argument and return details.
     349             :   nsresult ReadAt(int64_t aOffset, char* aBuffer,
     350             :                   uint32_t aCount, uint32_t* aBytes);
     351             : 
     352             :   void ThrottleReadahead(bool bThrottle);
     353             : 
     354             :   size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
     355             : 
     356             : private:
     357             :   friend class MediaCache;
     358             : 
     359             :   /**
     360             :    * A doubly-linked list of blocks. Add/Remove/Get methods are all
     361             :    * constant time. We declare this here so that a stream can contain a
     362             :    * BlockList of its read-ahead blocks. Blocks are referred to by index
     363             :    * into the MediaCache::mIndex array.
     364             :    *
     365             :    * Blocks can belong to more than one list at the same time, because
     366             :    * the next/prev pointers are not stored in the block.
     367             :    */
     368             :   class BlockList {
     369             :   public:
     370           0 :     BlockList() : mFirstBlock(-1), mCount(0) {}
     371           0 :     ~BlockList() {
     372           0 :       NS_ASSERTION(mFirstBlock == -1 && mCount == 0,
     373             :                    "Destroying non-empty block list");
     374           0 :     }
     375             :     void AddFirstBlock(int32_t aBlock);
     376             :     void AddAfter(int32_t aBlock, int32_t aBefore);
     377             :     void RemoveBlock(int32_t aBlock);
     378             :     // Returns the first block in the list, or -1 if empty
     379           0 :     int32_t GetFirstBlock() const { return mFirstBlock; }
     380             :     // Returns the last block in the list, or -1 if empty
     381             :     int32_t GetLastBlock() const;
     382             :     // Returns the next block in the list after aBlock or -1 if
     383             :     // aBlock is the last block
     384             :     int32_t GetNextBlock(int32_t aBlock) const;
     385             :     // Returns the previous block in the list before aBlock or -1 if
     386             :     // aBlock is the first block
     387             :     int32_t GetPrevBlock(int32_t aBlock) const;
     388           0 :     bool IsEmpty() const { return mFirstBlock < 0; }
     389           0 :     int32_t GetCount() const { return mCount; }
     390             :     // The contents of aBlockIndex1 and aBlockIndex2 have been swapped
     391             :     void NotifyBlockSwapped(int32_t aBlockIndex1, int32_t aBlockIndex2);
     392             : #ifdef DEBUG
     393             :     // Verify linked-list invariants
     394             :     void Verify();
     395             : #else
     396             :     void Verify() {}
     397             : #endif
     398             : 
     399             :     size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
     400             : 
     401             :   private:
     402           0 :     struct Entry : public nsUint32HashKey {
     403           0 :       explicit Entry(KeyTypePointer aKey) : nsUint32HashKey(aKey) { }
     404             :       Entry(const Entry& toCopy) : nsUint32HashKey(&toCopy.GetKey()),
     405             :         mNextBlock(toCopy.mNextBlock), mPrevBlock(toCopy.mPrevBlock) {}
     406             : 
     407             :       int32_t mNextBlock;
     408             :       int32_t mPrevBlock;
     409             :     };
     410             :     nsTHashtable<Entry> mEntries;
     411             : 
     412             :     // The index of the first block in the list, or -1 if the list is empty.
     413             :     int32_t mFirstBlock;
     414             :     // The number of blocks in the list.
     415             :     int32_t mCount;
     416             :   };
     417             : 
     418             :   // Returns the end of the bytes starting at the given offset
     419             :   // which are in cache.
     420             :   // This method assumes that the cache monitor is held and can be called on
     421             :   // any thread.
     422             :   int64_t GetCachedDataEndInternal(int64_t aOffset);
     423             :   // Returns the offset of the first byte of cached data at or after aOffset,
     424             :   // or -1 if there is no such cached data.
     425             :   // This method assumes that the cache monitor is held and can be called on
     426             :   // any thread.
     427             :   int64_t GetNextCachedDataInternal(int64_t aOffset);
     428             :   // Writes |mPartialBlock| to disk.
     429             :   // Used by |NotifyDataEnded| and |FlushPartialBlock|.
     430             :   // If |aNotifyAll| is true, this function will wake up readers who may be
     431             :   // waiting on the media cache monitor. Called on the main thread only.
     432             :   void FlushPartialBlockInternal(bool aNotify, ReentrantMonitorAutoEnter& aReentrantMonitor);
     433             :   // A helper function to do the work of closing the stream. Assumes
     434             :   // that the cache monitor is held. Main thread only.
     435             :   // aReentrantMonitor is the nsAutoReentrantMonitor wrapper holding the cache monitor.
     436             :   // This is used to NotifyAll to wake up threads that might be
     437             :   // blocked on reading from this stream.
     438             :   void CloseInternal(ReentrantMonitorAutoEnter& aReentrantMonitor);
     439             :   // Update mPrincipal given that data has been received from aPrincipal
     440             :   bool UpdatePrincipal(nsIPrincipal* aPrincipal);
     441             : 
     442             :   // Instance of MediaCache to use with this MediaCacheStream.
     443             :   RefPtr<MediaCache> mMediaCache;
     444             : 
     445             :   // These fields are main-thread-only.
     446             :   ChannelMediaResource*  mClient;
     447             :   nsCOMPtr<nsIPrincipal> mPrincipal;
     448             :   // Set to true when MediaCache::Update() has finished while this stream
     449             :   // was present.
     450             :   bool                   mHasHadUpdate;
     451             :   // Set to true when the stream has been closed either explicitly or
     452             :   // due to an internal cache error
     453             :   bool                   mClosed;
     454             :   // True if CacheClientNotifyDataEnded has been called for this stream.
     455             :   bool                   mDidNotifyDataEnded;
     456             : 
     457             :   // The following fields must be written holding the cache's monitor and
     458             :   // only on the main thread, thus can be read either on the main thread
     459             :   // or while holding the cache's monitor.
     460             : 
     461             :   // This is a unique ID representing the resource we're loading.
     462             :   // All streams with the same mResourceID are loading the same
     463             :   // underlying resource and should share data.
     464             :   int64_t mResourceID;
     465             :   // The last reported seekability state for the underlying channel
     466             :   bool mIsTransportSeekable;
     467             :   // True if the cache has suspended our channel because the cache is
     468             :   // full and the priority of the data that would be received is lower
     469             :   // than the priority of the data already in the cache
     470             :   bool mCacheSuspended;
     471             :   // True if the channel ended and we haven't seeked it again.
     472             :   bool mChannelEnded;
     473             :   // The offset where the next data from the channel will arrive
     474             :   int64_t      mChannelOffset;
     475             :   // The reported or discovered length of the data, or -1 if nothing is
     476             :   // known
     477             :   int64_t      mStreamLength;
     478             : 
     479             :   // The following fields are protected by the cache's monitor can can be written
     480             :   // by any thread.
     481             : 
     482             :   // The offset where the reader is positioned in the stream
     483             :   int64_t           mStreamOffset;
     484             :   // For each block in the stream data, maps to the cache entry for the
     485             :   // block, or -1 if the block is not cached.
     486             :   nsTArray<int32_t> mBlocks;
     487             :   // The list of read-ahead blocks, ordered by stream offset; the first
     488             :   // block is the earliest in the stream (so the last block will be the
     489             :   // least valuable).
     490             :   BlockList         mReadaheadBlocks;
     491             :   // The list of metadata blocks; the first block is the most recently used
     492             :   BlockList         mMetadataBlocks;
     493             :   // The list of played-back blocks; the first block is the most recently used
     494             :   BlockList         mPlayedBlocks;
     495             :   // The last reported estimate of the decoder's playback rate
     496             :   uint32_t          mPlaybackBytesPerSecond;
     497             :   // The number of times this stream has been Pinned without a
     498             :   // corresponding Unpin
     499             :   uint32_t          mPinCount;
     500             :   // The status used when we did CacheClientNotifyDataEnded. Only valid
     501             :   // when mDidNotifyDataEnded is true.
     502             :   nsresult          mNotifyDataEndedStatus;
     503             :   // The last reported read mode
     504             :   ReadMode          mCurrentMode;
     505             :   // True if some data in mPartialBlockBuffer has been read as metadata
     506             :   bool              mMetadataInPartialBlockBuffer;
     507             : 
     508             :   // The following field is protected by the cache's monitor but are
     509             :   // only written on the main thread.
     510             : 
     511             :   // Data received for the block containing mChannelOffset. Data needs
     512             :   // to wait here so we can write back a complete block. The first
     513             :   // mChannelOffset%BLOCK_SIZE bytes have been filled in with good data,
     514             :   // the rest are garbage.
     515             :   // Heap allocate this buffer since the exact power-of-2 will cause allocation
     516             :   // slop when combined with the rest of the object members.
     517             :   UniquePtr<uint8_t[]> mPartialBlockBuffer = MakeUnique<uint8_t[]>(BLOCK_SIZE);
     518             : 
     519             :   // True if associated with a private browsing window.
     520             :   const bool mIsPrivateBrowsing;
     521             : 
     522             :   bool mThrottleReadahead = false;
     523             : };
     524             : 
     525             : } // namespace mozilla
     526             : 
     527             : #endif

Generated by: LCOV version 1.13