ResourceQueue.cpp (6269B)
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 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 15 extern mozilla::LogModule* GetSourceBufferResourceLog(); 16 17 #define SBR_DEBUG(arg, ...) \ 18 MOZ_LOG(GetSourceBufferResourceLog(), mozilla::LogLevel::Debug, \ 19 ("ResourceQueue(%p)::%s: " arg, this, __func__, ##__VA_ARGS__)) 20 #define SBR_DEBUGV(arg, ...) \ 21 MOZ_LOG(GetSourceBufferResourceLog(), mozilla::LogLevel::Verbose, \ 22 ("ResourceQueue(%p)::%s: " arg, this, __func__, ##__VA_ARGS__)) 23 24 namespace mozilla { 25 26 ResourceItem::ResourceItem(const MediaSpan& aData, uint64_t aOffset) 27 : mData(aData), mOffset(aOffset) {} 28 29 size_t ResourceItem::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { 30 return aMallocSizeOf(this); 31 } 32 33 class ResourceQueueDeallocator : public nsDequeFunctor<ResourceItem> { 34 void operator()(ResourceItem* aObject) override { delete aObject; } 35 }; 36 37 ResourceQueue::ResourceQueue() 38 : nsDeque<ResourceItem>(new ResourceQueueDeallocator()), 39 mLogicalLength(0), 40 mOffset(0) {} 41 42 uint64_t ResourceQueue::GetOffset() { return mOffset; } 43 44 uint64_t ResourceQueue::GetLength() { return mLogicalLength; } 45 46 const uint8_t* ResourceQueue::GetContiguousAccess(int64_t aOffset, 47 size_t aSize) { 48 uint32_t offset = 0; 49 uint32_t start = GetAtOffset(aOffset, &offset); 50 if (start >= GetSize()) { 51 return nullptr; 52 } 53 ResourceItem* item = ResourceAt(start); 54 if (offset + aSize > item->mData.Length()) { 55 return nullptr; 56 } 57 return item->mData.Elements() + offset; 58 } 59 60 void ResourceQueue::CopyData(uint64_t aOffset, uint32_t aCount, char* aDest) { 61 uint32_t offset = 0; 62 uint32_t start = GetAtOffset(aOffset, &offset); 63 size_t i = start; 64 while (i < uint32_t(GetSize()) && aCount > 0) { 65 ResourceItem* item = ResourceAt(i++); 66 uint32_t bytes = std::min(aCount, uint32_t(item->mData.Length() - offset)); 67 if (bytes != 0) { 68 memcpy(aDest, item->mData.Elements() + offset, bytes); 69 offset = 0; 70 aCount -= bytes; 71 aDest += bytes; 72 } 73 } 74 } 75 76 void ResourceQueue::AppendItem(const MediaSpan& aData) { 77 uint64_t offset = mLogicalLength; 78 mLogicalLength += aData.Length(); 79 Push(new ResourceItem(aData, offset)); 80 } 81 82 uint32_t ResourceQueue::Evict(uint64_t aOffset, uint32_t aSizeToEvict) { 83 SBR_DEBUG("Evict(aOffset=%" PRIu64 ", aSizeToEvict=%u)", aOffset, 84 aSizeToEvict); 85 return EvictBefore(std::min(aOffset, mOffset + (uint64_t)aSizeToEvict)); 86 } 87 88 uint32_t ResourceQueue::EvictBefore(uint64_t aOffset) { 89 SBR_DEBUG("EvictBefore(%" PRIu64 ")", aOffset); 90 uint32_t evicted = 0; 91 while (GetSize()) { 92 ResourceItem* item = ResourceAt(0); 93 SBR_DEBUG("item=%p length=%zu offset=%" PRIu64, item, item->mData.Length(), 94 mOffset); 95 if (item->mData.Length() + mOffset >= aOffset) { 96 if (aOffset <= mOffset) { 97 break; 98 } 99 uint32_t offset = aOffset - mOffset; 100 mOffset += offset; 101 evicted += offset; 102 item->mData.RemoveFront(offset); 103 item->mOffset += offset; 104 break; 105 } 106 mOffset += item->mData.Length(); 107 evicted += item->mData.Length(); 108 delete PopFront(); 109 } 110 return evicted; 111 } 112 113 uint32_t ResourceQueue::EvictAll() { 114 SBR_DEBUG("EvictAll()"); 115 uint32_t evicted = 0; 116 while (GetSize()) { 117 ResourceItem* item = ResourceAt(0); 118 SBR_DEBUG("item=%p length=%zu offset=%" PRIu64, item, item->mData.Length(), 119 mOffset); 120 mOffset += item->mData.Length(); 121 evicted += item->mData.Length(); 122 delete PopFront(); 123 } 124 return evicted; 125 } 126 127 size_t ResourceQueue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { 128 // Calculate the size of the internal deque. 129 size_t size = nsDeque<ResourceItem>::SizeOfExcludingThis(aMallocSizeOf); 130 131 // Sum the ResourceItems. The ResourceItems's MediaSpans may share the 132 // same underlying MediaByteBuffers, so we need to de-dupe the buffers 133 // in order to report an accurate size. 134 nsTArray<MediaByteBuffer*> buffers; 135 for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) { 136 const ResourceItem* item = ResourceAt(i); 137 size += item->SizeOfIncludingThis(aMallocSizeOf); 138 if (!buffers.Contains(item->mData.Buffer())) { 139 buffers.AppendElement(item->mData.Buffer()); 140 } 141 } 142 143 for (MediaByteBuffer* buffer : buffers) { 144 size += buffer->ShallowSizeOfExcludingThis(aMallocSizeOf); 145 } 146 147 return size; 148 } 149 150 #if defined(DEBUG) 151 void ResourceQueue::Dump(const char* aPath) { 152 for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) { 153 ResourceItem* item = ResourceAt(i); 154 155 char buf[255]; 156 SprintfLiteral(buf, "%s/%08u.bin", aPath, i); 157 FILE* fp = fopen(buf, "wb"); 158 if (!fp) { 159 return; 160 } 161 (void)fwrite(item->mData.Elements(), item->mData.Length(), 1, fp); 162 fclose(fp); 163 } 164 } 165 #endif 166 167 ResourceItem* ResourceQueue::ResourceAt(uint32_t aIndex) const { 168 return static_cast<ResourceItem*>(ObjectAt(aIndex)); 169 } 170 171 uint32_t ResourceQueue::GetAtOffset(uint64_t aOffset, 172 uint32_t* aResourceOffset) const { 173 MOZ_RELEASE_ASSERT(aOffset >= mOffset); 174 175 size_t hi = GetSize(); 176 size_t lo = 0; 177 while (lo < hi) { 178 size_t mid = lo + (hi - lo) / 2; 179 const ResourceItem* resource = ResourceAt(mid); 180 if (resource->mOffset <= aOffset && 181 aOffset < resource->mOffset + resource->mData.Length()) { 182 if (aResourceOffset) { 183 *aResourceOffset = aOffset - resource->mOffset; 184 } 185 return uint32_t(mid); 186 } 187 if (resource->mOffset + resource->mData.Length() <= aOffset) { 188 lo = mid + 1; 189 } else { 190 hi = mid; 191 } 192 } 193 194 return uint32_t(GetSize()); 195 } 196 197 ResourceItem* ResourceQueue::PopFront() { 198 return nsDeque<ResourceItem>::PopFront(); 199 } 200 201 #undef SBR_DEBUG 202 #undef SBR_DEBUGV 203 204 } // namespace mozilla