#include "config.h"
#include "modules/mediastream/MediaStream.h"
-#include "bindings/v8/ExceptionState.h"
+#include "bindings/core/v8/ExceptionState.h"
#include "core/dom/ExceptionCode.h"
-#include "core/events/Event.h"
#include "modules/mediastream/MediaStreamRegistry.h"
#include "modules/mediastream/MediaStreamTrackEvent.h"
#include "platform/mediastream/MediaStreamCenter.h"
#include "platform/mediastream/MediaStreamSource.h"
-namespace WebCore {
+namespace blink {
-static bool containsSource(MediaStreamSourceVector& sourceVector, MediaStreamSource* source)
+static bool containsSource(MediaStreamTrackVector& trackVector, MediaStreamSource* source)
{
- for (size_t i = 0; i < sourceVector.size(); ++i) {
- if (source->id() == sourceVector[i]->id())
+ for (size_t i = 0; i < trackVector.size(); ++i) {
+ if (source->id() == trackVector[i]->component()->source()->id())
return true;
}
return false;
}
-static void processTrack(MediaStreamTrack* track, MediaStreamSourceVector& sourceVector)
+static void processTrack(MediaStreamTrack* track, MediaStreamTrackVector& trackVector)
{
if (track->ended())
return;
MediaStreamSource* source = track->component()->source();
- if (!containsSource(sourceVector, source))
- sourceVector.append(source);
+ if (!containsSource(trackVector, source))
+ trackVector.append(track);
}
-static PassRefPtr<MediaStream> createFromSourceVectors(ExecutionContext* context, const MediaStreamSourceVector& audioSources, const MediaStreamSourceVector& videoSources)
+MediaStream* MediaStream::create(ExecutionContext* context)
{
- RefPtr<MediaStreamDescriptor> descriptor = MediaStreamDescriptor::create(audioSources, videoSources);
- MediaStreamCenter::instance().didCreateMediaStream(descriptor.get());
+ MediaStreamTrackVector audioTracks;
+ MediaStreamTrackVector videoTracks;
- return MediaStream::create(context, descriptor.release());
+ return new MediaStream(context, audioTracks, videoTracks);
}
-PassRefPtr<MediaStream> MediaStream::create(ExecutionContext* context)
-{
- MediaStreamSourceVector audioSources;
- MediaStreamSourceVector videoSources;
-
- return createFromSourceVectors(context, audioSources, videoSources);
-}
-
-PassRefPtr<MediaStream> MediaStream::create(ExecutionContext* context, PassRefPtr<MediaStream> stream)
+MediaStream* MediaStream::create(ExecutionContext* context, MediaStream* stream)
{
ASSERT(stream);
- MediaStreamSourceVector audioSources;
- MediaStreamSourceVector videoSources;
+ MediaStreamTrackVector audioTracks;
+ MediaStreamTrackVector videoTracks;
for (size_t i = 0; i < stream->m_audioTracks.size(); ++i)
- processTrack(stream->m_audioTracks[i].get(), audioSources);
+ processTrack(stream->m_audioTracks[i].get(), audioTracks);
for (size_t i = 0; i < stream->m_videoTracks.size(); ++i)
- processTrack(stream->m_videoTracks[i].get(), videoSources);
+ processTrack(stream->m_videoTracks[i].get(), videoTracks);
- return createFromSourceVectors(context, audioSources, videoSources);
+ return new MediaStream(context, audioTracks, videoTracks);
}
-PassRefPtr<MediaStream> MediaStream::create(ExecutionContext* context, const MediaStreamTrackVector& tracks)
+MediaStream* MediaStream::create(ExecutionContext* context, const MediaStreamTrackVector& tracks)
{
- MediaStreamSourceVector audioSources;
- MediaStreamSourceVector videoSources;
+ MediaStreamTrackVector audioTracks;
+ MediaStreamTrackVector videoTracks;
for (size_t i = 0; i < tracks.size(); ++i)
- processTrack(tracks[i].get(), tracks[i]->kind() == "audio" ? audioSources : videoSources);
+ processTrack(tracks[i].get(), tracks[i]->kind() == "audio" ? audioTracks : videoTracks);
- return createFromSourceVectors(context, audioSources, videoSources);
+ return new MediaStream(context, audioTracks, videoTracks);
}
-PassRefPtr<MediaStream> MediaStream::create(ExecutionContext* context, PassRefPtr<MediaStreamDescriptor> streamDescriptor)
+MediaStream* MediaStream::create(ExecutionContext* context, PassRefPtr<MediaStreamDescriptor> streamDescriptor)
{
- return adoptRef(new MediaStream(context, streamDescriptor));
+ return new MediaStream(context, streamDescriptor);
}
MediaStream::MediaStream(ExecutionContext* context, PassRefPtr<MediaStreamDescriptor> streamDescriptor)
, m_descriptor(streamDescriptor)
, m_scheduledEventTimer(this, &MediaStream::scheduledEventTimerFired)
{
- ScriptWrappable::init(this);
m_descriptor->setClient(this);
size_t numberOfAudioTracks = m_descriptor->numberOfAudioComponents();
m_audioTracks.reserveCapacity(numberOfAudioTracks);
- for (size_t i = 0; i < numberOfAudioTracks; i++)
- m_audioTracks.append(MediaStreamTrack::create(context, m_descriptor->audioComponent(i)));
+ for (size_t i = 0; i < numberOfAudioTracks; i++) {
+ MediaStreamTrack* newTrack = MediaStreamTrack::create(context, m_descriptor->audioComponent(i));
+ newTrack->registerMediaStream(this);
+ m_audioTracks.append(newTrack);
+ }
size_t numberOfVideoTracks = m_descriptor->numberOfVideoComponents();
m_videoTracks.reserveCapacity(numberOfVideoTracks);
- for (size_t i = 0; i < numberOfVideoTracks; i++)
- m_videoTracks.append(MediaStreamTrack::create(context, m_descriptor->videoComponent(i)));
+ for (size_t i = 0; i < numberOfVideoTracks; i++) {
+ MediaStreamTrack* newTrack = MediaStreamTrack::create(context, m_descriptor->videoComponent(i));
+ newTrack->registerMediaStream(this);
+ m_videoTracks.append(newTrack);
+ }
+}
+
+MediaStream::MediaStream(ExecutionContext* context, const MediaStreamTrackVector& audioTracks, const MediaStreamTrackVector& videoTracks)
+ : ContextLifecycleObserver(context)
+ , m_stopped(false)
+ , m_scheduledEventTimer(this, &MediaStream::scheduledEventTimerFired)
+{
+ MediaStreamComponentVector audioComponents;
+ MediaStreamComponentVector videoComponents;
+
+ MediaStreamTrackVector::const_iterator iter;
+ for (iter = audioTracks.begin(); iter != audioTracks.end(); ++iter) {
+ (*iter)->registerMediaStream(this);
+ audioComponents.append((*iter)->component());
+ }
+ for (iter = videoTracks.begin(); iter != videoTracks.end(); ++iter) {
+ (*iter)->registerMediaStream(this);
+ videoComponents.append((*iter)->component());
+ }
+
+ m_descriptor = MediaStreamDescriptor::create(audioComponents, videoComponents);
+ m_descriptor->setClient(this);
+ MediaStreamCenter::instance().didCreateMediaStream(m_descriptor.get());
+
+ m_audioTracks = audioTracks;
+ m_videoTracks = videoTracks;
}
MediaStream::~MediaStream()
return m_stopped || m_descriptor->ended();
}
-void MediaStream::addTrack(PassRefPtr<MediaStreamTrack> prpTrack, ExceptionState& exceptionState)
+MediaStreamTrackVector MediaStream::getTracks()
+{
+ MediaStreamTrackVector tracks;
+ for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter)
+ tracks.append(iter->get());
+ for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter)
+ tracks.append(iter->get());
+ return tracks;
+}
+
+void MediaStream::addTrack(MediaStreamTrack* track, ExceptionState& exceptionState)
{
if (ended()) {
- exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
+ exceptionState.throwDOMException(InvalidStateError, "The MediaStream is finished.");
return;
}
- if (!prpTrack) {
- exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError);
+ if (!track) {
+ exceptionState.throwDOMException(TypeMismatchError, "The MediaStreamTrack provided is invalid.");
return;
}
- RefPtr<MediaStreamTrack> track = prpTrack;
-
if (getTrackById(track->id()))
return;
- RefPtr<MediaStreamComponent> component = MediaStreamComponent::create(m_descriptor.get(), track->component()->source());
- RefPtr<MediaStreamTrack> newTrack = MediaStreamTrack::create(executionContext(), component.get());
-
- switch (component->source()->type()) {
+ switch (track->component()->source()->type()) {
case MediaStreamSource::TypeAudio:
- m_audioTracks.append(newTrack);
+ m_audioTracks.append(track);
break;
case MediaStreamSource::TypeVideo:
- m_videoTracks.append(newTrack);
+ m_videoTracks.append(track);
break;
}
-
- m_descriptor->addComponent(component.release());
-
- MediaStreamCenter::instance().didAddMediaStreamTrack(m_descriptor.get(), newTrack->component());
+ track->registerMediaStream(this);
+ m_descriptor->addComponent(track->component());
+ MediaStreamCenter::instance().didAddMediaStreamTrack(m_descriptor.get(), track->component());
}
-void MediaStream::removeTrack(PassRefPtr<MediaStreamTrack> prpTrack, ExceptionState& exceptionState)
+void MediaStream::removeTrack(MediaStreamTrack* track, ExceptionState& exceptionState)
{
if (ended()) {
- exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError);
+ exceptionState.throwDOMException(InvalidStateError, "The MediaStream is finished.");
return;
}
- if (!prpTrack) {
- exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError);
+ if (!track) {
+ exceptionState.throwDOMException(TypeMismatchError, "The MediaStreamTrack provided is invalid.");
return;
}
- RefPtr<MediaStreamTrack> track = prpTrack;
-
size_t pos = kNotFound;
switch (track->component()->source()->type()) {
case MediaStreamSource::TypeAudio:
if (pos == kNotFound)
return;
-
+ track->unregisterMediaStream(this);
m_descriptor->removeComponent(track->component());
if (!m_audioTracks.size() && !m_videoTracks.size())
{
for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter) {
if ((*iter)->id() == id)
- return (*iter).get();
+ return iter->get();
}
for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter) {
if ((*iter)->id() == id)
- return (*iter).get();
+ return iter->get();
}
return 0;
}
+MediaStream* MediaStream::clone(ExecutionContext* context)
+{
+ MediaStreamTrackVector tracks;
+ for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter)
+ tracks.append((*iter)->clone(context));
+ for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter)
+ tracks.append((*iter)->clone(context));
+ return MediaStream::create(context, tracks);
+}
+
void MediaStream::stop()
{
if (ended())
void MediaStream::trackEnded()
{
- for (size_t i = 0; i < m_audioTracks.size(); ++i)
- if (!m_audioTracks[i]->ended())
+ for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter) {
+ if (!(*iter)->ended())
return;
+ }
- for (size_t i = 0; i < m_videoTracks.size(); ++i)
- if (!m_videoTracks[i]->ended())
+ for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter) {
+ if (!(*iter)->ended())
return;
+ }
streamEnded();
}
void MediaStream::addRemoteTrack(MediaStreamComponent* component)
{
- ASSERT(component && !component->stream());
+ ASSERT(component);
if (ended())
return;
- component->setStream(descriptor());
-
- RefPtr<MediaStreamTrack> track = MediaStreamTrack::create(executionContext(), component);
+ MediaStreamTrack* track = MediaStreamTrack::create(executionContext(), component);
switch (component->source()->type()) {
case MediaStreamSource::TypeAudio:
m_audioTracks.append(track);
m_videoTracks.append(track);
break;
}
+ track->registerMediaStream(this);
m_descriptor->addComponent(component);
scheduleDispatchEvent(MediaStreamTrackEvent::create(EventTypeNames::addtrack, false, false, track));
void MediaStream::removeRemoteTrack(MediaStreamComponent* component)
{
- if (ended())
+ if (m_stopped)
return;
MediaStreamTrackVector* tracks = 0;
m_descriptor->removeComponent(component);
- RefPtr<MediaStreamTrack> track = (*tracks)[index];
+ MediaStreamTrack* track = (*tracks)[index];
+ track->unregisterMediaStream(this);
tracks->remove(index);
scheduleDispatchEvent(MediaStreamTrackEvent::create(EventTypeNames::removetrack, false, false, track));
}
-void MediaStream::scheduleDispatchEvent(PassRefPtr<Event> event)
+void MediaStream::scheduleDispatchEvent(PassRefPtrWillBeRawPtr<Event> event)
{
m_scheduledEvents.append(event);
if (!m_scheduledEventTimer.isActive())
- m_scheduledEventTimer.startOneShot(0);
+ m_scheduledEventTimer.startOneShot(0, FROM_HERE);
}
void MediaStream::scheduledEventTimerFired(Timer<MediaStream>*)
if (m_stopped)
return;
- Vector<RefPtr<Event> > events;
+ WillBeHeapVector<RefPtrWillBeMember<Event> > events;
events.swap(m_scheduledEvents);
- Vector<RefPtr<Event> >::iterator it = events.begin();
+ WillBeHeapVector<RefPtrWillBeMember<Event> >::iterator it = events.begin();
for (; it != events.end(); ++it)
dispatchEvent((*it).release());
return MediaStreamRegistry::registry();
}
-} // namespace WebCore
+void MediaStream::trace(Visitor* visitor)
+{
+ visitor->trace(m_audioTracks);
+ visitor->trace(m_videoTracks);
+ visitor->trace(m_scheduledEvents);
+ EventTargetWithInlineData::trace(visitor);
+}
+
+} // namespace blink