Commit b1877f02 authored by Henrik Boström's avatar Henrik Boström Committed by Commit Bot

Remove WebRtcMediaStreamAdapterMap and WebRtcMediaStreamAdapter.

These classes were used to create and map blink-layer representations of
media streams with webrtc-layer representations of media streams.

The life-cycle of these streams were for some time complicated,
ownership was shared through reference counting between legacy stream
sets, senders and receivers. "GetOrCreate" was necessary in case the
stream already existed due to legacy APIs and threading restrictions
were different depending on if the stream was local or remote, with
destructor having to run on a different thread than it was created.
Because of the threading restrictions, ownership passing was made
explicit with "AdapterRef" classes, std::unique_ptr<>s and
ShallowCopy(). This is not very conventional or pretty.
The multi-thread usage required mutexes and this class has been
responsible for a couple of deadlock bugs and flaky tests due to
thread jumps in the destructor.

As of recently, stream objects only exist in the blink layer, and the
content/webrtc layer's notion of streams are just the stream IDs. CLs
listed prior in the referenced bugs have replaced function calls to
third_party/webrtc to use the "std::string stream_id"-versions.

With these classes no longer needed, we happily delete them.

For the time being, WebRtcMediaStreamTrackAdapter[Map] is still needed,
but this can likely be simplified during the Onion Souping.

TBR=pfeldman@chromium.org

Bug: 777617, 756436
Change-Id: I629597181fcd4eca286887cf1ff1ebbb3f08c64e
Reviewed-on: https://chromium-review.googlesource.com/1131499
Commit-Queue: Henrik Boström <hbos@chromium.org>
Reviewed-by: default avatarGuido Urdaneta <guidou@chromium.org>
Cr-Commit-Position: refs/heads/master@{#575212}
parent 1de58a36
...@@ -428,10 +428,6 @@ target(link_target_type, "renderer") { ...@@ -428,10 +428,6 @@ target(link_target_type, "renderer") {
"media/webrtc/webrtc_audio_renderer.h", "media/webrtc/webrtc_audio_renderer.h",
"media/webrtc/webrtc_audio_sink.cc", "media/webrtc/webrtc_audio_sink.cc",
"media/webrtc/webrtc_audio_sink.h", "media/webrtc/webrtc_audio_sink.h",
"media/webrtc/webrtc_media_stream_adapter.cc",
"media/webrtc/webrtc_media_stream_adapter.h",
"media/webrtc/webrtc_media_stream_adapter_map.cc",
"media/webrtc/webrtc_media_stream_adapter_map.h",
"media/webrtc/webrtc_media_stream_track_adapter.cc", "media/webrtc/webrtc_media_stream_track_adapter.cc",
"media/webrtc/webrtc_media_stream_track_adapter.h", "media/webrtc/webrtc_media_stream_track_adapter.h",
"media/webrtc/webrtc_media_stream_track_adapter_map.cc", "media/webrtc/webrtc_media_stream_track_adapter_map.cc",
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include "content/renderer/media/webrtc/rtc_event_log_output_sink_proxy.h" #include "content/renderer/media/webrtc/rtc_event_log_output_sink_proxy.h"
#include "content/renderer/media/webrtc/rtc_stats.h" #include "content/renderer/media/webrtc/rtc_stats.h"
#include "content/renderer/media/webrtc/webrtc_audio_device_impl.h" #include "content/renderer/media/webrtc/webrtc_audio_device_impl.h"
#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h"
#include "content/renderer/media/webrtc/webrtc_set_remote_description_observer.h" #include "content/renderer/media/webrtc/webrtc_set_remote_description_observer.h"
#include "content/renderer/media/webrtc/webrtc_uma_histograms.h" #include "content/renderer/media/webrtc/webrtc_uma_histograms.h"
#include "content/renderer/render_thread_impl.h" #include "content/renderer/render_thread_impl.h"
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_H_
#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_H_
#include <map>
#include <memory>
#include <string>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h"
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
class PeerConnectionDependencyFactory;
// An adapter is the glue between webrtc and blink media streams. Adapters of
// local media streams are created from a blink stream and get a webrtc stream
// correspondent. Adapters of remote media streams are created from a webrtc
// stream and get a blink stream correspondent. The adapter makes sure that when
// the stream it was created from is modified the correspondent is updated to
// reflect the new state.
// The adapters are thread safe but must be constructed on the correct thread
// (local adapters: main thread, remote adapters: webrtc signaling thread) and
// destroyed on the main thread.
class CONTENT_EXPORT WebRtcMediaStreamAdapter {
public:
using TrackAdapterRefs = std::vector<
std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>>;
// Creates an adapter for a local media stream. The adapter is already
// initialized. Invoked on the main thread.
static std::unique_ptr<WebRtcMediaStreamAdapter> CreateLocalStreamAdapter(
PeerConnectionDependencyFactory* factory,
scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map,
const blink::WebMediaStream& web_stream);
// Creates an adapter for a remote media stream. Invoked on the webrtc
// signaling thread. The adapter is initialized in a post to the main thread.
static std::unique_ptr<WebRtcMediaStreamAdapter> CreateRemoteStreamAdapter(
scoped_refptr<base::SingleThreadTaskRunner> main_thread,
scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map,
scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream);
// Invoke on the main thread.
virtual ~WebRtcMediaStreamAdapter();
// Once initialized, |webrtc_stream| and |web_stream| are accessible. An
// initialized adapter remains initialized until destroyed.
virtual bool is_initialized() const = 0;
virtual const scoped_refptr<webrtc::MediaStreamInterface>& webrtc_stream()
const = 0;
virtual const blink::WebMediaStream& web_stream() const = 0;
bool IsEqual(const blink::WebMediaStream& stream) const {
return (web_stream_.IsNull() && stream.IsNull()) ||
(web_stream_.Id() == stream.Id());
}
virtual void SetTracks(TrackAdapterRefs track_refs) = 0;
protected:
WebRtcMediaStreamAdapter(
scoped_refptr<base::SingleThreadTaskRunner> main_thread,
scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map,
scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream,
const blink::WebMediaStream& web_stream);
scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
// The map and owner of all track adapters for the associated peer connection.
// When a track is added or removed from this stream, the map provides us with
// a reference to the corresponding track adapter, creating a new one if
// necessary.
scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_;
// If |is_initialized()| both of these need to be set and remain constant.
scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream_;
blink::WebMediaStream web_stream_;
DISALLOW_COPY_AND_ASSIGN(WebRtcMediaStreamAdapter);
};
// Adapter implementation for a local |blink::WebMediaStream|. Created and
// destroyed on the main thread.
class LocalWebRtcMediaStreamAdapter : public WebRtcMediaStreamAdapter,
blink::WebMediaStreamObserver {
public:
LocalWebRtcMediaStreamAdapter(
PeerConnectionDependencyFactory* factory,
scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map,
const blink::WebMediaStream& web_stream);
~LocalWebRtcMediaStreamAdapter() override;
// |WebRtcMediaStreamAdapter| implementation.
bool is_initialized() const override;
const scoped_refptr<webrtc::MediaStreamInterface>& webrtc_stream()
const override;
const blink::WebMediaStream& web_stream() const override;
void SetTracks(TrackAdapterRefs track_refs) override;
private:
// A map between web track UniqueIDs and references to track adapters.
using LocalAdapterRefMap =
std::map<int, // blink::WebMediaStreamTrack::UniqueId()
std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>>;
// |MediaStreamObserver| implementation. Also used as a helper functions when
// adding/removing all tracks in the constructor/destructor.
void TrackAdded(const blink::WebMediaStreamTrack& web_track) override;
void TrackRemoved(const blink::WebMediaStreamTrack& web_track) override;
// Pointer to a |PeerConnectionDependencyFactory|, owned by the
// |RenderThread|. It's valid for the lifetime of |RenderThread|.
PeerConnectionDependencyFactory* const factory_;
// Track adapters belonging to this stream. Keeping adapter references alive
// ensures the adapters are not disposed by the |track_adapter_map_| as long
// as the webrtc layer track is in use by the webrtc layer stream.
LocalAdapterRefMap adapter_refs_;
DISALLOW_COPY_AND_ASSIGN(LocalWebRtcMediaStreamAdapter);
};
// Adapter implementation for a remote |webrtc::MediaStreamInterface|. Created
// on the the webrtc signaling thread, initialized on the main thread where it
// must be destroyed.
class RemoteWebRtcMediaStreamAdapter : public WebRtcMediaStreamAdapter {
public:
RemoteWebRtcMediaStreamAdapter(
scoped_refptr<base::SingleThreadTaskRunner> main_thread,
scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map,
scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream);
~RemoteWebRtcMediaStreamAdapter() override;
// |WebRtcMediaStreamAdapter| implementation.
bool is_initialized() const override;
const scoped_refptr<webrtc::MediaStreamInterface>& webrtc_stream()
const override;
const blink::WebMediaStream& web_stream() const override;
void SetTracks(TrackAdapterRefs track_refs) override;
private:
// Track adapters for the remote webrtc tracks of a stream.
using RemoteAdapterRefs = WebRtcMediaStreamAdapter::TrackAdapterRefs;
static bool RemoteAdapterRefsContainsTrack(
const RemoteAdapterRefs& adapter_refs,
webrtc::MediaStreamTrackInterface* track);
// Gets the adapters for the tracks that are members of the webrtc stream.
// Invoke on webrtc signaling thread. New adapters are initialized in a post
// to the main thread after which their |web_track| becomes available.
static RemoteAdapterRefs GetRemoteAdapterRefsFromWebRtcStream(
const scoped_refptr<WebRtcMediaStreamTrackAdapterMap>& track_adapter_map,
webrtc::MediaStreamInterface* webrtc_stream);
void InitializeOnMainThread(const std::string& label,
RemoteAdapterRefs track_adapter_refs,
size_t audio_track_count,
size_t video_track_count);
mutable base::Lock lock_;
bool is_initialized_;
// Track adapters belonging to this stream. Keeping adapter references alive
// ensures the adapters are not disposed by the |track_adapter_map_| as long
// as the webrtc layer track is in use by the webrtc layer stream.
RemoteAdapterRefs adapter_refs_;
base::WeakPtrFactory<RemoteWebRtcMediaStreamAdapter> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RemoteWebRtcMediaStreamAdapter);
};
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_H_
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h"
namespace content {
WebRtcMediaStreamAdapterMap::AdapterEntry::AdapterEntry(
std::unique_ptr<WebRtcMediaStreamAdapter> adapter)
: adapter(std::move(adapter)), ref_count(0) {
DCHECK(this->adapter);
}
WebRtcMediaStreamAdapterMap::AdapterEntry::AdapterEntry(AdapterEntry&& other)
: adapter(other.adapter.release()), ref_count(other.ref_count) {}
WebRtcMediaStreamAdapterMap::AdapterEntry::~AdapterEntry() {
// |ref_count| is allowed to be non-zero only if this entry has been moved
// which is the case if the |adapter| has already been released.
DCHECK(!ref_count || !adapter);
}
WebRtcMediaStreamAdapterMap::AdapterRef::AdapterRef(
scoped_refptr<WebRtcMediaStreamAdapterMap> map,
Type type,
AdapterEntry* adapter_entry)
: map_(std::move(map)), type_(type), adapter_entry_(adapter_entry) {
DCHECK(map_);
DCHECK(adapter_entry_);
map_->lock_.AssertAcquired();
++adapter_entry_->ref_count;
}
WebRtcMediaStreamAdapterMap::AdapterRef::~AdapterRef() {
DCHECK(map_->main_thread_->BelongsToCurrentThread());
std::unique_ptr<WebRtcMediaStreamAdapter> removed_adapter;
{
base::AutoLock scoped_lock(map_->lock_);
--adapter_entry_->ref_count;
if (adapter_entry_->ref_count == 0) {
removed_adapter = std::move(adapter_entry_->adapter);
// "GetOrCreate..." ensures the adapter is initialized and the secondary
// key is set before the last |AdapterRef| is destroyed. We can use either
// the primary or secondary key for removal.
if (type_ == Type::kLocal) {
map_->local_stream_adapters_.EraseByPrimary(
removed_adapter->web_stream().UniqueId());
} else {
map_->remote_stream_adapters_.EraseByPrimary(
removed_adapter->webrtc_stream().get());
}
}
}
// Destroy the adapter whilst not holding the lock so that it is safe for
// destructors to use the signaling thread synchronously without any risk of
// deadlock.
removed_adapter.reset();
}
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>
WebRtcMediaStreamAdapterMap::AdapterRef::Copy() const {
base::AutoLock scoped_lock(map_->lock_);
return base::WrapUnique(new AdapterRef(map_, type_, adapter_entry_));
}
WebRtcMediaStreamAdapterMap::WebRtcMediaStreamAdapterMap(
PeerConnectionDependencyFactory* const factory,
scoped_refptr<base::SingleThreadTaskRunner> main_thread,
scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map)
: factory_(factory),
main_thread_(std::move(main_thread)),
track_adapter_map_(std::move(track_adapter_map)) {
DCHECK(factory_);
DCHECK(main_thread_);
DCHECK(track_adapter_map_);
}
WebRtcMediaStreamAdapterMap::~WebRtcMediaStreamAdapterMap() {
DCHECK(local_stream_adapters_.empty());
DCHECK(remote_stream_adapters_.empty());
}
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>
WebRtcMediaStreamAdapterMap::GetLocalStreamAdapter(
const blink::WebMediaStream& web_stream) {
base::AutoLock scoped_lock(lock_);
AdapterEntry* adapter_entry =
local_stream_adapters_.FindByPrimary(web_stream.UniqueId());
if (!adapter_entry)
return nullptr;
return base::WrapUnique(
new AdapterRef(this, AdapterRef::Type::kLocal, adapter_entry));
}
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>
WebRtcMediaStreamAdapterMap::GetLocalStreamAdapter(
webrtc::MediaStreamInterface* webrtc_stream) {
base::AutoLock scoped_lock(lock_);
AdapterEntry* adapter_entry =
local_stream_adapters_.FindBySecondary(webrtc_stream);
if (!adapter_entry)
return nullptr;
return base::WrapUnique(
new AdapterRef(this, AdapterRef::Type::kLocal, adapter_entry));
}
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>
WebRtcMediaStreamAdapterMap::GetOrCreateLocalStreamAdapter(
const blink::WebMediaStream& web_stream) {
CHECK(main_thread_->BelongsToCurrentThread());
CHECK(!web_stream.IsNull());
base::AutoLock scoped_lock(lock_);
AdapterEntry* adapter_entry =
local_stream_adapters_.FindByPrimary(web_stream.UniqueId());
if (!adapter_entry) {
std::unique_ptr<WebRtcMediaStreamAdapter> adapter;
{
// Make sure we don't hold the lock while calling out to
// CreateLocalStreamAdapter(). The reason is that constructing a local
// stream adapter, will synchronize with WebRTC's signaling thread and
// callbacks on the signaling thread might end up coming back to us
// and we might need the lock then.
base::AutoUnlock scoped_unlock(lock_);
adapter = WebRtcMediaStreamAdapter::CreateLocalStreamAdapter(
factory_, track_adapter_map_, web_stream);
}
adapter_entry = local_stream_adapters_.Insert(web_stream.UniqueId(),
std::move(adapter));
CHECK(adapter_entry->adapter->is_initialized());
CHECK(adapter_entry->adapter->webrtc_stream());
local_stream_adapters_.SetSecondaryKey(
web_stream.UniqueId(), adapter_entry->adapter->webrtc_stream().get());
}
return base::WrapUnique(
new AdapterRef(this, AdapterRef::Type::kLocal, adapter_entry));
}
size_t WebRtcMediaStreamAdapterMap::GetLocalStreamCount() const {
base::AutoLock scoped_lock(lock_);
return local_stream_adapters_.PrimarySize();
}
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>
WebRtcMediaStreamAdapterMap::GetRemoteStreamAdapter(
const blink::WebMediaStream& web_stream) {
base::AutoLock scoped_lock(lock_);
AdapterEntry* adapter_entry =
remote_stream_adapters_.FindBySecondary(web_stream.UniqueId());
if (!adapter_entry)
return nullptr;
return base::WrapUnique(
new AdapterRef(this, AdapterRef::Type::kRemote, adapter_entry));
}
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>
WebRtcMediaStreamAdapterMap::GetRemoteStreamAdapter(
webrtc::MediaStreamInterface* webrtc_stream) {
base::AutoLock scoped_lock(lock_);
AdapterEntry* adapter_entry =
remote_stream_adapters_.FindByPrimary(webrtc_stream);
if (!adapter_entry)
return nullptr;
return base::WrapUnique(
new AdapterRef(this, AdapterRef::Type::kRemote, adapter_entry));
}
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>
WebRtcMediaStreamAdapterMap::GetOrCreateRemoteStreamAdapter(
scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream) {
CHECK(!main_thread_->BelongsToCurrentThread());
CHECK(webrtc_stream);
base::AutoLock scoped_lock(lock_);
AdapterEntry* adapter_entry =
remote_stream_adapters_.FindByPrimary(webrtc_stream.get());
if (!adapter_entry) {
// Make sure we don't hold the lock while calling out to
// CreateRemoteStreamAdapter(). The reason is that it might synchronize
// with other threads, possibly the main thread, where we might need to grab
// the lock (e.g. inside of GetOrCreateLocalStreamAdapter()).
std::unique_ptr<WebRtcMediaStreamAdapter> adapter;
{
base::AutoUnlock scoped_unlock(lock_);
adapter = WebRtcMediaStreamAdapter::CreateRemoteStreamAdapter(
main_thread_, track_adapter_map_, webrtc_stream.get());
}
adapter_entry =
remote_stream_adapters_.Insert(webrtc_stream.get(), std::move(adapter));
// The new adapter is initialized in a post to the main thread. As soon as
// it is initialized we map its |webrtc_stream| to the
// |remote_stream_adapters_| entry as its secondary key. This ensures that
// there is at least one |AdapterRef| alive until after the adapter is
// initialized and its secondary key is set.
main_thread_->PostTask(
FROM_HERE,
base::BindOnce(
&WebRtcMediaStreamAdapterMap::OnRemoteStreamAdapterInitialized,
this,
base::WrapUnique(new AdapterRef(this, AdapterRef::Type::kRemote,
adapter_entry))));
}
return base::WrapUnique(
new AdapterRef(this, AdapterRef::Type::kRemote, adapter_entry));
}
size_t WebRtcMediaStreamAdapterMap::GetRemoteStreamCount() const {
base::AutoLock scoped_lock(lock_);
return remote_stream_adapters_.PrimarySize();
}
void WebRtcMediaStreamAdapterMap::OnRemoteStreamAdapterInitialized(
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref) {
CHECK(main_thread_->BelongsToCurrentThread());
CHECK(adapter_ref->is_initialized());
CHECK(!adapter_ref->adapter().web_stream().IsNull());
{
base::AutoLock scoped_lock(lock_);
remote_stream_adapters_.SetSecondaryKey(
adapter_ref->adapter().webrtc_stream().get(),
adapter_ref->adapter().web_stream().UniqueId());
}
}
} // namespace content
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_MAP_H_
#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_MAP_H_
#include <map>
#include <memory>
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "content/renderer/media/webrtc/two_keys_adapter_map.h"
#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h"
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
// A map and owner of |WebRtcMediaStreamAdapter|s. Adapters are the glue between
// blink and webrtc layer versions of streams. As long as a stream is in use by
// a peer connection there has to exist an adapter for it. The map takes care of
// creating and disposing stream adapters. Adapters are accessed via
// |AdapterRef|s, when all references to an adapter are destroyed it is
// destroyed and removed from the map.
class CONTENT_EXPORT WebRtcMediaStreamAdapterMap
: public base::RefCountedThreadSafe<WebRtcMediaStreamAdapterMap> {
private:
// The map's entries are reference counted in order to remove the adapter when
// all |AdapterRef|s referencing an entry are destroyed.
// Private section needed here due to |AdapterRef|'s usage of |AdapterEntry|.
struct AdapterEntry {
AdapterEntry(std::unique_ptr<WebRtcMediaStreamAdapter> adapter);
AdapterEntry(AdapterEntry&& other);
~AdapterEntry();
AdapterEntry(const AdapterEntry&) = delete;
AdapterEntry& operator=(const AdapterEntry&) = delete;
std::unique_ptr<WebRtcMediaStreamAdapter> adapter;
size_t ref_count;
};
public:
// Accessor to an adapter to take care of reference counting. When the last
// |AdapterRef| is destroyed, the corresponding adapter is destroyed and
// removed from the map.
class CONTENT_EXPORT AdapterRef {
public:
// Must be invoked on the main thread. If this was the last reference to the
// adapter it will be disposed and removed from the map.
~AdapterRef();
std::unique_ptr<AdapterRef> Copy() const;
bool is_initialized() const { return adapter().is_initialized(); }
const WebRtcMediaStreamAdapter& adapter() const {
return *adapter_entry_->adapter;
}
WebRtcMediaStreamAdapter& adapter() { return *adapter_entry_->adapter; }
private:
friend class WebRtcMediaStreamAdapterMap;
enum class Type { kLocal, kRemote };
// Increments the |AdapterEntry::ref_count|. Assumes map's |lock_| is held.
AdapterRef(scoped_refptr<WebRtcMediaStreamAdapterMap> map,
Type type,
AdapterEntry* adapter_entry);
scoped_refptr<WebRtcMediaStreamAdapterMap> map_;
Type type_;
AdapterEntry* adapter_entry_;
};
// Must be invoked on the main thread.
WebRtcMediaStreamAdapterMap(
PeerConnectionDependencyFactory* const factory,
scoped_refptr<base::SingleThreadTaskRunner> main_thread,
scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map);
// Gets a new reference to the local stream adapter, or null if no such
// adapter was found. When all references are destroyed the adapter is
// destroyed and removed from the map. This can be called on any thread, but
// references must be destroyed on the main thread.
// The adapter is a associated with a blink and webrtc stream, lookup works by
// either stream.
std::unique_ptr<AdapterRef> GetLocalStreamAdapter(
const blink::WebMediaStream& web_stream);
std::unique_ptr<AdapterRef> GetLocalStreamAdapter(
webrtc::MediaStreamInterface* webrtc_stream);
// Invoke on the main thread. Gets a new reference to the local stream adapter
// for the web stream. If no adapter exists for the stream one is created.
// When all references are destroyed the adapter is destroyed and removed from
// the map. References must be destroyed on the main thread.
std::unique_ptr<AdapterRef> GetOrCreateLocalStreamAdapter(
const blink::WebMediaStream& web_stream);
size_t GetLocalStreamCount() const;
// Gets a new reference to the remote stream adapter by ID, or null if no such
// adapter was found. When all references are destroyed the adapter is
// destroyed and removed from the map. This can be called on any thread, but
// references must be destroyed on the main thread. The adapter is a
// associated with a blink and webrtc stream, lookup works by either stream.
// First variety: If an adapter exists it will already be initialized, if one
// does not exist null is returned.
std::unique_ptr<AdapterRef> GetRemoteStreamAdapter(
const blink::WebMediaStream& web_stream);
// Second variety: If an adapter exists it may or may not be initialized, see
// |AdapterRef::is_initialized|. If an adapter does not exist null is
// returned.
std::unique_ptr<AdapterRef> GetRemoteStreamAdapter(
webrtc::MediaStreamInterface* webrtc_stream);
// Invoke on the webrtc signaling thread. Gets a new reference to the remote
// stream adapter for the webrtc stream. If no adapter exists for the stream
// one is created and initialization completes on the main thread in a post.
// When all references are destroyed the adapter is destroyed and removed from
// the map. References must be destroyed on the main thread.
std::unique_ptr<AdapterRef> GetOrCreateRemoteStreamAdapter(
scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream);
size_t GetRemoteStreamCount() const;
const scoped_refptr<WebRtcMediaStreamTrackAdapterMap>& track_adapter_map()
const {
return track_adapter_map_;
}
private:
friend class base::RefCountedThreadSafe<WebRtcMediaStreamAdapterMap>;
// "(blink::WebMediaStream, webrtc::MediaStreamInterface) -> AdapterEntry"
// maps. The primary key is based on the object used to create the adapter.
// Local streams are created from |blink::WebMediaStream|s, remote streams are
// created from |webrtc::MediaStreamInterface|s.
// The adapter keeps the |webrtc::MediaStreamInterface| alive with ref
// counting making it safe to use a raw pointer for key.
using LocalStreamAdapterMap =
TwoKeysAdapterMap<int, // blink::WebMediaStream::UniqueId()
webrtc::MediaStreamInterface*,
AdapterEntry>;
using RemoteStreamAdapterMap =
TwoKeysAdapterMap<webrtc::MediaStreamInterface*,
int, // blink::WebMediaStream::UniqueId()
AdapterEntry>;
// Invoke on the main thread.
virtual ~WebRtcMediaStreamAdapterMap();
void OnRemoteStreamAdapterInitialized(
std::unique_ptr<AdapterRef> adapter_ref);
// Pointer to a |PeerConnectionDependencyFactory| owned by the |RenderThread|.
// It's valid for the lifetime of |RenderThread|.
PeerConnectionDependencyFactory* const factory_;
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
// Takes care of creating and owning track adapters, used by stream adapters.
const scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_;
mutable base::Lock lock_;
LocalStreamAdapterMap local_stream_adapters_;
RemoteStreamAdapterMap remote_stream_adapters_;
};
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_MAP_H_
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h"
#include <memory>
#include <string>
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/scoped_task_environment.h"
#include "content/child/child_process.h"
#include "content/renderer/media/audio/mock_audio_device_factory.h"
#include "content/renderer/media/stream/media_stream_video_source.h"
#include "content/renderer/media/stream/media_stream_video_track.h"
#include "content/renderer/media/stream/mock_media_stream_video_source.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_heap.h"
using ::testing::_;
namespace content {
class WebRtcMediaStreamAdapterMapTest : public ::testing::Test {
public:
void SetUp() override {
dependency_factory_.reset(new MockPeerConnectionDependencyFactory());
main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting();
map_ = new WebRtcMediaStreamAdapterMap(
dependency_factory_.get(), main_thread_,
new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(),
main_thread_));
}
void TearDown() override { blink::WebHeap::CollectAllGarbageForTesting(); }
blink::WebMediaStream CreateLocalStream(const std::string& id) {
blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks(
static_cast<size_t>(1));
blink::WebMediaStreamSource video_source;
video_source.Initialize("video_source",
blink::WebMediaStreamSource::kTypeVideo,
"video_source", false /* remote */);
MediaStreamVideoSource* native_source = new MockMediaStreamVideoSource();
video_source.SetExtraData(native_source);
web_video_tracks[0] = MediaStreamVideoTrack::CreateVideoTrack(
native_source, MediaStreamVideoSource::ConstraintsCallback(), true);
blink::WebMediaStream web_stream;
web_stream.Initialize(blink::WebString::FromUTF8(id),
blink::WebVector<blink::WebMediaStreamTrack>(),
web_video_tracks);
return web_stream;
}
scoped_refptr<webrtc::MediaStreamInterface> CreateRemoteStream(
const std::string& id) {
scoped_refptr<webrtc::MediaStreamInterface> stream(
new rtc::RefCountedObject<MockMediaStream>(id));
stream->AddTrack(MockWebRtcAudioTrack::Create("remote_audio_track").get());
stream->AddTrack(MockWebRtcVideoTrack::Create("remote_video_track").get());
return stream;
}
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>
GetOrCreateRemoteStreamAdapter(webrtc::MediaStreamInterface* webrtc_stream) {
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref;
dependency_factory_->GetWebRtcSignalingThread()->PostTask(
FROM_HERE,
base::BindOnce(&WebRtcMediaStreamAdapterMapTest::
GetOrCreateRemoteStreamAdapterOnSignalingThread,
base::Unretained(this), base::Unretained(webrtc_stream),
base::Unretained(&adapter_ref)));
RunMessageLoopsUntilIdle();
DCHECK(adapter_ref);
return adapter_ref;
}
protected:
void GetOrCreateRemoteStreamAdapterOnSignalingThread(
webrtc::MediaStreamInterface* webrtc_stream,
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>* adapter_ref) {
*adapter_ref = map_->GetOrCreateRemoteStreamAdapter(webrtc_stream);
EXPECT_TRUE(*adapter_ref);
}
// Runs message loops on the webrtc signaling thread and the main thread until
// idle.
void RunMessageLoopsUntilIdle() {
base::WaitableEvent waitable_event(
base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
dependency_factory_->GetWebRtcSignalingThread()->PostTask(
FROM_HERE, base::BindOnce(&WebRtcMediaStreamAdapterMapTest::SignalEvent,
base::Unretained(this), &waitable_event));
waitable_event.Wait();
base::RunLoop().RunUntilIdle();
}
void SignalEvent(base::WaitableEvent* waitable_event) {
waitable_event->Signal();
}
// Message loop and child processes is needed for task queues and threading to
// work, as is necessary to create tracks and adapters.
base::test::ScopedTaskEnvironment scoped_task_environment_;
ChildProcess child_process_;
std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
scoped_refptr<WebRtcMediaStreamAdapterMap> map_;
};
TEST_F(WebRtcMediaStreamAdapterMapTest, AddAndRemoveLocalStreamAdapter) {
blink::WebMediaStream local_web_stream = CreateLocalStream("local_stream");
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref =
map_->GetOrCreateLocalStreamAdapter(local_web_stream);
EXPECT_TRUE(adapter_ref);
EXPECT_TRUE(adapter_ref->adapter().IsEqual(local_web_stream));
EXPECT_EQ(1u, map_->GetLocalStreamCount());
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref2 =
map_->GetLocalStreamAdapter(local_web_stream);
EXPECT_TRUE(adapter_ref2);
EXPECT_EQ(&adapter_ref2->adapter(), &adapter_ref->adapter());
EXPECT_EQ(1u, map_->GetLocalStreamCount());
adapter_ref.reset();
EXPECT_EQ(1u, map_->GetLocalStreamCount());
adapter_ref2.reset();
EXPECT_EQ(0u, map_->GetLocalStreamCount());
}
TEST_F(WebRtcMediaStreamAdapterMapTest, LookUpLocalAdapterByWebRtcStream) {
blink::WebMediaStream local_web_stream = CreateLocalStream("local_stream");
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref =
map_->GetOrCreateLocalStreamAdapter(local_web_stream);
EXPECT_TRUE(adapter_ref);
EXPECT_TRUE(adapter_ref->adapter().IsEqual(local_web_stream));
EXPECT_EQ(1u, map_->GetLocalStreamCount());
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref2 =
map_->GetLocalStreamAdapter(adapter_ref->adapter().web_stream());
EXPECT_TRUE(adapter_ref2);
EXPECT_EQ(&adapter_ref2->adapter(), &adapter_ref->adapter());
}
TEST_F(WebRtcMediaStreamAdapterMapTest, GetLocalStreamAdapterInvalidID) {
blink::WebMediaStream local_web_stream = CreateLocalStream("missing");
EXPECT_FALSE(map_->GetLocalStreamAdapter(local_web_stream));
}
TEST_F(WebRtcMediaStreamAdapterMapTest, AddAndRemoveRemoteStreamAdapter) {
scoped_refptr<webrtc::MediaStreamInterface> remote_webrtc_stream =
CreateRemoteStream("remote_stream");
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref =
GetOrCreateRemoteStreamAdapter(remote_webrtc_stream.get());
EXPECT_EQ(remote_webrtc_stream, adapter_ref->adapter().webrtc_stream());
EXPECT_EQ(1u, map_->GetRemoteStreamCount());
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref2 =
map_->GetRemoteStreamAdapter(remote_webrtc_stream.get());
EXPECT_TRUE(adapter_ref2);
EXPECT_EQ(&adapter_ref2->adapter(), &adapter_ref->adapter());
EXPECT_EQ(1u, map_->GetRemoteStreamCount());
adapter_ref.reset();
EXPECT_EQ(1u, map_->GetRemoteStreamCount());
adapter_ref2.reset();
EXPECT_EQ(0u, map_->GetRemoteStreamCount());
}
TEST_F(WebRtcMediaStreamAdapterMapTest, LookUpRemoteAdapterByWebStream) {
scoped_refptr<webrtc::MediaStreamInterface> remote_webrtc_stream =
CreateRemoteStream("remote_stream");
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref =
GetOrCreateRemoteStreamAdapter(remote_webrtc_stream.get());
EXPECT_EQ(remote_webrtc_stream, adapter_ref->adapter().webrtc_stream());
EXPECT_EQ(1u, map_->GetRemoteStreamCount());
std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref2 =
map_->GetRemoteStreamAdapter(
adapter_ref->adapter().webrtc_stream().get());
EXPECT_TRUE(adapter_ref2);
EXPECT_EQ(&adapter_ref2->adapter(), &adapter_ref->adapter());
}
TEST_F(WebRtcMediaStreamAdapterMapTest, GetRemoteStreamAdapterInvalidID) {
scoped_refptr<webrtc::MediaStreamInterface> remote_webrtc_stream =
CreateRemoteStream("missing");
EXPECT_FALSE(map_->GetRemoteStreamAdapter(remote_webrtc_stream.get()));
}
} // namespace content
...@@ -1697,8 +1697,6 @@ test("content_unittests") { ...@@ -1697,8 +1697,6 @@ test("content_unittests") {
"../renderer/media/webrtc/transceiver_state_surfacer_unittest.cc", "../renderer/media/webrtc/transceiver_state_surfacer_unittest.cc",
"../renderer/media/webrtc/two_keys_adapter_map_unittest.cc", "../renderer/media/webrtc/two_keys_adapter_map_unittest.cc",
"../renderer/media/webrtc/webrtc_audio_renderer_unittest.cc", "../renderer/media/webrtc/webrtc_audio_renderer_unittest.cc",
"../renderer/media/webrtc/webrtc_media_stream_adapter_map_unittest.cc",
"../renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc",
"../renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc", "../renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc",
"../renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc", "../renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc",
"../renderer/media/webrtc/webrtc_set_remote_description_observer_unittest.cc", "../renderer/media/webrtc/webrtc_set_remote_description_observer_unittest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment