DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (d96ee8115c5a)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_dom_media_FileMediaResource_h
#define mozilla_dom_media_FileMediaResource_h

#include "BaseMediaResource.h"
#include "mozilla/Mutex.h"

namespace mozilla {

class FileMediaResource : public BaseMediaResource {
 public:
  FileMediaResource(MediaResourceCallback* aCallback, nsIChannel* aChannel,
                    nsIURI* aURI, int64_t aSize = -1 /* unknown size */)
      : BaseMediaResource(aCallback, aChannel, aURI),
        mSize(aSize),
        mLock("FileMediaResource.mLock"),
        mSizeInitialized(aSize != -1) {}
  ~FileMediaResource() {}

  // Main thread
  nsresult Open(nsIStreamListener** aStreamListener) override;
  nsresult Close() override;
  void Suspend(bool aCloseImmediately) override {}
  void Resume() override {}
  already_AddRefed<nsIPrincipal> GetCurrentPrincipal() override;
  nsresult ReadFromCache(char* aBuffer, int64_t aOffset,
                         uint32_t aCount) override;

  // These methods are called off the main thread.

  // Other thread
  void SetReadMode(MediaCacheStream::ReadMode aMode) override {}
  void SetPlaybackRate(uint32_t aBytesPerSecond) override {}
  nsresult ReadAt(int64_t aOffset, char* aBuffer, uint32_t aCount,
                  uint32_t* aBytes) override;
  // (Probably) file-based, caching recommended.
  bool ShouldCacheReads() override { return true; }

  // Any thread
  void Pin() override {}
  void Unpin() override {}
  double GetDownloadRate(bool* aIsReliable) override {
    // The data's all already here
    *aIsReliable = true;
    return 100 * 1024 * 1024;  // arbitray, use 100MB/s
  }

  int64_t GetLength() override {
    MutexAutoLock lock(mLock);

    EnsureSizeInitialized();
    return mSizeInitialized ? mSize : 0;
  }

  int64_t GetNextCachedData(int64_t aOffset) override {
    MutexAutoLock lock(mLock);

    EnsureSizeInitialized();
    return (aOffset < mSize) ? aOffset : -1;
  }

  int64_t GetCachedDataEnd(int64_t aOffset) override {
    MutexAutoLock lock(mLock);

    EnsureSizeInitialized();
    return std::max(aOffset, mSize);
  }
  bool IsDataCachedToEndOfResource(int64_t aOffset) override { return true; }
  bool IsTransportSeekable() override { return true; }

  nsresult GetCachedRanges(MediaByteRangeSet& aRanges) override;

  size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override {
    // Might be useful to track in the future:
    // - mInput
    return BaseMediaResource::SizeOfExcludingThis(aMallocSizeOf);
  }

  size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override {
    return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
  }

 protected:
  // These Unsafe variants of Read and Seek perform their operations
  // without acquiring mLock. The caller must obtain the lock before
  // calling. The implmentation of Read, Seek and ReadAt obtains the
  // lock before calling these Unsafe variants to read or seek.
  nsresult UnsafeRead(char* aBuffer, uint32_t aCount, uint32_t* aBytes);
  nsresult UnsafeSeek(int32_t aWhence, int64_t aOffset);

 private:
  // Ensures mSize is initialized, if it can be.
  // mLock must be held when this is called, and mInput must be non-null.
  void EnsureSizeInitialized();
  already_AddRefed<MediaByteBuffer> UnsafeMediaReadAt(int64_t aOffset,
                                                      uint32_t aCount);

  // The file size, or -1 if not known. Immutable after Open().
  // Can be used from any thread.
  int64_t mSize;

  // This lock handles synchronisation between calls to Close() and
  // the Read, Seek, etc calls. Close must not be called while a
  // Read or Seek is in progress since it resets various internal
  // values to null.
  // This lock protects mSeekable, mInput, mSize, and mSizeInitialized.
  Mutex mLock;

  // Seekable stream interface to file. This can be used from any
  // thread.
  nsCOMPtr<nsISeekableStream> mSeekable;

  // Input stream for the media data. This can be used from any
  // thread.
  nsCOMPtr<nsIInputStream> mInput;

  // Whether we've attempted to initialize mSize. Note that mSize can be -1
  // when mSizeInitialized is true if we tried and failed to get the size
  // of the file.
  bool mSizeInitialized;
  // Set to true if NotifyDataEnded callback has been processed (which only
  // occurs if resource size is known)
  bool mNotifyDataEndedProcessed = false;
};

}  // namespace mozilla

#endif  // mozilla_dom_media_FileMediaResource_h