OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | |
3 * Copyright (C) 2011, 2012 Ericsson AB. All rights reserved. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions | |
7 * are met: | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * | |
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND AN
Y | |
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR AN
Y | |
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND O
N | |
21 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 */ | |
25 | |
26 #include "config.h" | |
27 #include "modules/mediastream/MediaStream.h" | |
28 | |
29 #include "bindings/core/v8/ExceptionState.h" | |
30 #include "core/dom/ExceptionCode.h" | |
31 #include "modules/mediastream/MediaStreamRegistry.h" | |
32 #include "modules/mediastream/MediaStreamTrackEvent.h" | |
33 #include "platform/mediastream/MediaStreamCenter.h" | |
34 #include "platform/mediastream/MediaStreamSource.h" | |
35 | |
36 namespace blink { | |
37 | |
38 static bool containsSource(MediaStreamTrackVector& trackVector, MediaStreamSourc
e* source) | |
39 { | |
40 for (size_t i = 0; i < trackVector.size(); ++i) { | |
41 if (source->id() == trackVector[i]->component()->source()->id()) | |
42 return true; | |
43 } | |
44 return false; | |
45 } | |
46 | |
47 static void processTrack(MediaStreamTrack* track, MediaStreamTrackVector& trackV
ector) | |
48 { | |
49 if (track->ended()) | |
50 return; | |
51 | |
52 MediaStreamSource* source = track->component()->source(); | |
53 if (!containsSource(trackVector, source)) | |
54 trackVector.append(track); | |
55 } | |
56 | |
57 MediaStream* MediaStream::create(ExecutionContext* context) | |
58 { | |
59 MediaStreamTrackVector audioTracks; | |
60 MediaStreamTrackVector videoTracks; | |
61 | |
62 return new MediaStream(context, audioTracks, videoTracks); | |
63 } | |
64 | |
65 MediaStream* MediaStream::create(ExecutionContext* context, MediaStream* stream) | |
66 { | |
67 ASSERT(stream); | |
68 | |
69 MediaStreamTrackVector audioTracks; | |
70 MediaStreamTrackVector videoTracks; | |
71 | |
72 for (size_t i = 0; i < stream->m_audioTracks.size(); ++i) | |
73 processTrack(stream->m_audioTracks[i].get(), audioTracks); | |
74 | |
75 for (size_t i = 0; i < stream->m_videoTracks.size(); ++i) | |
76 processTrack(stream->m_videoTracks[i].get(), videoTracks); | |
77 | |
78 return new MediaStream(context, audioTracks, videoTracks); | |
79 } | |
80 | |
81 MediaStream* MediaStream::create(ExecutionContext* context, const MediaStreamTra
ckVector& tracks) | |
82 { | |
83 MediaStreamTrackVector audioTracks; | |
84 MediaStreamTrackVector videoTracks; | |
85 | |
86 for (size_t i = 0; i < tracks.size(); ++i) | |
87 processTrack(tracks[i].get(), tracks[i]->kind() == "audio" ? audioTracks
: videoTracks); | |
88 | |
89 return new MediaStream(context, audioTracks, videoTracks); | |
90 } | |
91 | |
92 MediaStream* MediaStream::create(ExecutionContext* context, MediaStreamDescripto
r* streamDescriptor) | |
93 { | |
94 return new MediaStream(context, streamDescriptor); | |
95 } | |
96 | |
97 MediaStream::MediaStream(ExecutionContext* context, MediaStreamDescriptor* strea
mDescriptor) | |
98 : ContextLifecycleObserver(context) | |
99 , m_stopped(false) | |
100 , m_descriptor(streamDescriptor) | |
101 , m_scheduledEventTimer(this, &MediaStream::scheduledEventTimerFired) | |
102 { | |
103 m_descriptor->setClient(this); | |
104 | |
105 size_t numberOfAudioTracks = m_descriptor->numberOfAudioComponents(); | |
106 m_audioTracks.reserveCapacity(numberOfAudioTracks); | |
107 for (size_t i = 0; i < numberOfAudioTracks; i++) { | |
108 MediaStreamTrack* newTrack = MediaStreamTrack::create(context, m_descrip
tor->audioComponent(i)); | |
109 newTrack->registerMediaStream(this); | |
110 m_audioTracks.append(newTrack); | |
111 } | |
112 | |
113 size_t numberOfVideoTracks = m_descriptor->numberOfVideoComponents(); | |
114 m_videoTracks.reserveCapacity(numberOfVideoTracks); | |
115 for (size_t i = 0; i < numberOfVideoTracks; i++) { | |
116 MediaStreamTrack* newTrack = MediaStreamTrack::create(context, m_descrip
tor->videoComponent(i)); | |
117 newTrack->registerMediaStream(this); | |
118 m_videoTracks.append(newTrack); | |
119 } | |
120 } | |
121 | |
122 MediaStream::MediaStream(ExecutionContext* context, const MediaStreamTrackVector
& audioTracks, const MediaStreamTrackVector& videoTracks) | |
123 : ContextLifecycleObserver(context) | |
124 , m_stopped(false) | |
125 , m_scheduledEventTimer(this, &MediaStream::scheduledEventTimerFired) | |
126 { | |
127 MediaStreamComponentVector audioComponents; | |
128 MediaStreamComponentVector videoComponents; | |
129 | |
130 MediaStreamTrackVector::const_iterator iter; | |
131 for (iter = audioTracks.begin(); iter != audioTracks.end(); ++iter) { | |
132 (*iter)->registerMediaStream(this); | |
133 audioComponents.append((*iter)->component()); | |
134 } | |
135 for (iter = videoTracks.begin(); iter != videoTracks.end(); ++iter) { | |
136 (*iter)->registerMediaStream(this); | |
137 videoComponents.append((*iter)->component()); | |
138 } | |
139 | |
140 m_descriptor = MediaStreamDescriptor::create(audioComponents, videoComponent
s); | |
141 m_descriptor->setClient(this); | |
142 MediaStreamCenter::instance().didCreateMediaStream(m_descriptor.get()); | |
143 | |
144 m_audioTracks = audioTracks; | |
145 m_videoTracks = videoTracks; | |
146 } | |
147 | |
148 MediaStream::~MediaStream() | |
149 { | |
150 } | |
151 | |
152 bool MediaStream::ended() const | |
153 { | |
154 return m_stopped || m_descriptor->ended(); | |
155 } | |
156 | |
157 MediaStreamTrackVector MediaStream::getTracks() | |
158 { | |
159 MediaStreamTrackVector tracks; | |
160 for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter !=
m_audioTracks.end(); ++iter) | |
161 tracks.append(iter->get()); | |
162 for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter !=
m_videoTracks.end(); ++iter) | |
163 tracks.append(iter->get()); | |
164 return tracks; | |
165 } | |
166 | |
167 void MediaStream::addTrack(MediaStreamTrack* track, ExceptionState& exceptionSta
te) | |
168 { | |
169 if (ended()) { | |
170 exceptionState.throwDOMException(InvalidStateError, "The MediaStream is
finished."); | |
171 return; | |
172 } | |
173 | |
174 if (!track) { | |
175 exceptionState.throwDOMException(TypeMismatchError, "The MediaStreamTrac
k provided is invalid."); | |
176 return; | |
177 } | |
178 | |
179 if (getTrackById(track->id())) | |
180 return; | |
181 | |
182 switch (track->component()->source()->type()) { | |
183 case MediaStreamSource::TypeAudio: | |
184 m_audioTracks.append(track); | |
185 break; | |
186 case MediaStreamSource::TypeVideo: | |
187 m_videoTracks.append(track); | |
188 break; | |
189 } | |
190 track->registerMediaStream(this); | |
191 m_descriptor->addComponent(track->component()); | |
192 MediaStreamCenter::instance().didAddMediaStreamTrack(m_descriptor.get(), tra
ck->component()); | |
193 } | |
194 | |
195 void MediaStream::removeTrack(MediaStreamTrack* track, ExceptionState& exception
State) | |
196 { | |
197 if (ended()) { | |
198 exceptionState.throwDOMException(InvalidStateError, "The MediaStream is
finished."); | |
199 return; | |
200 } | |
201 | |
202 if (!track) { | |
203 exceptionState.throwDOMException(TypeMismatchError, "The MediaStreamTrac
k provided is invalid."); | |
204 return; | |
205 } | |
206 | |
207 size_t pos = kNotFound; | |
208 switch (track->component()->source()->type()) { | |
209 case MediaStreamSource::TypeAudio: | |
210 pos = m_audioTracks.find(track); | |
211 if (pos != kNotFound) | |
212 m_audioTracks.remove(pos); | |
213 break; | |
214 case MediaStreamSource::TypeVideo: | |
215 pos = m_videoTracks.find(track); | |
216 if (pos != kNotFound) | |
217 m_videoTracks.remove(pos); | |
218 break; | |
219 } | |
220 | |
221 if (pos == kNotFound) | |
222 return; | |
223 track->unregisterMediaStream(this); | |
224 m_descriptor->removeComponent(track->component()); | |
225 | |
226 if (!m_audioTracks.size() && !m_videoTracks.size()) | |
227 m_descriptor->setEnded(); | |
228 | |
229 MediaStreamCenter::instance().didRemoveMediaStreamTrack(m_descriptor.get(),
track->component()); | |
230 } | |
231 | |
232 MediaStreamTrack* MediaStream::getTrackById(String id) | |
233 { | |
234 for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter !=
m_audioTracks.end(); ++iter) { | |
235 if ((*iter)->id() == id) | |
236 return iter->get(); | |
237 } | |
238 | |
239 for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter !=
m_videoTracks.end(); ++iter) { | |
240 if ((*iter)->id() == id) | |
241 return iter->get(); | |
242 } | |
243 | |
244 return 0; | |
245 } | |
246 | |
247 MediaStream* MediaStream::clone(ExecutionContext* context) | |
248 { | |
249 MediaStreamTrackVector tracks; | |
250 for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter !=
m_audioTracks.end(); ++iter) | |
251 tracks.append((*iter)->clone(context)); | |
252 for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter !=
m_videoTracks.end(); ++iter) | |
253 tracks.append((*iter)->clone(context)); | |
254 return MediaStream::create(context, tracks); | |
255 } | |
256 | |
257 void MediaStream::stop() | |
258 { | |
259 if (ended()) | |
260 return; | |
261 | |
262 MediaStreamCenter::instance().didStopLocalMediaStream(descriptor()); | |
263 | |
264 streamEnded(); | |
265 } | |
266 | |
267 void MediaStream::trackEnded() | |
268 { | |
269 for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter !=
m_audioTracks.end(); ++iter) { | |
270 if (!(*iter)->ended()) | |
271 return; | |
272 } | |
273 | |
274 for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter !=
m_videoTracks.end(); ++iter) { | |
275 if (!(*iter)->ended()) | |
276 return; | |
277 } | |
278 | |
279 streamEnded(); | |
280 } | |
281 | |
282 void MediaStream::streamEnded() | |
283 { | |
284 if (ended()) | |
285 return; | |
286 | |
287 m_descriptor->setEnded(); | |
288 scheduleDispatchEvent(Event::create(EventTypeNames::ended)); | |
289 } | |
290 | |
291 void MediaStream::contextDestroyed() | |
292 { | |
293 ContextLifecycleObserver::contextDestroyed(); | |
294 m_stopped = true; | |
295 } | |
296 | |
297 const AtomicString& MediaStream::interfaceName() const | |
298 { | |
299 return EventTargetNames::MediaStream; | |
300 } | |
301 | |
302 ExecutionContext* MediaStream::executionContext() const | |
303 { | |
304 return ContextLifecycleObserver::executionContext(); | |
305 } | |
306 | |
307 void MediaStream::addRemoteTrack(MediaStreamComponent* component) | |
308 { | |
309 ASSERT(component); | |
310 if (ended()) | |
311 return; | |
312 | |
313 MediaStreamTrack* track = MediaStreamTrack::create(executionContext(), compo
nent); | |
314 switch (component->source()->type()) { | |
315 case MediaStreamSource::TypeAudio: | |
316 m_audioTracks.append(track); | |
317 break; | |
318 case MediaStreamSource::TypeVideo: | |
319 m_videoTracks.append(track); | |
320 break; | |
321 } | |
322 track->registerMediaStream(this); | |
323 m_descriptor->addComponent(component); | |
324 | |
325 scheduleDispatchEvent(MediaStreamTrackEvent::create(EventTypeNames::addtrack
, false, false, track)); | |
326 } | |
327 | |
328 void MediaStream::removeRemoteTrack(MediaStreamComponent* component) | |
329 { | |
330 if (m_stopped) | |
331 return; | |
332 | |
333 MediaStreamTrackVector* tracks = 0; | |
334 switch (component->source()->type()) { | |
335 case MediaStreamSource::TypeAudio: | |
336 tracks = &m_audioTracks; | |
337 break; | |
338 case MediaStreamSource::TypeVideo: | |
339 tracks = &m_videoTracks; | |
340 break; | |
341 } | |
342 | |
343 size_t index = kNotFound; | |
344 for (size_t i = 0; i < tracks->size(); ++i) { | |
345 if ((*tracks)[i]->component() == component) { | |
346 index = i; | |
347 break; | |
348 } | |
349 } | |
350 if (index == kNotFound) | |
351 return; | |
352 | |
353 m_descriptor->removeComponent(component); | |
354 | |
355 MediaStreamTrack* track = (*tracks)[index]; | |
356 track->unregisterMediaStream(this); | |
357 tracks->remove(index); | |
358 scheduleDispatchEvent(MediaStreamTrackEvent::create(EventTypeNames::removetr
ack, false, false, track)); | |
359 } | |
360 | |
361 void MediaStream::scheduleDispatchEvent(PassRefPtrWillBeRawPtr<Event> event) | |
362 { | |
363 m_scheduledEvents.append(event); | |
364 | |
365 if (!m_scheduledEventTimer.isActive()) | |
366 m_scheduledEventTimer.startOneShot(0, FROM_HERE); | |
367 } | |
368 | |
369 void MediaStream::scheduledEventTimerFired(Timer<MediaStream>*) | |
370 { | |
371 if (m_stopped) | |
372 return; | |
373 | |
374 WillBeHeapVector<RefPtrWillBeMember<Event> > events; | |
375 events.swap(m_scheduledEvents); | |
376 | |
377 WillBeHeapVector<RefPtrWillBeMember<Event> >::iterator it = events.begin(); | |
378 for (; it != events.end(); ++it) | |
379 dispatchEvent((*it).release()); | |
380 | |
381 events.clear(); | |
382 } | |
383 | |
384 URLRegistry& MediaStream::registry() const | |
385 { | |
386 return MediaStreamRegistry::registry(); | |
387 } | |
388 | |
389 void MediaStream::trace(Visitor* visitor) | |
390 { | |
391 visitor->trace(m_audioTracks); | |
392 visitor->trace(m_videoTracks); | |
393 visitor->trace(m_scheduledEvents); | |
394 visitor->trace(m_descriptor); | |
395 EventTargetWithInlineData::trace(visitor); | |
396 MediaStreamDescriptorClient::trace(visitor); | |
397 } | |
398 | |
399 } // namespace blink | |
OLD | NEW |