Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / 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  *
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 ANY
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 ANY
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 ON
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, MediaStreamSource* 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& trackVector)
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 adoptRefCountedGarbageCollectedWillBeNoop(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 adoptRefCountedGarbageCollectedWillBeNoop(new MediaStream(context, audioTracks, videoTracks));
79 }
80
81 MediaStream* MediaStream::create(ExecutionContext* context, const MediaStreamTrackVector& 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 adoptRefCountedGarbageCollectedWillBeNoop(new MediaStream(context, audioTracks, videoTracks));
90 }
91
92 MediaStream* MediaStream::create(ExecutionContext* context, PassRefPtr<MediaStreamDescriptor> streamDescriptor)
93 {
94     return adoptRefCountedGarbageCollectedWillBeNoop(new MediaStream(context, streamDescriptor));
95 }
96
97 MediaStream::MediaStream(ExecutionContext* context, PassRefPtr<MediaStreamDescriptor> streamDescriptor)
98     : ContextLifecycleObserver(context)
99     , m_stopped(false)
100     , m_descriptor(streamDescriptor)
101     , m_scheduledEventTimer(this, &MediaStream::scheduledEventTimerFired)
102 {
103     ScriptWrappable::init(this);
104     m_descriptor->setClient(this);
105
106     size_t numberOfAudioTracks = m_descriptor->numberOfAudioComponents();
107     m_audioTracks.reserveCapacity(numberOfAudioTracks);
108     for (size_t i = 0; i < numberOfAudioTracks; i++) {
109         MediaStreamTrack* newTrack = MediaStreamTrack::create(context, m_descriptor->audioComponent(i));
110         newTrack->registerMediaStream(this);
111         m_audioTracks.append(newTrack);
112     }
113
114     size_t numberOfVideoTracks = m_descriptor->numberOfVideoComponents();
115     m_videoTracks.reserveCapacity(numberOfVideoTracks);
116     for (size_t i = 0; i < numberOfVideoTracks; i++) {
117         MediaStreamTrack* newTrack = MediaStreamTrack::create(context, m_descriptor->videoComponent(i));
118         newTrack->registerMediaStream(this);
119         m_videoTracks.append(newTrack);
120     }
121 }
122
123 MediaStream::MediaStream(ExecutionContext* context, const MediaStreamTrackVector& audioTracks, const MediaStreamTrackVector& videoTracks)
124     : ContextLifecycleObserver(context)
125     , m_stopped(false)
126     , m_scheduledEventTimer(this, &MediaStream::scheduledEventTimerFired)
127 {
128     ScriptWrappable::init(this);
129
130     MediaStreamComponentVector audioComponents;
131     MediaStreamComponentVector videoComponents;
132
133     MediaStreamTrackVector::const_iterator iter;
134     for (iter = audioTracks.begin(); iter != audioTracks.end(); ++iter) {
135         (*iter)->registerMediaStream(this);
136         audioComponents.append((*iter)->component());
137     }
138     for (iter = videoTracks.begin(); iter != videoTracks.end(); ++iter) {
139         (*iter)->registerMediaStream(this);
140         videoComponents.append((*iter)->component());
141     }
142
143     m_descriptor = MediaStreamDescriptor::create(audioComponents, videoComponents);
144     m_descriptor->setClient(this);
145     MediaStreamCenter::instance().didCreateMediaStream(m_descriptor.get());
146
147     m_audioTracks = audioTracks;
148     m_videoTracks = videoTracks;
149 }
150
151 MediaStream::~MediaStream()
152 {
153     m_descriptor->setClient(0);
154 }
155
156 bool MediaStream::ended() const
157 {
158     return m_stopped || m_descriptor->ended();
159 }
160
161 MediaStreamTrackVector MediaStream::getTracks()
162 {
163     MediaStreamTrackVector tracks;
164     for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter)
165         tracks.append(iter->get());
166     for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter)
167         tracks.append(iter->get());
168     return tracks;
169 }
170
171 void MediaStream::addTrack(MediaStreamTrack* track, ExceptionState& exceptionState)
172 {
173     if (ended()) {
174         exceptionState.throwDOMException(InvalidStateError, "The MediaStream is finished.");
175         return;
176     }
177
178     if (!track) {
179         exceptionState.throwDOMException(TypeMismatchError, "The MediaStreamTrack provided is invalid.");
180         return;
181     }
182
183     if (getTrackById(track->id()))
184         return;
185
186     switch (track->component()->source()->type()) {
187     case MediaStreamSource::TypeAudio:
188         m_audioTracks.append(track);
189         break;
190     case MediaStreamSource::TypeVideo:
191         m_videoTracks.append(track);
192         break;
193     }
194     track->registerMediaStream(this);
195     m_descriptor->addComponent(track->component());
196     MediaStreamCenter::instance().didAddMediaStreamTrack(m_descriptor.get(), track->component());
197 }
198
199 void MediaStream::removeTrack(MediaStreamTrack* track, ExceptionState& exceptionState)
200 {
201     if (ended()) {
202         exceptionState.throwDOMException(InvalidStateError, "The MediaStream is finished.");
203         return;
204     }
205
206     if (!track) {
207         exceptionState.throwDOMException(TypeMismatchError, "The MediaStreamTrack provided is invalid.");
208         return;
209     }
210
211     size_t pos = kNotFound;
212     switch (track->component()->source()->type()) {
213     case MediaStreamSource::TypeAudio:
214         pos = m_audioTracks.find(track);
215         if (pos != kNotFound)
216             m_audioTracks.remove(pos);
217         break;
218     case MediaStreamSource::TypeVideo:
219         pos = m_videoTracks.find(track);
220         if (pos != kNotFound)
221             m_videoTracks.remove(pos);
222         break;
223     }
224
225     if (pos == kNotFound)
226         return;
227     track->unregisterMediaStream(this);
228     m_descriptor->removeComponent(track->component());
229
230     if (!m_audioTracks.size() && !m_videoTracks.size())
231         m_descriptor->setEnded();
232
233     MediaStreamCenter::instance().didRemoveMediaStreamTrack(m_descriptor.get(), track->component());
234 }
235
236 MediaStreamTrack* MediaStream::getTrackById(String id)
237 {
238     for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter) {
239         if ((*iter)->id() == id)
240             return iter->get();
241     }
242
243     for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter) {
244         if ((*iter)->id() == id)
245             return iter->get();
246     }
247
248     return 0;
249 }
250
251 MediaStream* MediaStream::clone(ExecutionContext* context)
252 {
253     MediaStreamTrackVector tracks;
254     for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter)
255         tracks.append((*iter)->clone(context));
256     for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter)
257         tracks.append((*iter)->clone(context));
258     return MediaStream::create(context, tracks);
259 }
260
261 void MediaStream::stop()
262 {
263     if (ended())
264         return;
265
266     MediaStreamCenter::instance().didStopLocalMediaStream(descriptor());
267
268     streamEnded();
269 }
270
271 void MediaStream::trackEnded()
272 {
273     for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter) {
274         if (!(*iter)->ended())
275             return;
276     }
277
278     for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter) {
279         if (!(*iter)->ended())
280             return;
281     }
282
283     streamEnded();
284 }
285
286 void MediaStream::streamEnded()
287 {
288     if (ended())
289         return;
290
291     m_descriptor->setEnded();
292     scheduleDispatchEvent(Event::create(EventTypeNames::ended));
293 }
294
295 void MediaStream::contextDestroyed()
296 {
297     ContextLifecycleObserver::contextDestroyed();
298     m_stopped = true;
299 }
300
301 const AtomicString& MediaStream::interfaceName() const
302 {
303     return EventTargetNames::MediaStream;
304 }
305
306 ExecutionContext* MediaStream::executionContext() const
307 {
308     return ContextLifecycleObserver::executionContext();
309 }
310
311 void MediaStream::addRemoteTrack(MediaStreamComponent* component)
312 {
313     ASSERT(component);
314     if (ended())
315         return;
316
317     MediaStreamTrack* track = MediaStreamTrack::create(executionContext(), component);
318     switch (component->source()->type()) {
319     case MediaStreamSource::TypeAudio:
320         m_audioTracks.append(track);
321         break;
322     case MediaStreamSource::TypeVideo:
323         m_videoTracks.append(track);
324         break;
325     }
326     track->registerMediaStream(this);
327     m_descriptor->addComponent(component);
328
329     scheduleDispatchEvent(MediaStreamTrackEvent::create(EventTypeNames::addtrack, false, false, track));
330 }
331
332 void MediaStream::removeRemoteTrack(MediaStreamComponent* component)
333 {
334     if (ended())
335         return;
336
337     MediaStreamTrackVector* tracks = 0;
338     switch (component->source()->type()) {
339     case MediaStreamSource::TypeAudio:
340         tracks = &m_audioTracks;
341         break;
342     case MediaStreamSource::TypeVideo:
343         tracks = &m_videoTracks;
344         break;
345     }
346
347     size_t index = kNotFound;
348     for (size_t i = 0; i < tracks->size(); ++i) {
349         if ((*tracks)[i]->component() == component) {
350             index = i;
351             break;
352         }
353     }
354     if (index == kNotFound)
355         return;
356
357     m_descriptor->removeComponent(component);
358
359     MediaStreamTrack* track = (*tracks)[index];
360     track->unregisterMediaStream(this);
361     tracks->remove(index);
362     scheduleDispatchEvent(MediaStreamTrackEvent::create(EventTypeNames::removetrack, false, false, track));
363 }
364
365 void MediaStream::scheduleDispatchEvent(PassRefPtrWillBeRawPtr<Event> event)
366 {
367     m_scheduledEvents.append(event);
368
369     if (!m_scheduledEventTimer.isActive())
370         m_scheduledEventTimer.startOneShot(0, FROM_HERE);
371 }
372
373 void MediaStream::scheduledEventTimerFired(Timer<MediaStream>*)
374 {
375     if (m_stopped)
376         return;
377
378     WillBeHeapVector<RefPtrWillBeMember<Event> > events;
379     events.swap(m_scheduledEvents);
380
381     WillBeHeapVector<RefPtrWillBeMember<Event> >::iterator it = events.begin();
382     for (; it != events.end(); ++it)
383         dispatchEvent((*it).release());
384
385     events.clear();
386 }
387
388 URLRegistry& MediaStream::registry() const
389 {
390     return MediaStreamRegistry::registry();
391 }
392
393 void MediaStream::trace(Visitor* visitor)
394 {
395     visitor->trace(m_audioTracks);
396     visitor->trace(m_videoTracks);
397     visitor->trace(m_scheduledEvents);
398     EventTargetWithInlineData::trace(visitor);
399 }
400
401 } // namespace blink