Line data Source code
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 : #include "ResourceQueue.h"
8 : #include "nsDeque.h"
9 : #include "MediaData.h"
10 : #include "mozilla/ErrorResult.h"
11 : #include "mozilla/IntegerPrintfMacros.h"
12 : #include "mozilla/Logging.h"
13 : #include "mozilla/Sprintf.h"
14 : #include "mozilla/SizePrintfMacros.h"
15 :
16 : extern mozilla::LogModule* GetSourceBufferResourceLog();
17 :
18 : #define SBR_DEBUG(arg, ...) MOZ_LOG(GetSourceBufferResourceLog(), mozilla::LogLevel::Debug, ("ResourceQueue(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
19 : #define SBR_DEBUGV(arg, ...) MOZ_LOG(GetSourceBufferResourceLog(), mozilla::LogLevel::Verbose, ("ResourceQueue(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
20 :
21 : namespace mozilla {
22 :
23 0 : ResourceItem::ResourceItem(MediaByteBuffer* aData)
24 0 : : mData(aData)
25 : {
26 0 : }
27 :
28 : size_t
29 0 : ResourceItem::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
30 : {
31 : // size including this
32 0 : size_t size = aMallocSizeOf(this);
33 :
34 : // size excluding this
35 0 : size += mData->ShallowSizeOfExcludingThis(aMallocSizeOf);
36 :
37 0 : return size;
38 : }
39 :
40 0 : class ResourceQueueDeallocator : public nsDequeFunctor {
41 0 : void* operator() (void* aObject) override {
42 0 : delete static_cast<ResourceItem*>(aObject);
43 0 : return nullptr;
44 : }
45 : };
46 :
47 0 : ResourceQueue::ResourceQueue()
48 0 : : nsDeque(new ResourceQueueDeallocator())
49 : , mLogicalLength(0)
50 0 : , mOffset(0)
51 : {
52 0 : }
53 :
54 : uint64_t
55 0 : ResourceQueue::GetOffset()
56 : {
57 0 : return mOffset;
58 : }
59 :
60 : uint64_t
61 0 : ResourceQueue::GetLength()
62 : {
63 0 : return mLogicalLength;
64 : }
65 :
66 : void
67 0 : ResourceQueue::CopyData(uint64_t aOffset, uint32_t aCount, char* aDest)
68 : {
69 0 : uint32_t offset = 0;
70 0 : uint32_t start = GetAtOffset(aOffset, &offset);
71 0 : uint32_t end = std::min(GetAtOffset(aOffset + aCount, nullptr) + 1, uint32_t(GetSize()));
72 0 : for (uint32_t i = start; i < end; ++i) {
73 0 : ResourceItem* item = ResourceAt(i);
74 0 : uint32_t bytes = std::min(aCount, uint32_t(item->mData->Length() - offset));
75 0 : if (bytes != 0) {
76 0 : memcpy(aDest, &(*item->mData)[offset], bytes);
77 0 : offset = 0;
78 0 : aCount -= bytes;
79 0 : aDest += bytes;
80 : }
81 : }
82 0 : }
83 :
84 : void
85 0 : ResourceQueue::AppendItem(MediaByteBuffer* aData)
86 : {
87 0 : mLogicalLength += aData->Length();
88 0 : Push(new ResourceItem(aData));
89 0 : }
90 :
91 : uint32_t
92 0 : ResourceQueue::Evict(uint64_t aOffset, uint32_t aSizeToEvict,
93 : ErrorResult& aRv)
94 : {
95 0 : SBR_DEBUG("Evict(aOffset=%" PRIu64 ", aSizeToEvict=%u)",
96 : aOffset, aSizeToEvict);
97 0 : return EvictBefore(std::min(aOffset, mOffset + (uint64_t)aSizeToEvict), aRv);
98 : }
99 :
100 0 : uint32_t ResourceQueue::EvictBefore(uint64_t aOffset, ErrorResult& aRv)
101 : {
102 0 : SBR_DEBUG("EvictBefore(%" PRIu64 ")", aOffset);
103 0 : uint32_t evicted = 0;
104 0 : while (ResourceItem* item = ResourceAt(0)) {
105 0 : SBR_DEBUG("item=%p length=%" PRIuSIZE " offset=%" PRIu64,
106 : item, item->mData->Length(), mOffset);
107 0 : if (item->mData->Length() + mOffset >= aOffset) {
108 0 : if (aOffset <= mOffset) {
109 0 : break;
110 : }
111 0 : uint32_t offset = aOffset - mOffset;
112 0 : mOffset += offset;
113 0 : evicted += offset;
114 0 : RefPtr<MediaByteBuffer> data = new MediaByteBuffer;
115 0 : if (!data->AppendElements(item->mData->Elements() + offset,
116 0 : item->mData->Length() - offset,
117 : fallible)) {
118 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
119 0 : return 0;
120 : }
121 :
122 0 : item->mData = data;
123 0 : break;
124 : }
125 0 : mOffset += item->mData->Length();
126 0 : evicted += item->mData->Length();
127 0 : delete PopFront();
128 0 : }
129 0 : return evicted;
130 : }
131 :
132 : uint32_t
133 0 : ResourceQueue::EvictAll()
134 : {
135 0 : SBR_DEBUG("EvictAll()");
136 0 : uint32_t evicted = 0;
137 0 : while (ResourceItem* item = ResourceAt(0)) {
138 0 : SBR_DEBUG("item=%p length=%" PRIuSIZE " offset=%" PRIu64,
139 : item, item->mData->Length(), mOffset);
140 0 : mOffset += item->mData->Length();
141 0 : evicted += item->mData->Length();
142 0 : delete PopFront();
143 0 : }
144 0 : return evicted;
145 : }
146 :
147 : size_t
148 0 : ResourceQueue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
149 : {
150 : // Calculate the size of the internal deque.
151 0 : size_t size = nsDeque::SizeOfExcludingThis(aMallocSizeOf);
152 :
153 : // Sum the ResourceItems.
154 0 : for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
155 0 : const ResourceItem* item = ResourceAt(i);
156 0 : size += item->SizeOfIncludingThis(aMallocSizeOf);
157 : }
158 :
159 0 : return size;
160 : }
161 :
162 : #if defined(DEBUG)
163 : void
164 0 : ResourceQueue::Dump(const char* aPath)
165 : {
166 0 : for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
167 0 : ResourceItem* item = ResourceAt(i);
168 :
169 : char buf[255];
170 0 : SprintfLiteral(buf, "%s/%08u.bin", aPath, i);
171 0 : FILE* fp = fopen(buf, "wb");
172 0 : if (!fp) {
173 0 : return;
174 : }
175 0 : fwrite(item->mData->Elements(), item->mData->Length(), 1, fp);
176 0 : fclose(fp);
177 : }
178 : }
179 : #endif
180 :
181 : ResourceItem*
182 0 : ResourceQueue::ResourceAt(uint32_t aIndex) const
183 : {
184 0 : return static_cast<ResourceItem*>(ObjectAt(aIndex));
185 : }
186 :
187 : uint32_t
188 0 : ResourceQueue::GetAtOffset(uint64_t aOffset, uint32_t *aResourceOffset)
189 : {
190 0 : MOZ_RELEASE_ASSERT(aOffset >= mOffset);
191 0 : uint64_t offset = mOffset;
192 0 : for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
193 0 : ResourceItem* item = ResourceAt(i);
194 : // If the item contains the start of the offset we want to
195 : // break out of the loop.
196 0 : if (item->mData->Length() + offset > aOffset) {
197 0 : if (aResourceOffset) {
198 0 : *aResourceOffset = aOffset - offset;
199 : }
200 0 : return i;
201 : }
202 0 : offset += item->mData->Length();
203 : }
204 0 : return GetSize();
205 : }
206 :
207 : ResourceItem*
208 0 : ResourceQueue::PopFront()
209 : {
210 0 : return static_cast<ResourceItem*>(nsDeque::PopFront());
211 : }
212 :
213 : #undef SBR_DEBUG
214 : #undef SBR_DEBUGV
215 :
216 : } // namespace mozilla
|