Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/mediasource/ResourceQueue.cpp
Line
Count
Source (jump to first uncovered line)
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/Unused.h"
15
16
extern mozilla::LogModule* GetSourceBufferResourceLog();
17
18
0
#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
ResourceItem::ResourceItem(MediaByteBuffer* aData)
24
  : mData(aData)
25
0
{
26
0
}
27
28
size_t
29
ResourceItem::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
30
0
{
31
0
  // size including this
32
0
  size_t size = aMallocSizeOf(this);
33
0
34
0
  // size excluding this
35
0
  size += mData->ShallowSizeOfExcludingThis(aMallocSizeOf);
36
0
37
0
  return size;
38
0
}
39
40
class ResourceQueueDeallocator : public nsDequeFunctor {
41
  void operator()(void* aObject) override
42
0
  {
43
0
    delete static_cast<ResourceItem*>(aObject);
44
0
  }
45
};
46
47
ResourceQueue::ResourceQueue()
48
  : nsDeque(new ResourceQueueDeallocator())
49
  , mLogicalLength(0)
50
  , mOffset(0)
51
0
{
52
0
}
53
54
uint64_t
55
ResourceQueue::GetOffset()
56
0
{
57
0
  return mOffset;
58
0
}
59
60
uint64_t
61
ResourceQueue::GetLength()
62
0
{
63
0
  return mLogicalLength;
64
0
}
65
66
void
67
ResourceQueue::CopyData(uint64_t aOffset, uint32_t aCount, char* aDest)
68
0
{
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
0
    }
81
0
  }
82
0
}
83
84
void
85
ResourceQueue::AppendItem(MediaByteBuffer* aData)
86
0
{
87
0
  mLogicalLength += aData->Length();
88
0
  Push(new ResourceItem(aData));
89
0
}
90
91
uint32_t
92
ResourceQueue::Evict(uint64_t aOffset, uint32_t aSizeToEvict,
93
                     ErrorResult& aRv)
94
0
{
95
0
  SBR_DEBUG("Evict(aOffset=%" PRIu64 ", aSizeToEvict=%u)",
96
0
            aOffset, aSizeToEvict);
97
0
  return EvictBefore(std::min(aOffset, mOffset + (uint64_t)aSizeToEvict), aRv);
98
0
}
99
100
uint32_t ResourceQueue::EvictBefore(uint64_t aOffset, ErrorResult& aRv)
101
0
{
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=%zu offset=%" PRIu64,
106
0
              item, item->mData->Length(), mOffset);
107
0
    if (item->mData->Length() + mOffset >= aOffset) {
108
0
      if (aOffset <= mOffset) {
109
0
        break;
110
0
      }
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
0
                                fallible)) {
118
0
        aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
119
0
        return 0;
120
0
      }
121
0
122
0
      item->mData = data;
123
0
      break;
124
0
    }
125
0
    mOffset += item->mData->Length();
126
0
    evicted += item->mData->Length();
127
0
    delete PopFront();
128
0
  }
129
0
  return evicted;
130
0
}
131
132
uint32_t
133
ResourceQueue::EvictAll()
134
0
{
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=%zu offset=%" PRIu64,
139
0
              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
0
}
146
147
size_t
148
ResourceQueue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
149
0
{
150
0
  // Calculate the size of the internal deque.
151
0
  size_t size = nsDeque::SizeOfExcludingThis(aMallocSizeOf);
152
0
153
0
  // 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
0
  }
158
0
159
0
  return size;
160
0
}
161
162
#if defined(DEBUG)
163
void
164
ResourceQueue::Dump(const char* aPath)
165
{
166
  for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
167
    ResourceItem* item = ResourceAt(i);
168
169
    char buf[255];
170
    SprintfLiteral(buf, "%s/%08u.bin", aPath, i);
171
    FILE* fp = fopen(buf, "wb");
172
    if (!fp) {
173
      return;
174
    }
175
    Unused << fwrite(item->mData->Elements(), item->mData->Length(), 1, fp);
176
    fclose(fp);
177
  }
178
}
179
#endif
180
181
ResourceItem*
182
ResourceQueue::ResourceAt(uint32_t aIndex) const
183
0
{
184
0
  return static_cast<ResourceItem*>(ObjectAt(aIndex));
185
0
}
186
187
uint32_t
188
ResourceQueue::GetAtOffset(uint64_t aOffset, uint32_t *aResourceOffset)
189
0
{
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
0
    // If the item contains the start of the offset we want to
195
0
    // break out of the loop.
196
0
    if (item->mData->Length() + offset > aOffset) {
197
0
      if (aResourceOffset) {
198
0
        *aResourceOffset = aOffset - offset;
199
0
      }
200
0
      return i;
201
0
    }
202
0
    offset += item->mData->Length();
203
0
  }
204
0
  return GetSize();
205
0
}
206
207
ResourceItem*
208
ResourceQueue::PopFront()
209
0
{
210
0
  return static_cast<ResourceItem*>(nsDeque::PopFront());
211
0
}
212
213
#undef SBR_DEBUG
214
#undef SBR_DEBUGV
215
216
} // namespace mozilla