This source file includes following definitions.
- containsSource
- processTrack
- create
- create
- create
- create
- m_scheduledEventTimer
- m_scheduledEventTimer
- ended
- addTrack
- removeTrack
- getTrackById
- clone
- stop
- trackEnded
- streamEnded
- contextDestroyed
- interfaceName
- executionContext
- addRemoteTrack
- removeRemoteTrack
- scheduleDispatchEvent
- scheduledEventTimerFired
- registry
#include "config.h"
#include "modules/mediastream/MediaStream.h"
#include "bindings/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 {
static bool containsSource(MediaStreamTrackVector& trackVector, MediaStreamSource* source)
{
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, MediaStreamTrackVector& trackVector)
{
if (track->ended())
return;
MediaStreamSource* source = track->component()->source();
if (!containsSource(trackVector, source))
trackVector.append(track);
}
PassRefPtr<MediaStream> MediaStream::create(ExecutionContext* context)
{
MediaStreamTrackVector audioTracks;
MediaStreamTrackVector videoTracks;
return adoptRef(new MediaStream(context, audioTracks, videoTracks));
}
PassRefPtr<MediaStream> MediaStream::create(ExecutionContext* context, PassRefPtr<MediaStream> stream)
{
ASSERT(stream);
MediaStreamTrackVector audioTracks;
MediaStreamTrackVector videoTracks;
for (size_t i = 0; i < stream->m_audioTracks.size(); ++i)
processTrack(stream->m_audioTracks[i].get(), audioTracks);
for (size_t i = 0; i < stream->m_videoTracks.size(); ++i)
processTrack(stream->m_videoTracks[i].get(), videoTracks);
return adoptRef(new MediaStream(context, audioTracks, videoTracks));
}
PassRefPtr<MediaStream> MediaStream::create(ExecutionContext* context, const MediaStreamTrackVector& tracks)
{
MediaStreamTrackVector audioTracks;
MediaStreamTrackVector videoTracks;
for (size_t i = 0; i < tracks.size(); ++i)
processTrack(tracks[i].get(), tracks[i]->kind() == "audio" ? audioTracks : videoTracks);
return adoptRef(new MediaStream(context, audioTracks, videoTracks));
}
PassRefPtr<MediaStream> MediaStream::create(ExecutionContext* context, PassRefPtr<MediaStreamDescriptor> streamDescriptor)
{
return adoptRef(new MediaStream(context, streamDescriptor));
}
MediaStream::MediaStream(ExecutionContext* context, PassRefPtr<MediaStreamDescriptor> streamDescriptor)
: ContextLifecycleObserver(context)
, m_stopped(false)
, 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++) {
RefPtr<MediaStreamTrack> newTrack = MediaStreamTrack::create(context, m_descriptor->audioComponent(i));
newTrack->addObserver(this);
m_audioTracks.append(newTrack.release());
}
size_t numberOfVideoTracks = m_descriptor->numberOfVideoComponents();
m_videoTracks.reserveCapacity(numberOfVideoTracks);
for (size_t i = 0; i < numberOfVideoTracks; i++) {
RefPtr<MediaStreamTrack> newTrack = MediaStreamTrack::create(context, m_descriptor->videoComponent(i));
newTrack->addObserver(this);
m_videoTracks.append(newTrack.release());
}
}
MediaStream::MediaStream(ExecutionContext* context, const MediaStreamTrackVector& audioTracks, const MediaStreamTrackVector& videoTracks)
: ContextLifecycleObserver(context)
, m_stopped(false)
, m_scheduledEventTimer(this, &MediaStream::scheduledEventTimerFired)
{
ScriptWrappable::init(this);
MediaStreamComponentVector audioComponents;
MediaStreamComponentVector videoComponents;
MediaStreamTrackVector::const_iterator iter;
for (iter = audioTracks.begin(); iter != audioTracks.end(); ++iter) {
(*iter)->addObserver(this);
audioComponents.append((*iter)->component());
}
for (iter = videoTracks.begin(); iter != videoTracks.end(); ++iter) {
(*iter)->addObserver(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()
{
for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter)
(*iter)->removeObserver(this);
for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter)
(*iter)->removeObserver(this);
m_descriptor->setClient(0);
}
bool MediaStream::ended() const
{
return m_stopped || m_descriptor->ended();
}
void MediaStream::addTrack(PassRefPtr<MediaStreamTrack> prpTrack, ExceptionState& exceptionState)
{
if (ended()) {
exceptionState.throwDOMException(InvalidStateError, "The MediaStream is finished.");
return;
}
if (!prpTrack) {
exceptionState.throwDOMException(TypeMismatchError, "The MediaStreamTrack provided is invalid.");
return;
}
RefPtr<MediaStreamTrack> track = prpTrack;
if (getTrackById(track->id()))
return;
switch (track->component()->source()->type()) {
case MediaStreamSource::TypeAudio:
m_audioTracks.append(track);
break;
case MediaStreamSource::TypeVideo:
m_videoTracks.append(track);
break;
}
track->addObserver(this);
m_descriptor->addComponent(track->component());
MediaStreamCenter::instance().didAddMediaStreamTrack(m_descriptor.get(), track->component());
}
void MediaStream::removeTrack(PassRefPtr<MediaStreamTrack> prpTrack, ExceptionState& exceptionState)
{
if (ended()) {
exceptionState.throwDOMException(InvalidStateError, "The MediaStream is finished.");
return;
}
if (!prpTrack) {
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:
pos = m_audioTracks.find(track);
if (pos != kNotFound)
m_audioTracks.remove(pos);
break;
case MediaStreamSource::TypeVideo:
pos = m_videoTracks.find(track);
if (pos != kNotFound)
m_videoTracks.remove(pos);
break;
}
if (pos == kNotFound)
return;
track->removeObserver(this);
m_descriptor->removeComponent(track->component());
if (!m_audioTracks.size() && !m_videoTracks.size())
m_descriptor->setEnded();
MediaStreamCenter::instance().didRemoveMediaStreamTrack(m_descriptor.get(), track->component());
}
MediaStreamTrack* MediaStream::getTrackById(String id)
{
for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter) {
if ((*iter)->id() == id)
return (*iter).get();
}
for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter) {
if ((*iter)->id() == id)
return (*iter).get();
}
return 0;
}
PassRefPtr<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));
RefPtr<MediaStream> clonedStream = MediaStream::create(context, tracks);
return clonedStream.release();
}
void MediaStream::stop()
{
if (ended())
return;
MediaStreamCenter::instance().didStopLocalMediaStream(descriptor());
streamEnded();
}
void MediaStream::trackEnded()
{
for (MediaStreamTrackVector::iterator iter = m_audioTracks.begin(); iter != m_audioTracks.end(); ++iter) {
if (!(*iter)->ended())
return;
}
for (MediaStreamTrackVector::iterator iter = m_videoTracks.begin(); iter != m_videoTracks.end(); ++iter) {
if (!(*iter)->ended())
return;
}
streamEnded();
}
void MediaStream::streamEnded()
{
if (ended())
return;
m_descriptor->setEnded();
scheduleDispatchEvent(Event::create(EventTypeNames::ended));
}
void MediaStream::contextDestroyed()
{
ContextLifecycleObserver::contextDestroyed();
m_stopped = true;
}
const AtomicString& MediaStream::interfaceName() const
{
return EventTargetNames::MediaStream;
}
ExecutionContext* MediaStream::executionContext() const
{
return ContextLifecycleObserver::executionContext();
}
void MediaStream::addRemoteTrack(MediaStreamComponent* component)
{
ASSERT(component);
if (ended())
return;
RefPtr<MediaStreamTrack> track = MediaStreamTrack::create(executionContext(), component);
switch (component->source()->type()) {
case MediaStreamSource::TypeAudio:
m_audioTracks.append(track);
break;
case MediaStreamSource::TypeVideo:
m_videoTracks.append(track);
break;
}
track->addObserver(this);
m_descriptor->addComponent(component);
scheduleDispatchEvent(MediaStreamTrackEvent::create(EventTypeNames::addtrack, false, false, track));
}
void MediaStream::removeRemoteTrack(MediaStreamComponent* component)
{
if (ended())
return;
MediaStreamTrackVector* tracks = 0;
switch (component->source()->type()) {
case MediaStreamSource::TypeAudio:
tracks = &m_audioTracks;
break;
case MediaStreamSource::TypeVideo:
tracks = &m_videoTracks;
break;
}
size_t index = kNotFound;
for (size_t i = 0; i < tracks->size(); ++i) {
if ((*tracks)[i]->component() == component) {
index = i;
break;
}
}
if (index == kNotFound)
return;
m_descriptor->removeComponent(component);
RefPtr<MediaStreamTrack> track = (*tracks)[index];
track->removeObserver(this);
tracks->remove(index);
scheduleDispatchEvent(MediaStreamTrackEvent::create(EventTypeNames::removetrack, false, false, track));
}
void MediaStream::scheduleDispatchEvent(PassRefPtrWillBeRawPtr<Event> event)
{
m_scheduledEvents.append(event);
if (!m_scheduledEventTimer.isActive())
m_scheduledEventTimer.startOneShot(0, FROM_HERE);
}
void MediaStream::scheduledEventTimerFired(Timer<MediaStream>*)
{
if (m_stopped)
return;
WillBeHeapVector<RefPtrWillBeMember<Event> > events;
events.swap(m_scheduledEvents);
WillBeHeapVector<RefPtrWillBeMember<Event> >::iterator it = events.begin();
for (; it != events.end(); ++it)
dispatchEvent((*it).release());
events.clear();
}
URLRegistry& MediaStream::registry() const
{
return MediaStreamRegistry::registry();
}
}