1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 MOZILLA_SOURCEBUFFERRESOURCE_H_
8 #define MOZILLA_SOURCEBUFFERRESOURCE_H_
9 
10 #include "mozilla/AbstractThread.h"
11 #include "mozilla/Logging.h"
12 #include "MediaResource.h"
13 #include "ResourceQueue.h"
14 
15 #define UNIMPLEMENTED()                               \
16   { /* Logging this is too spammy to do by default */ \
17   }
18 
19 namespace mozilla {
20 
21 class MediaByteBuffer;
22 class AbstractThread;
23 
24 namespace dom {
25 
26 class SourceBuffer;
27 
28 }  // namespace dom
29 
30 DDLoggedTypeDeclNameAndBase(SourceBufferResource, MediaResource);
31 
32 // SourceBufferResource is not thread safe.
33 class SourceBufferResource final
34     : public MediaResource,
35       public DecoderDoctorLifeLogger<SourceBufferResource> {
36  public:
37   SourceBufferResource();
38   RefPtr<GenericPromise> Close() override;
39   nsresult ReadAt(int64_t aOffset, char* aBuffer, uint32_t aCount,
40                   uint32_t* aBytes) override;
41   // Memory-based and no locks, caching discouraged.
ShouldCacheReads()42   bool ShouldCacheReads() override { return false; }
Pin()43   void Pin() override { UNIMPLEMENTED(); }
Unpin()44   void Unpin() override { UNIMPLEMENTED(); }
GetLength()45   int64_t GetLength() override { return mInputBuffer.GetLength(); }
GetNextCachedData(int64_t aOffset)46   int64_t GetNextCachedData(int64_t aOffset) override {
47     MOZ_ASSERT(OnThread());
48     MOZ_ASSERT(aOffset >= 0);
49     if (uint64_t(aOffset) < mInputBuffer.GetOffset()) {
50       return mInputBuffer.GetOffset();
51     } else if (aOffset == GetLength()) {
52       return -1;
53     }
54     return aOffset;
55   }
GetCachedDataEnd(int64_t aOffset)56   int64_t GetCachedDataEnd(int64_t aOffset) override {
57     MOZ_ASSERT(OnThread());
58     MOZ_ASSERT(aOffset >= 0);
59     if (uint64_t(aOffset) < mInputBuffer.GetOffset() ||
60         aOffset >= GetLength()) {
61       // aOffset is outside of the buffered range.
62       return aOffset;
63     }
64     return GetLength();
65   }
IsDataCachedToEndOfResource(int64_t aOffset)66   bool IsDataCachedToEndOfResource(int64_t aOffset) override { return false; }
67   nsresult ReadFromCache(char* aBuffer, int64_t aOffset,
68                          uint32_t aCount) override;
69 
GetCachedRanges(MediaByteRangeSet & aRanges)70   nsresult GetCachedRanges(MediaByteRangeSet& aRanges) override {
71     MOZ_ASSERT(OnThread());
72     if (mInputBuffer.GetLength()) {
73       aRanges +=
74           MediaByteRange(mInputBuffer.GetOffset(), mInputBuffer.GetLength());
75     }
76     return NS_OK;
77   }
78 
SizeOfExcludingThis(MallocSizeOf aMallocSizeOf)79   size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
80     MOZ_ASSERT(OnThread());
81     return mInputBuffer.SizeOfExcludingThis(aMallocSizeOf);
82   }
83 
SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)84   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
85     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
86   }
87 
88   // Used by SourceBuffer.
89   void AppendData(MediaByteBuffer* aData);
90   void AppendData(const MediaSpan& aData);
91   void Ended();
IsEnded()92   bool IsEnded() {
93     MOZ_ASSERT(OnThread());
94     return mEnded;
95   }
96   // Remove data from resource if it holds more than the threshold reduced by
97   // the given number of bytes. Returns amount evicted.
98   uint32_t EvictData(uint64_t aPlaybackOffset, int64_t aThresholdReduct);
99 
100   // Remove data from resource before the given offset.
101   void EvictBefore(uint64_t aOffset);
102 
103   // Remove all data from the resource
104   uint32_t EvictAll();
105 
106   // Returns the amount of data currently retained by this resource.
GetSize()107   int64_t GetSize() {
108     MOZ_ASSERT(OnThread());
109     return mInputBuffer.GetLength() - mInputBuffer.GetOffset();
110   }
111 
GetContiguousAccess(int64_t aOffset,size_t aSize)112   const uint8_t* GetContiguousAccess(int64_t aOffset, size_t aSize) {
113     return mInputBuffer.GetContiguousAccess(aOffset, aSize);
114   }
115 
116 #if defined(DEBUG)
Dump(const char * aPath)117   void Dump(const char* aPath) { mInputBuffer.Dump(aPath); }
118 #endif
119 
120  private:
121   virtual ~SourceBufferResource();
122   nsresult ReadAtInternal(int64_t aOffset, char* aBuffer, uint32_t aCount,
123                           uint32_t* aBytes);
124 
125 #if defined(DEBUG)
126   const RefPtr<AbstractThread> mThread;
127   // TaskQueue methods and objects.
128   const AbstractThread* GetThread() const;
129   bool OnThread() const;
130 #endif
131 
132   // The buffer holding resource data.
133   ResourceQueue mInputBuffer;
134 
135   bool mClosed = false;
136   bool mEnded = false;
137 };
138 
139 }  // namespace mozilla
140 
141 #undef UNIMPLEMENTED
142 
143 #endif /* MOZILLA_SOURCEBUFFERRESOURCE_H_ */
144