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_)
11 #include "mozilla/ReentrantMonitor.h"
12 #include "mozilla/RefPtr.h"
13 #include "MediaTaskQueue.h"
17 // Thread and type safe wrapper around nsDeque.
19 class MediaQueueDeallocator
: public nsDequeFunctor
{
20 virtual void* operator() (void* aObject
) {
21 delete static_cast<T
*>(aObject
);
26 template <class T
> class MediaQueue
: private nsDeque
{
30 : nsDeque(new MediaQueueDeallocator
<T
>()),
31 mReentrantMonitor("mediaqueue"),
39 inline int32_t GetSize() {
40 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
41 return nsDeque::GetSize();
44 inline void Push(T
* aItem
) {
45 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
50 inline void PushFront(T
* aItem
) {
51 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
53 nsDeque::PushFront(aItem
);
56 inline T
* PopFront() {
57 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
58 T
* rv
= static_cast<T
*>(nsDeque::PopFront());
66 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
67 return static_cast<T
*>(nsDeque::Peek());
70 inline T
* PeekFront() {
71 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
72 return static_cast<T
*>(nsDeque::PeekFront());
76 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
81 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
82 while (GetSize() > 0) {
89 bool AtEndOfStream() {
90 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
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.
98 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
102 // Informs the media queue that it won't be receiving any more items.
104 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
108 // Returns the approximate number of microseconds of items in the queue.
110 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
115 T
* first
= PeekFront();
116 return last
->mTime
- first
->mTime
;
119 void LockedForEach(nsDequeFunctor
& aFunctor
) const {
120 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
124 // Extracts elements from the queue into aResult, in order.
125 // Elements whose start time is before aTime are ignored.
126 void GetElementsAfter(int64_t aTime
, nsTArray
<T
*>* aResult
) {
127 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
131 for (i
= GetSize() - 1; i
> 0; --i
) {
132 T
* v
= static_cast<T
*>(ObjectAt(i
));
133 if (v
->GetEndTime() < aTime
)
136 // Elements less than i have a end time before aTime. It's also possible
137 // that the element at i has a end time before aTime, but that's OK.
138 for (; i
< GetSize(); ++i
) {
139 aResult
->AppendElement(static_cast<T
*>(ObjectAt(i
)));
143 uint32_t FrameCount() {
144 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
146 for (int32_t i
= 0; i
< GetSize(); ++i
) {
147 T
* v
= static_cast<T
*>(ObjectAt(i
));
148 frames
+= v
->mFrames
;
153 void ClearListeners() {
154 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
155 mPopListeners
.Clear();
158 void AddPopListener(nsIRunnable
* aRunnable
, MediaTaskQueue
* aTaskQueue
) {
159 ReentrantMonitorAutoEnter
mon(mReentrantMonitor
);
160 mPopListeners
.AppendElement(Listener(aRunnable
, aTaskQueue
));
164 mutable ReentrantMonitor mReentrantMonitor
;
167 Listener(nsIRunnable
* aRunnable
, MediaTaskQueue
* aTaskQueue
)
168 : mRunnable(aRunnable
)
169 , mTarget(aTaskQueue
)
172 Listener(const Listener
& aOther
)
173 : mRunnable(aOther
.mRunnable
)
174 , mTarget(aOther
.mTarget
)
177 RefPtr
<nsIRunnable
> mRunnable
;
178 RefPtr
<MediaTaskQueue
> mTarget
;
181 nsTArray
<Listener
> mPopListeners
;
183 void NotifyPopListeners() {
184 for (uint32_t i
= 0; i
< mPopListeners
.Length(); i
++) {
185 Listener
& l
= mPopListeners
[i
];
186 l
.mTarget
->Dispatch(l
.mRunnable
);
190 // True when we've decoded the last frame of data in the
191 // bitstream for which we're queueing frame data.
195 } // namespace mozilla