summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp')
-rw-r--r--Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp339
1 files changed, 229 insertions, 110 deletions
diff --git a/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp b/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp
index e7140ad23..21c0769a6 100644
--- a/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp
+++ b/Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp
@@ -1,7 +1,8 @@
/*
- * Copyright (C) 2011 Ericsson AB. All rights reserved.
+ * Copyright (C) 2011, 2015 Ericsson AB. All rights reserved.
* Copyright (C) 2013 Google Inc. All rights reserved.
* Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -31,174 +32,292 @@
*/
#include "config.h"
+#include "MediaStreamPrivate.h"
#if ENABLE(MEDIA_STREAM)
-#include "MediaStreamPrivate.h"
-
-#include "MediaStreamCenter.h"
+#include "GraphicsContext.h"
+#include "IntRect.h"
#include "UUID.h"
+#include <wtf/MainThread.h>
#include <wtf/RefCounted.h>
#include <wtf/Vector.h>
namespace WebCore {
-PassRefPtr<MediaStreamPrivate> MediaStreamPrivate::create(const Vector<RefPtr<MediaStreamSource>>& audioSources, const Vector<RefPtr<MediaStreamSource>>& videoSources)
+Ref<MediaStreamPrivate> MediaStreamPrivate::create(const Vector<Ref<RealtimeMediaSource>>& audioSources, const Vector<Ref<RealtimeMediaSource>>& videoSources)
{
- return adoptRef(new MediaStreamPrivate(createCanonicalUUIDString(), audioSources, videoSources));
+ MediaStreamTrackPrivateVector tracks;
+ tracks.reserveInitialCapacity(audioSources.size() + videoSources.size());
+
+ for (auto& source : audioSources)
+ tracks.uncheckedAppend(MediaStreamTrackPrivate::create(source.copyRef()));
+
+ for (auto& source : videoSources)
+ tracks.uncheckedAppend(MediaStreamTrackPrivate::create(source.copyRef()));
+
+ return MediaStreamPrivate::create(tracks);
}
-PassRefPtr<MediaStreamPrivate> MediaStreamPrivate::create(const Vector<RefPtr<MediaStreamTrackPrivate>>& audioPrivateTracks, const Vector<RefPtr<MediaStreamTrackPrivate>>& videoPrivateTracks)
+Ref<MediaStreamPrivate> MediaStreamPrivate::create(const MediaStreamTrackPrivateVector& tracks)
{
- return adoptRef(new MediaStreamPrivate(createCanonicalUUIDString(), audioPrivateTracks, videoPrivateTracks));
+ return adoptRef(*new MediaStreamPrivate(createCanonicalUUIDString(), tracks));
}
-void MediaStreamPrivate::addSource(PassRefPtr<MediaStreamSource> prpSource)
+MediaStreamPrivate::MediaStreamPrivate(const String& id, const MediaStreamTrackPrivateVector& tracks)
+ : m_weakPtrFactory(this)
+ , m_id(id)
{
- RefPtr<MediaStreamSource> source = prpSource;
- switch (source->type()) {
- case MediaStreamSource::Audio:
- if (m_audioStreamSources.find(source) == notFound)
- m_audioStreamSources.append(source);
- break;
- case MediaStreamSource::Video:
- if (m_videoStreamSources.find(source) == notFound)
- m_videoStreamSources.append(source);
- break;
- case MediaStreamSource::None:
- ASSERT_NOT_REACHED();
- break;
+ ASSERT(!m_id.isEmpty());
+
+ for (auto& track : tracks) {
+ track->addObserver(*this);
+ m_trackSet.add(track->id(), track);
}
+
+ updateActiveState(NotifyClientOption::DontNotify);
}
-void MediaStreamPrivate::removeSource(PassRefPtr<MediaStreamSource> source)
+MediaStreamPrivate::~MediaStreamPrivate()
{
- size_t pos = notFound;
- switch (source->type()) {
- case MediaStreamSource::Audio:
- pos = m_audioStreamSources.find(source);
- if (pos == notFound)
- return;
- m_audioStreamSources.remove(pos);
- break;
- case MediaStreamSource::Video:
- pos = m_videoStreamSources.find(source);
- if (pos == notFound)
- return;
- m_videoStreamSources.remove(pos);
- break;
- case MediaStreamSource::None:
- ASSERT_NOT_REACHED();
- break;
+ for (auto& track : m_trackSet.values())
+ track->removeObserver(*this);
+}
+
+void MediaStreamPrivate::addObserver(MediaStreamPrivate::Observer& observer)
+{
+ m_observers.append(&observer);
+}
+
+void MediaStreamPrivate::removeObserver(MediaStreamPrivate::Observer& observer)
+{
+ size_t pos = m_observers.find(&observer);
+ if (pos != notFound)
+ m_observers.remove(pos);
+}
+
+MediaStreamTrackPrivateVector MediaStreamPrivate::tracks() const
+{
+ MediaStreamTrackPrivateVector tracks;
+ tracks.reserveCapacity(m_trackSet.size());
+ copyValuesToVector(m_trackSet, tracks);
+
+ return tracks;
+}
+
+void MediaStreamPrivate::updateActiveState(NotifyClientOption notifyClientOption)
+{
+ bool newActiveState = false;
+ for (auto& track : m_trackSet.values()) {
+ if (!track->ended()) {
+ newActiveState = true;
+ break;
+ }
+ }
+
+ updateActiveVideoTrack();
+
+ // A stream is active if it has at least one un-ended track.
+ if (newActiveState == m_isActive)
+ return;
+
+ m_isActive = newActiveState;
+
+ if (notifyClientOption == NotifyClientOption::Notify) {
+ for (auto& observer : m_observers)
+ observer->activeStatusChanged();
}
}
-void MediaStreamPrivate::addRemoteSource(MediaStreamSource* source)
+void MediaStreamPrivate::addTrack(RefPtr<MediaStreamTrackPrivate>&& track, NotifyClientOption notifyClientOption)
{
- if (m_client)
- m_client->addRemoteSource(source);
- else
- addSource(source);
+ if (m_trackSet.contains(track->id()))
+ return;
+
+ track->addObserver(*this);
+ m_trackSet.add(track->id(), track);
+
+ if (notifyClientOption == NotifyClientOption::Notify) {
+ for (auto& observer : m_observers)
+ observer->didAddTrack(*track.get());
+ }
+
+ updateActiveState(notifyClientOption);
}
-void MediaStreamPrivate::removeRemoteSource(MediaStreamSource* source)
+void MediaStreamPrivate::removeTrack(MediaStreamTrackPrivate& track, NotifyClientOption notifyClientOption)
{
- if (m_client)
- m_client->removeRemoteSource(source);
- else
- removeSource(source);
+ if (!m_trackSet.remove(track.id()))
+ return;
+
+ track.removeObserver(*this);
+
+ if (notifyClientOption == NotifyClientOption::Notify) {
+ for (auto& observer : m_observers)
+ observer->didRemoveTrack(track);
+ }
+
+ updateActiveState(NotifyClientOption::Notify);
}
-void MediaStreamPrivate::addRemoteTrack(MediaStreamTrackPrivate* track)
+void MediaStreamPrivate::startProducingData()
{
- if (m_client)
- m_client->addRemoteTrack(track);
- else
- addTrack(track);
+ for (auto& track : m_trackSet.values())
+ track->startProducingData();
}
-void MediaStreamPrivate::removeRemoteTrack(MediaStreamTrackPrivate* track)
+void MediaStreamPrivate::stopProducingData()
{
- if (m_client)
- m_client->removeRemoteTrack(track);
- else
- removeTrack(track);
+ for (auto& track : m_trackSet.values())
+ track->stopProducingData();
}
-MediaStreamPrivate::MediaStreamPrivate(const String& id, const Vector<RefPtr<MediaStreamSource>>& audioSources, const Vector<RefPtr<MediaStreamSource>>& videoSources)
- : m_client(0)
- , m_id(id)
- , m_ended(false)
+bool MediaStreamPrivate::isProducingData() const
{
- ASSERT(m_id.length());
- for (size_t i = 0; i < audioSources.size(); i++)
- addTrack(MediaStreamTrackPrivate::create(audioSources[i]));
+ for (auto& track : m_trackSet.values()) {
+ if (track->isProducingData())
+ return true;
+ }
+ return false;
+}
- for (size_t i = 0; i < videoSources.size(); i++)
- addTrack(MediaStreamTrackPrivate::create(videoSources[i]));
+bool MediaStreamPrivate::hasVideo() const
+{
+ for (auto& track : m_trackSet.values()) {
+ if (track->type() == RealtimeMediaSource::Type::Video && track->enabled() && !track->ended())
+ return true;
+ }
+ return false;
+}
- unsigned providedSourcesSize = audioSources.size() + videoSources.size();
- unsigned tracksSize = m_audioPrivateTracks.size() + m_videoPrivateTracks.size();
- // If sources were provided and no track was added to the MediaStreamPrivate's tracks, this means
- // that the tracks were all ended
- if (providedSourcesSize > 0 && !tracksSize)
- m_ended = true;
+bool MediaStreamPrivate::hasAudio() const
+{
+ for (auto& track : m_trackSet.values()) {
+ if (track->type() == RealtimeMediaSource::Type::Audio && track->enabled() && !track->ended())
+ return true;
+ }
+ return false;
}
-MediaStreamPrivate::MediaStreamPrivate(const String& id, const Vector<RefPtr<MediaStreamTrackPrivate>>& audioPrivateTracks, const Vector<RefPtr<MediaStreamTrackPrivate>>& videoPrivateTracks)
- : m_client(0)
- , m_id(id)
- , m_ended(false)
+bool MediaStreamPrivate::hasLocalVideoSource() const
{
- ASSERT(m_id.length());
- for (size_t i = 0; i < audioPrivateTracks.size(); i++)
- addTrack(audioPrivateTracks[i]);
+ for (auto& track : m_trackSet.values()) {
+ if (track->type() == RealtimeMediaSource::Type::Video && !track->remote())
+ return true;
+ }
+ return false;
+}
- for (size_t i = 0; i < videoPrivateTracks.size(); i++)
- addTrack(videoPrivateTracks[i]);
+bool MediaStreamPrivate::hasLocalAudioSource() const
+{
+ for (auto& track : m_trackSet.values()) {
+ if (track->type() == RealtimeMediaSource::Type::Audio && !track->remote())
+ return true;
+ }
+ return false;
+}
- unsigned providedTracksSize = audioPrivateTracks.size() + videoPrivateTracks.size();
- unsigned tracksSize = m_audioPrivateTracks.size() + m_videoPrivateTracks.size();
- // If tracks were provided and no one was added to the MediaStreamPrivate's tracks, this means
- // that the tracks were all ended
- if (providedTracksSize > 0 && !tracksSize)
- m_ended = true;
+bool MediaStreamPrivate::muted() const
+{
+ for (auto& track : m_trackSet.values()) {
+ if (!track->muted())
+ return false;
+ }
+ return true;
}
-void MediaStreamPrivate::setEnded()
+FloatSize MediaStreamPrivate::intrinsicSize() const
{
- if (m_client)
- m_client->streamDidEnd();
+ FloatSize size;
+
+ if (m_activeVideoTrack) {
+ const RealtimeMediaSourceSettings& setting = m_activeVideoTrack->settings();
+ size.setWidth(setting.width());
+ size.setHeight(setting.height());
+ }
- m_ended = true;
+ return size;
}
-void MediaStreamPrivate::addTrack(PassRefPtr<MediaStreamTrackPrivate> prpTrack)
+void MediaStreamPrivate::paintCurrentFrameInContext(GraphicsContext& context, const FloatRect& rect)
{
- RefPtr<MediaStreamTrackPrivate> track = prpTrack;
- if (track->ended())
+ if (context.paintingDisabled())
return;
- Vector<RefPtr<MediaStreamTrackPrivate>>& tracks = track->type() == MediaStreamSource::Audio ? m_audioPrivateTracks : m_videoPrivateTracks;
+ if (active() && m_activeVideoTrack)
+ m_activeVideoTrack->paintCurrentFrameInContext(context, rect);
+ else {
+ GraphicsContextStateSaver stateSaver(context);
+ context.translate(rect.x(), rect.y() + rect.height());
+ context.scale(FloatSize(1, -1));
+ IntRect paintRect(IntPoint(0, 0), IntSize(rect.width(), rect.height()));
+ context.fillRect(paintRect, Color::black);
+ }
+}
- size_t pos = tracks.find(track);
- if (pos != notFound)
- return;
+RefPtr<Image> MediaStreamPrivate::currentFrameImage()
+{
+ if (!active() || !m_activeVideoTrack)
+ return nullptr;
- tracks.append(track);
- if (track->source())
- addSource(track->source());
+ return m_activeVideoTrack->source().currentFrameImage();
}
-void MediaStreamPrivate::removeTrack(PassRefPtr<MediaStreamTrackPrivate> track)
+void MediaStreamPrivate::updateActiveVideoTrack()
{
- Vector<RefPtr<MediaStreamTrackPrivate>>& tracks = track->type() == MediaStreamSource::Audio ? m_audioPrivateTracks : m_videoPrivateTracks;
+ m_activeVideoTrack = nullptr;
+ for (auto& track : m_trackSet.values()) {
+ if (!track->ended() && track->type() == RealtimeMediaSource::Type::Video) {
+ m_activeVideoTrack = track.get();
+ break;
+ }
+ }
+}
- size_t pos = tracks.find(track);
- if (pos == notFound)
- return;
+void MediaStreamPrivate::characteristicsChanged()
+{
+ for (auto& observer : m_observers)
+ observer->characteristicsChanged();
+}
+
+void MediaStreamPrivate::trackMutedChanged(MediaStreamTrackPrivate&)
+{
+ scheduleDeferredTask([this] {
+ characteristicsChanged();
+ });
+}
+
+void MediaStreamPrivate::trackSettingsChanged(MediaStreamTrackPrivate&)
+{
+ characteristicsChanged();
+}
+
+void MediaStreamPrivate::trackEnabledChanged(MediaStreamTrackPrivate&)
+{
+ updateActiveVideoTrack();
+
+ scheduleDeferredTask([this] {
+ characteristicsChanged();
+ });
+}
+
+void MediaStreamPrivate::trackEnded(MediaStreamTrackPrivate&)
+{
+ scheduleDeferredTask([this] {
+ updateActiveState(NotifyClientOption::Notify);
+ characteristicsChanged();
+ });
+}
+
+void MediaStreamPrivate::scheduleDeferredTask(Function<void ()>&& function)
+{
+ ASSERT(function);
+ callOnMainThread([weakThis = createWeakPtr(), function = WTFMove(function)] {
+ if (!weakThis)
+ return;
- tracks.remove(pos);
+ function();
+ });
}
} // namespace WebCore