diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp')
-rw-r--r-- | Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp | 339 |
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 |