Bug 1708422: part 16) Rename `mozInlineSpellChecker::SpellCheckerTimeSlice` to `mozIn...
[gecko.git] / dom / media / MediaQueue.h
blob6950b209a75548dba2c00d89800614f76d3a0e52
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_
9 # include <type_traits>
11 # include "mozilla/RecursiveMutex.h"
12 # include "mozilla/TaskQueue.h"
14 # include "nsDeque.h"
15 # include "MediaEventSource.h"
16 # include "TimeUnits.h"
18 namespace mozilla {
20 class AudioData;
22 template <class T>
23 class MediaQueue : private nsRefPtrDeque<T> {
24 public:
25 MediaQueue()
26 : nsRefPtrDeque<T>(),
27 mRecursiveMutex("mediaqueue"),
28 mEndOfStream(false) {}
30 ~MediaQueue() { Reset(); }
32 inline size_t GetSize() const {
33 RecursiveMutexAutoLock lock(mRecursiveMutex);
34 return nsRefPtrDeque<T>::GetSize();
37 inline void Push(T* aItem) {
38 MOZ_DIAGNOSTIC_ASSERT(aItem);
39 Push(do_AddRef(aItem));
42 inline void Push(already_AddRefed<T> aItem) {
43 RecursiveMutexAutoLock lock(mRecursiveMutex);
44 T* item = aItem.take();
46 MOZ_DIAGNOSTIC_ASSERT(item);
47 MOZ_DIAGNOSTIC_ASSERT(item->GetEndTime() >= item->mTime);
48 nsRefPtrDeque<T>::Push(dont_AddRef(item));
49 mPushEvent.Notify(RefPtr<T>(item));
51 // Pushing new data after queue has ended means that the stream is active
52 // again, so we should not mark it as ended.
53 if (mEndOfStream) {
54 mEndOfStream = false;
58 inline already_AddRefed<T> PopFront() {
59 RecursiveMutexAutoLock lock(mRecursiveMutex);
60 RefPtr<T> rv = nsRefPtrDeque<T>::PopFront();
61 if (rv) {
62 MOZ_DIAGNOSTIC_ASSERT(rv->GetEndTime() >= rv->mTime);
63 mPopFrontEvent.Notify(RefPtr<T>(rv));
65 return rv.forget();
68 inline already_AddRefed<T> PopBack() {
69 RecursiveMutexAutoLock lock(mRecursiveMutex);
70 return nsRefPtrDeque<T>::Pop();
73 inline RefPtr<T> PeekFront() const {
74 RecursiveMutexAutoLock lock(mRecursiveMutex);
75 return nsRefPtrDeque<T>::PeekFront();
78 inline RefPtr<T> PeekBack() const {
79 RecursiveMutexAutoLock lock(mRecursiveMutex);
80 return nsRefPtrDeque<T>::Peek();
83 void Reset() {
84 RecursiveMutexAutoLock lock(mRecursiveMutex);
85 nsRefPtrDeque<T>::Erase();
86 mEndOfStream = false;
89 bool AtEndOfStream() const {
90 RecursiveMutexAutoLock lock(mRecursiveMutex);
91 return GetSize() == 0 && mEndOfStream;
94 // Returns true if the media queue has had its last item added to it.
95 // This happens when the media stream has been completely decoded. Note this
96 // does not mean that the corresponding stream has finished playback.
97 bool IsFinished() const {
98 RecursiveMutexAutoLock lock(mRecursiveMutex);
99 return mEndOfStream;
102 // Informs the media queue that it won't be receiving any more items.
103 void Finish() {
104 RecursiveMutexAutoLock lock(mRecursiveMutex);
105 if (!mEndOfStream) {
106 mEndOfStream = true;
107 mFinishEvent.Notify();
111 // Returns the approximate number of microseconds of items in the queue.
112 int64_t Duration() {
113 RecursiveMutexAutoLock lock(mRecursiveMutex);
114 if (GetSize() == 0) {
115 return 0;
117 T* last = nsRefPtrDeque<T>::Peek();
118 T* first = nsRefPtrDeque<T>::PeekFront();
119 return (last->GetEndTime() - first->mTime).ToMicroseconds();
122 void LockedForEach(nsDequeFunctor<T>& aFunctor) const {
123 RecursiveMutexAutoLock lock(mRecursiveMutex);
124 nsRefPtrDeque<T>::ForEach(aFunctor);
127 // Fill aResult with the elements which end later than the given time aTime.
128 void GetElementsAfter(const media::TimeUnit& aTime,
129 nsTArray<RefPtr<T>>* aResult) {
130 GetElementsAfterStrict(aTime.ToMicroseconds(), aResult);
133 void GetFirstElements(uint32_t aMaxElements, nsTArray<RefPtr<T>>* aResult) {
134 RecursiveMutexAutoLock lock(mRecursiveMutex);
135 for (size_t i = 0; i < aMaxElements && i < GetSize(); ++i) {
136 *aResult->AppendElement() = nsRefPtrDeque<T>::ObjectAt(i);
140 uint32_t AudioFramesCount() {
141 static_assert(std::is_same_v<T, AudioData>,
142 "Only usable with MediaQueue<AudioData>");
143 RecursiveMutexAutoLock lock(mRecursiveMutex);
144 uint32_t frames = 0;
145 for (size_t i = 0; i < GetSize(); ++i) {
146 T* v = nsRefPtrDeque<T>::ObjectAt(i);
147 frames += v->Frames();
149 return frames;
152 MediaEventSource<RefPtr<T>>& PopFrontEvent() { return mPopFrontEvent; }
154 MediaEventSource<RefPtr<T>>& PushEvent() { return mPushEvent; }
156 MediaEventSource<void>& FinishEvent() { return mFinishEvent; }
158 private:
159 // Extracts elements from the queue into aResult, in order.
160 // Elements whose end time is before or equal to aTime are ignored.
161 void GetElementsAfterStrict(int64_t aTime, nsTArray<RefPtr<T>>* aResult) {
162 RecursiveMutexAutoLock lock(mRecursiveMutex);
163 if (GetSize() == 0) return;
164 size_t i;
165 for (i = GetSize() - 1; i > 0; --i) {
166 T* v = nsRefPtrDeque<T>::ObjectAt(i);
167 if (v->GetEndTime().ToMicroseconds() < aTime) break;
169 for (; i < GetSize(); ++i) {
170 RefPtr<T> elem = nsRefPtrDeque<T>::ObjectAt(i);
171 if (elem->GetEndTime().ToMicroseconds() > aTime) {
172 aResult->AppendElement(elem);
177 mutable RecursiveMutex mRecursiveMutex;
178 MediaEventProducer<RefPtr<T>> mPopFrontEvent;
179 MediaEventProducer<RefPtr<T>> mPushEvent;
180 MediaEventProducer<void> mFinishEvent;
181 // True when we've decoded the last frame of data in the
182 // bitstream for which we're queueing frame data.
183 bool mEndOfStream;
186 } // namespace mozilla
188 #endif