Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/MediaQueue.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim:set ts=2 sw=2 sts=2 et cindent: */
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
#if !defined(MediaQueue_h_)
7
#define MediaQueue_h_
8
9
#include "mozilla/RecursiveMutex.h"
10
#include "mozilla/TaskQueue.h"
11
12
#include "nsDeque.h"
13
#include "MediaEventSource.h"
14
#include "TimeUnits.h"
15
16
namespace mozilla {
17
18
// Thread and type safe wrapper around nsDeque.
19
template <class T>
20
class MediaQueueDeallocator : public nsDequeFunctor {
21
  virtual void operator()(void* aObject) override
22
  {
23
    RefPtr<T> releaseMe = dont_AddRef(static_cast<T*>(aObject));
24
  }
25
};
26
27
template <class T>
28
class MediaQueue : private nsDeque {
29
public:
30
  MediaQueue()
31
    : nsDeque(new MediaQueueDeallocator<T>()),
32
      mRecursiveMutex("mediaqueue"),
33
      mEndOfStream(false)
34
  {}
35
36
  ~MediaQueue() {
37
    Reset();
38
  }
39
40
  inline size_t GetSize() const {
41
    RecursiveMutexAutoLock lock(mRecursiveMutex);
42
    return nsDeque::GetSize();
43
  }
44
45
  inline void Push(T* aItem) {
46
    RecursiveMutexAutoLock lock(mRecursiveMutex);
47
    MOZ_ASSERT(!mEndOfStream);
48
    MOZ_ASSERT(aItem);
49
    NS_ADDREF(aItem);
50
    MOZ_ASSERT(aItem->GetEndTime() >= aItem->mTime);
51
    nsDeque::Push(aItem);
52
    mPushEvent.Notify(RefPtr<T>(aItem));
53
  }
54
55
  inline already_AddRefed<T> PopFront() {
56
    RecursiveMutexAutoLock lock(mRecursiveMutex);
57
    RefPtr<T> rv = dont_AddRef(static_cast<T*>(nsDeque::PopFront()));
58
    if (rv) {
59
      mPopEvent.Notify(rv);
60
    }
61
    return rv.forget();
62
  }
63
64
  inline RefPtr<T> PeekFront() const {
65
    RecursiveMutexAutoLock lock(mRecursiveMutex);
66
    return static_cast<T*>(nsDeque::PeekFront());
67
  }
68
69
  void Reset() {
70
    RecursiveMutexAutoLock lock(mRecursiveMutex);
71
    while (GetSize() > 0) {
72
      RefPtr<T> x = dont_AddRef(static_cast<T*>(nsDeque::PopFront()));
73
    }
74
    mEndOfStream = false;
75
  }
76
77
  bool AtEndOfStream() const {
78
    RecursiveMutexAutoLock lock(mRecursiveMutex);
79
    return GetSize() == 0 && mEndOfStream;
80
  }
81
82
  // Returns true if the media queue has had its last item added to it.
83
  // This happens when the media stream has been completely decoded. Note this
84
  // does not mean that the corresponding stream has finished playback.
85
  bool IsFinished() const {
86
    RecursiveMutexAutoLock lock(mRecursiveMutex);
87
    return mEndOfStream;
88
  }
89
90
  // Informs the media queue that it won't be receiving any more items.
91
  void Finish() {
92
    RecursiveMutexAutoLock lock(mRecursiveMutex);
93
    if (!mEndOfStream) {
94
      mEndOfStream = true;
95
      mFinishEvent.Notify();
96
    }
97
  }
98
99
  // Returns the approximate number of microseconds of items in the queue.
100
  int64_t Duration() {
101
    RecursiveMutexAutoLock lock(mRecursiveMutex);
102
    if (GetSize() == 0) {
103
      return 0;
104
    }
105
    T* last = static_cast<T*>(nsDeque::Peek());
106
    T* first = static_cast<T*>(nsDeque::PeekFront());
107
    return (last->GetEndTime() - first->mTime).ToMicroseconds();
108
  }
109
110
  void LockedForEach(nsDequeFunctor& aFunctor) const {
111
    RecursiveMutexAutoLock lock(mRecursiveMutex);
112
    ForEach(aFunctor);
113
  }
114
115
  // Extracts elements from the queue into aResult, in order.
116
  // Elements whose start time is before aTime are ignored.
117
0
  void GetElementsAfter(int64_t aTime, nsTArray<RefPtr<T>>* aResult) {
118
0
    RecursiveMutexAutoLock lock(mRecursiveMutex);
119
0
    if (GetSize() == 0)
120
0
      return;
121
0
    size_t i;
122
0
    for (i = GetSize() - 1; i > 0; --i) {
123
0
      T* v = static_cast<T*>(ObjectAt(i));
124
0
      if (v->GetEndTime().ToMicroseconds() < aTime)
125
0
        break;
126
0
    }
127
0
    // Elements less than i have a end time before aTime. It's also possible
128
0
    // that the element at i has a end time before aTime, but that's OK.
129
0
    for (; i < GetSize(); ++i) {
130
0
      RefPtr<T> elem = static_cast<T*>(ObjectAt(static_cast<size_t>(i)));
131
0
      aResult->AppendElement(elem);
132
0
    }
133
0
  }
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::GetElementsAfter(long, nsTArray<RefPtr<mozilla::AudioData> >*)
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::GetElementsAfter(long, nsTArray<RefPtr<mozilla::VideoData> >*)
134
135
  void GetElementsAfter(const media::TimeUnit& aTime,
136
0
                        nsTArray<RefPtr<T>>* aResult) {
137
0
    GetElementsAfter(aTime.ToMicroseconds(), aResult);
138
0
  }
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::GetElementsAfter(mozilla::media::TimeUnit const&, nsTArray<RefPtr<mozilla::AudioData> >*)
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::GetElementsAfter(mozilla::media::TimeUnit const&, nsTArray<RefPtr<mozilla::VideoData> >*)
139
140
0
  void GetFirstElements(uint32_t aMaxElements, nsTArray<RefPtr<T>>* aResult) {
141
0
    RecursiveMutexAutoLock lock(mRecursiveMutex);
142
0
    for (size_t i = 0; i < aMaxElements && i < GetSize(); ++i) {
143
0
      *aResult->AppendElement() = static_cast<T*>(ObjectAt(i));
144
0
    }
145
0
  }
146
147
  uint32_t FrameCount() {
148
    RecursiveMutexAutoLock lock(mRecursiveMutex);
149
    uint32_t frames = 0;
150
    for (size_t i = 0; i < GetSize(); ++i) {
151
      T* v = static_cast<T*>(ObjectAt(i));
152
      frames += v->mFrames;
153
    }
154
    return frames;
155
  }
156
157
  MediaEventSource<RefPtr<T>>& PopEvent() {
158
    return mPopEvent;
159
  }
160
161
0
  MediaEventSource<RefPtr<T>>& PushEvent() {
162
0
    return mPushEvent;
163
0
  }
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::PushEvent()
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::PushEvent()
164
165
0
  MediaEventSource<void>& FinishEvent() {
166
0
    return mFinishEvent;
167
0
  }
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::FinishEvent()
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::FinishEvent()
168
169
private:
170
  mutable RecursiveMutex mRecursiveMutex;
171
  MediaEventProducer<RefPtr<T>> mPopEvent;
172
  MediaEventProducer<RefPtr<T>> mPushEvent;
173
  MediaEventProducer<void> mFinishEvent;
174
  // True when we've decoded the last frame of data in the
175
  // bitstream for which we're queueing frame data.
176
  bool mEndOfStream;
177
};
178
179
} // namespace mozilla
180
181
#endif