summaryrefslogtreecommitdiffstats
path: root/dom/media/FileMediaResource.h
blob: 7373a6fd37defacca73e077b880b68ae885a880c (plain)
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
133
134
135
136
/* 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() = default;

  // Main thread
  nsresult Open(nsIStreamListener** aStreamListener) override;
  RefPtr<GenericPromise> Close() override;
  void Suspend(bool aCloseImmediately) override {}
  void Resume() override {}
  already_AddRefed<nsIPrincipal> GetCurrentPrincipal() override;
  bool HadCrossOriginRedirects() 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)
      MOZ_REQUIRES(mLock);
  nsresult UnsafeSeek(int32_t aWhence, int64_t aOffset) MOZ_REQUIRES(mLock);

 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() MOZ_REQUIRES(mLock);
  already_AddRefed<MediaByteBuffer> UnsafeMediaReadAt(int64_t aOffset,
                                                      uint32_t aCount)
      MOZ_REQUIRES(mLock);

  // The file size, or -1 if not known. Immutable after Open().
  // Can be used from any thread.
  // XXX FIX?  is this under mLock?   comments are contradictory
  int64_t mSize MOZ_GUARDED_BY(mLock);

  // 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 MOZ_GUARDED_BY(mLock);

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

  // 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 MOZ_GUARDED_BY(mLock);
  // 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