Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/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
0
  {
23
0
    RefPtr<T> releaseMe = dont_AddRef(static_cast<T*>(aObject));
24
0
  }
Unexecuted instantiation: mozilla::MediaQueueDeallocator<mozilla::AudioData>::operator()(void*)
Unexecuted instantiation: mozilla::MediaQueueDeallocator<mozilla::VideoData>::operator()(void*)
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
0
  {}
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::MediaQueue()
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::MediaQueue()
35
36
0
  ~MediaQueue() {
37
0
    Reset();
38
0
  }
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::~MediaQueue()
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::~MediaQueue()
39
40
0
  inline size_t GetSize() const {
41
0
    RecursiveMutexAutoLock lock(mRecursiveMutex);
42
0
    return nsDeque::GetSize();
43
0
  }
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::GetSize() const
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::GetSize() const
44
45
0
  inline void Push(T* aItem) {
46
0
    RecursiveMutexAutoLock lock(mRecursiveMutex);
47
0
    MOZ_ASSERT(!mEndOfStream);
48
0
    MOZ_ASSERT(aItem);
49
0
    NS_ADDREF(aItem);
50
0
    MOZ_ASSERT(aItem->GetEndTime() >= aItem->mTime);
51
0
    nsDeque::Push(aItem);
52
0
    mPushEvent.Notify(RefPtr<T>(aItem));
53
0
  }
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::Push(mozilla::AudioData*)
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::Push(mozilla::VideoData*)
54
55
0
  inline already_AddRefed<T> PopFront() {
56
0
    RecursiveMutexAutoLock lock(mRecursiveMutex);
57
0
    RefPtr<T> rv = dont_AddRef(static_cast<T*>(nsDeque::PopFront()));
58
0
    if (rv) {
59
0
      mPopEvent.Notify(rv);
60
0
    }
61
0
    return rv.forget();
62
0
  }
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::PopFront()
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::PopFront()
63
64
0
  inline RefPtr<T> PeekFront() const {
65
0
    RecursiveMutexAutoLock lock(mRecursiveMutex);
66
0
    return static_cast<T*>(nsDeque::PeekFront());
67
0
  }
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::PeekFront() const
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::PeekFront() const
68
69
0
  void Reset() {
70
0
    RecursiveMutexAutoLock lock(mRecursiveMutex);
71
0
    while (GetSize() > 0) {
72
0
      RefPtr<T> x = dont_AddRef(static_cast<T*>(nsDeque::PopFront()));
73
0
    }
74
0
    mEndOfStream = false;
75
0
  }
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::Reset()
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::Reset()
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
0
  bool IsFinished() const {
86
0
    RecursiveMutexAutoLock lock(mRecursiveMutex);
87
0
    return mEndOfStream;
88
0
  }
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::IsFinished() const
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::IsFinished() const
89
90
  // Informs the media queue that it won't be receiving any more items.
91
0
  void Finish() {
92
0
    RecursiveMutexAutoLock lock(mRecursiveMutex);
93
0
    if (!mEndOfStream) {
94
0
      mEndOfStream = true;
95
0
      mFinishEvent.Notify();
96
0
    }
97
0
  }
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::Finish()
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::Finish()
98
99
  // Returns the approximate number of microseconds of items in the queue.
100
0
  int64_t Duration() {
101
0
    RecursiveMutexAutoLock lock(mRecursiveMutex);
102
0
    if (GetSize() == 0) {
103
0
      return 0;
104
0
    }
105
0
    T* last = static_cast<T*>(nsDeque::Peek());
106
0
    T* first = static_cast<T*>(nsDeque::PeekFront());
107
0
    return (last->GetEndTime() - first->mTime).ToMicroseconds();
108
0
  }
109
110
0
  void LockedForEach(nsDequeFunctor& aFunctor) const {
111
0
    RecursiveMutexAutoLock lock(mRecursiveMutex);
112
0
    ForEach(aFunctor);
113
0
  }
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::LockedForEach(nsDequeFunctor&) const
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::LockedForEach(nsDequeFunctor&) const
114
115
  // Extracts elements from the queue into aResult, in order.
116
  // Elements whose start time is before aTime are ignored.
117
  void GetElementsAfter(int64_t aTime, nsTArray<RefPtr<T>>* aResult) {
118
    RecursiveMutexAutoLock lock(mRecursiveMutex);
119
    if (GetSize() == 0)
120
      return;
121
    size_t i;
122
    for (i = GetSize() - 1; i > 0; --i) {
123
      T* v = static_cast<T*>(ObjectAt(i));
124
      if (v->GetEndTime().ToMicroseconds() < aTime)
125
        break;
126
    }
127
    // Elements less than i have a end time before aTime. It's also possible
128
    // that the element at i has a end time before aTime, but that's OK.
129
    for (; i < GetSize(); ++i) {
130
      RefPtr<T> elem = static_cast<T*>(ObjectAt(static_cast<size_t>(i)));
131
      aResult->AppendElement(elem);
132
    }
133
  }
134
135
  void GetElementsAfter(const media::TimeUnit& aTime,
136
                        nsTArray<RefPtr<T>>* aResult) {
137
    GetElementsAfter(aTime.ToMicroseconds(), aResult);
138
  }
139
140
  void GetFirstElements(uint32_t aMaxElements, nsTArray<RefPtr<T>>* aResult) {
141
    RecursiveMutexAutoLock lock(mRecursiveMutex);
142
    for (size_t i = 0; i < aMaxElements && i < GetSize(); ++i) {
143
      *aResult->AppendElement() = static_cast<T*>(ObjectAt(i));
144
    }
145
  }
146
147
0
  uint32_t FrameCount() {
148
0
    RecursiveMutexAutoLock lock(mRecursiveMutex);
149
0
    uint32_t frames = 0;
150
0
    for (size_t i = 0; i < GetSize(); ++i) {
151
0
      T* v = static_cast<T*>(ObjectAt(i));
152
0
      frames += v->mFrames;
153
0
    }
154
0
    return frames;
155
0
  }
156
157
0
  MediaEventSource<RefPtr<T>>& PopEvent() {
158
0
    return mPopEvent;
159
0
  }
Unexecuted instantiation: mozilla::MediaQueue<mozilla::AudioData>::PopEvent()
Unexecuted instantiation: mozilla::MediaQueue<mozilla::VideoData>::PopEvent()
160
161
  MediaEventSource<RefPtr<T>>& PushEvent() {
162
    return mPushEvent;
163
  }
164
165
  MediaEventSource<void>& FinishEvent() {
166
    return mFinishEvent;
167
  }
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