Removing MediaStreamTrackVector and MediaStreamSourceVector typedefs
[WebKit-https.git] / Source / WebCore / Modules / mediastream / MediaStream.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  * Copyright (C) 2011, 2012 Ericsson AB. All rights reserved.
4  * Copyright (C) 2013 Apple Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "MediaStream.h"
29
30 #if ENABLE(MEDIA_STREAM)
31
32 #include "AudioStreamTrack.h"
33 #include "Event.h"
34 #include "ExceptionCode.h"
35 #include "MediaStreamCenter.h"
36 #include "MediaStreamRegistry.h"
37 #include "MediaStreamSource.h"
38 #include "MediaStreamTrackEvent.h"
39 #include "VideoStreamTrack.h"
40 #include <wtf/NeverDestroyed.h>
41
42 namespace WebCore {
43
44 PassRefPtr<MediaStream> MediaStream::create(ScriptExecutionContext& context)
45 {
46     return MediaStream::create(context, MediaStreamDescriptor::create(Vector<RefPtr<MediaStreamSource>>(), Vector<RefPtr<MediaStreamSource>>()));
47 }
48
49 PassRefPtr<MediaStream> MediaStream::create(ScriptExecutionContext& context, PassRefPtr<MediaStream> stream)
50 {
51     ASSERT(stream);
52
53     Vector<RefPtr<MediaStreamTrackPrivate>> audioTracks;
54     Vector<RefPtr<MediaStreamTrackPrivate>> videoTracks;
55
56     for (size_t i = 0; i < stream->m_audioTracks.size(); ++i)
57         audioTracks.append(&stream->m_audioTracks[i]->privateTrack());
58
59     for (size_t i = 0; i < stream->m_videoTracks.size(); ++i)
60         videoTracks.append(&stream->m_videoTracks[i]->privateTrack());
61
62     return MediaStream::create(context, MediaStreamDescriptor::create(audioTracks, videoTracks));
63 }
64
65 PassRefPtr<MediaStream> MediaStream::create(ScriptExecutionContext& context, const Vector<RefPtr<MediaStreamTrack>>& tracks)
66 {
67     Vector<RefPtr<MediaStreamTrackPrivate>> audioTracks;
68     Vector<RefPtr<MediaStreamTrackPrivate>> videoTracks;
69
70     for (size_t i = 0; i < tracks.size(); ++i) {
71         if (tracks[i]->kind() == "audio")
72             audioTracks.append(&tracks[i]->privateTrack());
73         else
74             videoTracks.append(&tracks[i]->privateTrack());
75     }
76
77     return MediaStream::create(context, MediaStreamDescriptor::create(audioTracks, videoTracks));
78 }
79
80 PassRefPtr<MediaStream> MediaStream::create(ScriptExecutionContext& context, PassRefPtr<MediaStreamDescriptor> streamDescriptor)
81 {
82     return adoptRef(new MediaStream(context, streamDescriptor));
83 }
84
85 MediaStream::MediaStream(ScriptExecutionContext& context, PassRefPtr<MediaStreamDescriptor> streamDescriptor)
86     : ContextDestructionObserver(&context)
87     , m_descriptor(streamDescriptor)
88     , m_scheduledEventTimer(this, &MediaStream::scheduledEventTimerFired)
89 {
90     ASSERT(m_descriptor);
91     m_descriptor->setClient(this);
92
93     RefPtr<MediaStreamTrack> track;
94     size_t numberOfAudioTracks = m_descriptor->numberOfAudioTracks();
95     m_audioTracks.reserveCapacity(numberOfAudioTracks);
96     for (size_t i = 0; i < numberOfAudioTracks; i++) {
97         track = AudioStreamTrack::create(context, *m_descriptor->audioTracks(i));
98         track->addObserver(this);
99         m_audioTracks.append(track.release());
100     }
101
102     size_t numberOfVideoTracks = m_descriptor->numberOfVideoTracks();
103     m_videoTracks.reserveCapacity(numberOfVideoTracks);
104     for (size_t i = 0; i < numberOfVideoTracks; i++) {
105         track = VideoStreamTrack::create(context, *m_descriptor->videoTracks(i));
106         track->addObserver(this);
107         m_videoTracks.append(track.release());
108     }
109 }
110
111 MediaStream::~MediaStream()
112 {
113     m_descriptor->setClient(0);
114 }
115
116 bool MediaStream::ended() const
117 {
118     return m_descriptor->ended();
119 }
120
121 void MediaStream::setEnded()
122 {
123     if (ended())
124         return;
125     m_descriptor->setEnded();
126 }
127
128 PassRefPtr<MediaStream> MediaStream::clone()
129 {
130     Vector<RefPtr<MediaStreamTrack>> trackSet;
131
132     cloneMediaStreamTrackVector(trackSet, getAudioTracks());
133     cloneMediaStreamTrackVector(trackSet, getVideoTracks());
134     return MediaStream::create(*scriptExecutionContext(), trackSet);
135 }
136
137 void MediaStream::cloneMediaStreamTrackVector(Vector<RefPtr<MediaStreamTrack>>& destination, const Vector<RefPtr<MediaStreamTrack>>& source)
138 {
139     for (unsigned i = 0; i < source.size(); i++)
140         destination.append(source[i]->clone());
141 }
142
143 void MediaStream::addTrack(PassRefPtr<MediaStreamTrack> prpTrack, ExceptionCode& ec)
144 {
145     if (ended()) {
146         ec = INVALID_STATE_ERR;
147         return;
148     }
149
150     if (!prpTrack) {
151         ec = TYPE_MISMATCH_ERR;
152         return;
153     }
154
155     addTrack(prpTrack);
156 }
157
158 bool MediaStream::addTrack(PassRefPtr<MediaStreamTrack> prpTrack)
159 {
160     // This is a common part used by addTrack called by JavaScript
161     // and addRemoteTrack and only addRemoteTrack must fire addtrack event
162     RefPtr<MediaStreamTrack> track = prpTrack;
163     if (getTrackById(track->id()))
164         return false;
165
166     Vector<RefPtr<MediaStreamTrack>>* tracks = trackVectorForType(track->source()->type());
167
168     tracks->append(track);
169     track->addObserver(this);
170     m_descriptor->addTrack(&track->privateTrack());
171     return true;
172 }
173
174 void MediaStream::removeTrack(PassRefPtr<MediaStreamTrack> prpTrack, ExceptionCode& ec)
175 {
176     if (ended()) {
177         ec = INVALID_STATE_ERR;
178         return;
179     }
180
181     if (!prpTrack) {
182         ec = TYPE_MISMATCH_ERR;
183         return;
184     }
185
186     removeTrack(prpTrack);
187 }
188
189 bool MediaStream::removeTrack(PassRefPtr<MediaStreamTrack> prpTrack)
190 {
191     // This is a common part used by removeTrack called by JavaScript
192     // and removeRemoteTrack and only removeRemoteTrack must fire removetrack event
193     RefPtr<MediaStreamTrack> track = prpTrack;
194     Vector<RefPtr<MediaStreamTrack>>* tracks = trackVectorForType(track->source()->type());
195
196     size_t pos = tracks->find(track);
197     if (pos == notFound)
198         return false;
199
200     tracks->remove(pos);
201     m_descriptor->removeTrack(&track->privateTrack());
202     // There can be other tracks using the same source in the same MediaStream,
203     // like when MediaStreamTrack::clone() is called, for instance.
204     // Spec says that a source can be shared, so we must assure that there is no
205     // other track using it.
206     if (!haveTrackWithSource(track->source()))
207         m_descriptor->removeSource(track->source());
208
209     track->removeObserver(this);
210     if (!m_audioTracks.size() && !m_videoTracks.size())
211         setEnded();
212
213     return true;
214 }
215
216 bool MediaStream::haveTrackWithSource(PassRefPtr<MediaStreamSource> source)
217 {
218     if (source->type() == MediaStreamSource::Audio) {
219         for (auto iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter) {
220             if ((*iter)->source() == source.get())
221                 return true;
222         }
223         return false;
224     }
225
226     for (auto iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter) {
227         if ((*iter)->source() == source.get())
228             return true;
229     }
230
231     return false;
232 }
233
234 MediaStreamTrack* MediaStream::getTrackById(String id)
235 {
236     for (auto iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter) {
237         if ((*iter)->id() == id)
238             return (*iter).get();
239     }
240
241     for (auto iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter) {
242         if ((*iter)->id() == id)
243             return (*iter).get();
244     }
245
246     return 0;
247 }
248
249 void MediaStream::trackDidEnd()
250 {
251     for (size_t i = 0; i < m_audioTracks.size(); ++i)
252         if (!m_audioTracks[i]->ended())
253             return;
254     
255     for (size_t i = 0; i < m_videoTracks.size(); ++i)
256         if (!m_videoTracks[i]->ended())
257             return;
258     
259     setEnded();
260 }
261
262 void MediaStream::streamDidEnd()
263 {
264     if (ended())
265         return;
266
267     scheduleDispatchEvent(Event::create(eventNames().endedEvent, false, false));
268 }
269
270 void MediaStream::contextDestroyed()
271 {
272     ContextDestructionObserver::contextDestroyed();
273 }
274
275 void MediaStream::addRemoteSource(MediaStreamSource* source)
276 {
277     ASSERT(source);
278     addRemoteTrack(MediaStreamTrackPrivate::create(source).get());
279 }
280
281 void MediaStream::removeRemoteSource(MediaStreamSource* source)
282 {
283     ASSERT(source);
284     if (ended())
285         return;
286
287     Vector<RefPtr<MediaStreamTrack>>* tracks = trackVectorForType(source->type());
288
289     for (int i = tracks->size() - 1; i >= 0; --i) {
290         if ((*tracks)[i]->source() != source)
291             continue;
292
293         RefPtr<MediaStreamTrack> track = (*tracks)[i];
294         track->removeObserver(this);
295         tracks->remove(i);
296         m_descriptor->removeTrack(&track->privateTrack());
297         scheduleDispatchEvent(MediaStreamTrackEvent::create(eventNames().removetrackEvent, false, false, track.release()));
298     }
299
300     m_descriptor->removeSource(source);
301 }
302
303 void MediaStream::addRemoteTrack(MediaStreamTrackPrivate* privateTrack)
304 {
305     ASSERT(privateTrack);
306     if (ended())
307         return;
308
309     RefPtr<MediaStreamTrack> track;
310     switch (privateTrack->type()) {
311     case MediaStreamSource::Audio:
312         track = AudioStreamTrack::create(*scriptExecutionContext(), *privateTrack);
313         break;
314     case MediaStreamSource::Video:
315         track = VideoStreamTrack::create(*scriptExecutionContext(), *privateTrack);
316         break;
317     case MediaStreamSource::None:
318         ASSERT_NOT_REACHED();
319         break;
320     }
321
322     if (!track)
323         return;
324
325     if (addTrack(track))
326         scheduleDispatchEvent(MediaStreamTrackEvent::create(eventNames().addtrackEvent, false, false, track));
327 }
328
329 void MediaStream::removeRemoteTrack(MediaStreamTrackPrivate* privateTrack)
330 {
331     ASSERT(privateTrack);
332     if (ended())
333         return;
334
335     RefPtr<MediaStreamTrack> track = getTrackById(privateTrack->id());
336     if (removeTrack(track))
337         scheduleDispatchEvent(MediaStreamTrackEvent::create(eventNames().removetrackEvent, false, false, track.release()));
338 }
339
340 void MediaStream::scheduleDispatchEvent(PassRefPtr<Event> event)
341 {
342     m_scheduledEvents.append(event);
343
344     if (!m_scheduledEventTimer.isActive())
345         m_scheduledEventTimer.startOneShot(0);
346 }
347
348 void MediaStream::scheduledEventTimerFired(Timer<MediaStream>*)
349 {
350     Vector<RefPtr<Event>> events;
351     events.swap(m_scheduledEvents);
352
353     Vector<RefPtr<Event>>::iterator it = events.begin();
354     for (; it != events.end(); ++it)
355         dispatchEvent((*it).release());
356
357     events.clear();
358 }
359
360 URLRegistry& MediaStream::registry() const
361 {
362     return MediaStreamRegistry::registry();
363 }
364
365 Vector<RefPtr<MediaStreamTrack>>* MediaStream::trackVectorForType(MediaStreamSource::Type type)
366 {
367     switch (type) {
368     case MediaStreamSource::Audio:
369         return &m_audioTracks;
370     case MediaStreamSource::Video:
371         return &m_videoTracks;
372     case MediaStreamSource::None:
373         ASSERT_NOT_REACHED();
374     }
375     return nullptr;
376 }
377
378 } // namespace WebCore
379
380 #endif // ENABLE(MEDIA_STREAM)