Commit 70d2a00a authored by tguilbert's avatar tguilbert Committed by Commit bot

Add RendererFactorySelector

There are 4 types of renderers that are used by WMPI directly, with a
potential fifth type in the works. Currently, a single RendererFactory
is chosen at WMPI creation time, and bound for the lifetime of WMPI.
However, there is a growing need to allow the smooth transition between
the use of different renderer types, after WMPI’s creation.

This CL introduces the RendererFactorySelector, which will allow us to
choose between different RendererFactory types at runtime. Its purpose
is to aggregate the signals and centralize the logic necessary to choose
which RendererFactory should be used when creating a new Renderer.

The interface is still extremelly simple, but it is expected to grow
as the number of concurrent RendererFactory types grows. In other words,
if there are 3+ renderer factories at play, some complexity is
inevitable, and the right place for that complexity to live is in the
RendererFactorySelector.

NOTE: The RendererFactorySelector uses a FactoryType enum as a key, in
order to avoid having to take dependencies on different (sometimes
platform specific) RendererFactories.

BUG=663503

Review-Url: https://codereview.chromium.org/2711153006
Cr-Commit-Position: refs/heads/master@{#466837}
parent 92efc425
......@@ -160,6 +160,7 @@
#include "media/base/media.h"
#include "media/base/media_log.h"
#include "media/base/media_switches.h"
#include "media/base/renderer_factory_selector.h"
#include "media/blink/url_index.h"
#include "media/blink/webencryptedmediaclient_impl.h"
#include "media/blink/webmediaplayer_impl.h"
......@@ -2898,6 +2899,7 @@ blink::WebMediaPlayer* RenderFrameImpl::CreateMediaPlayer(
#endif // defined(OS_ANDROID)
std::unique_ptr<media::RendererFactory> media_renderer_factory;
media::RendererFactorySelector::FactoryType factory_type;
if (use_fallback_path) {
#if defined(OS_ANDROID)
auto mojo_renderer_factory = base::MakeUnique<media::MojoRendererFactory>(
......@@ -2912,6 +2914,12 @@ blink::WebMediaPlayer* RenderFrameImpl::CreateMediaPlayer(
render_thread->GetStreamTexureFactory(),
base::ThreadTaskRunnerHandle::Get()));
#endif // defined(OS_ANDROID)
// TODO(tguilbert): Move this line back into an #if defined(OS_ANDROID).
// This will never be reached, unless we are on Android. Moving this line
// outside of the #if/#endif block fixes a "sometimes-uninitialized" error
// on desktop. This will be fixed with the next CL for crbug.com/663503.
factory_type = media::RendererFactorySelector::FactoryType::MEDIA_PLAYER;
} else {
#if defined(ENABLE_MOJO_RENDERER)
#if BUILDFLAG(ENABLE_RUNTIME_MEDIA_RENDERER_SELECTION)
......@@ -2921,6 +2929,8 @@ blink::WebMediaPlayer* RenderFrameImpl::CreateMediaPlayer(
media_log.get(), GetDecoderFactory(),
base::Bind(&RenderThreadImpl::GetGpuFactories,
base::Unretained(render_thread)));
factory_type = media::RendererFactorySelector::FactoryType::DEFAULT;
}
#endif // BUILDFLAG(ENABLE_RUNTIME_MEDIA_RENDERER_SELECTION)
if (!media_renderer_factory) {
......@@ -2928,12 +2938,16 @@ blink::WebMediaPlayer* RenderFrameImpl::CreateMediaPlayer(
base::Bind(&RenderThreadImpl::GetGpuFactories,
base::Unretained(render_thread)),
GetMediaInterfaceProvider());
factory_type = media::RendererFactorySelector::FactoryType::MOJO;
}
#else
media_renderer_factory = base::MakeUnique<media::DefaultRendererFactory>(
media_log.get(), GetDecoderFactory(),
base::Bind(&RenderThreadImpl::GetGpuFactories,
base::Unretained(render_thread)));
factory_type = media::RendererFactorySelector::FactoryType::DEFAULT;
#endif // defined(ENABLE_MOJO_RENDERER)
}
......@@ -2941,11 +2955,18 @@ blink::WebMediaPlayer* RenderFrameImpl::CreateMediaPlayer(
media_renderer_factory =
base::MakeUnique<media::remoting::AdaptiveRendererFactory>(
std::move(media_renderer_factory), std::move(remoting_controller));
factory_type = media::RendererFactorySelector::FactoryType::ADAPTIVE;
#endif
if (!url_index_.get() || url_index_->frame() != frame_)
url_index_.reset(new media::UrlIndex(frame_));
auto factory_selector = base::MakeUnique<media::RendererFactorySelector>();
factory_selector->AddFactory(factory_type, std::move(media_renderer_factory));
factory_selector->SetBaseFactoryType(factory_type);
std::unique_ptr<media::WebMediaPlayerParams> params(
new media::WebMediaPlayerParams(
std::move(media_log),
......@@ -2967,7 +2988,7 @@ blink::WebMediaPlayer* RenderFrameImpl::CreateMediaPlayer(
media::WebMediaPlayerImpl* media_player = new media::WebMediaPlayerImpl(
frame_, client, encrypted_client, GetWebMediaPlayerDelegate(),
std::move(media_renderer_factory), url_index_, std::move(params));
std::move(factory_selector), url_index_, std::move(params));
#if defined(OS_ANDROID) // WMPI_CAST
media_player->SetMediaPlayerManager(GetMediaPlayerManager());
......
......@@ -210,6 +210,8 @@ target(link_target_type, "base") {
"renderer_client.h",
"renderer_factory.cc",
"renderer_factory.h",
"renderer_factory_selector.cc",
"renderer_factory_selector.h",
"sample_format.cc",
"sample_format.h",
"seekable_buffer.cc",
......@@ -454,6 +456,7 @@ source_set("unit_tests") {
"null_video_sink_unittest.cc",
"pipeline_impl_unittest.cc",
"ranges_unittest.cc",
"renderer_factory_selector_unittest.cc",
"seekable_buffer_unittest.cc",
"serial_runner_unittest.cc",
"silent_sink_suspender_unittest.cc",
......
// Copyright 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 "media/base/renderer_factory_selector.h"
#include "base/logging.h"
namespace media {
RendererFactorySelector::RendererFactorySelector() {}
RendererFactorySelector::~RendererFactorySelector() {}
void RendererFactorySelector::AddFactory(
FactoryType type,
std::unique_ptr<RendererFactory> factory) {
DCHECK(!factories_[type]);
factories_[type] = std::move(factory);
}
void RendererFactorySelector::SetBaseFactoryType(FactoryType type) {
DCHECK(factories_[type]);
base_factory_type_ = type;
}
RendererFactory* RendererFactorySelector::GetCurrentFactory() {
DCHECK(base_factory_type_);
FactoryType next_factory_type = base_factory_type_.value();
RendererFactory* factory = factories_[next_factory_type].get();
if (factory == nullptr) {
NOTREACHED();
return nullptr;
}
DVLOG(1) << __func__ << " Selected factory type: " << next_factory_type;
return factory;
}
} // namespace media
// Copyright 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 MEDIA_BASE_RENDERER_FACTORY_SELECTOR_H_
#define MEDIA_BASE_RENDERER_FACTORY_SELECTOR_H_
#include "base/optional.h"
#include "media/base/renderer_factory.h"
namespace media {
// RendererFactorySelector owns RendererFactory instances used within WMPI.
// Its purpose is to aggregate the signals and centralize the logic behind
// choosing which RendererFactory should be used when creating a new Renderer.
class MEDIA_EXPORT RendererFactorySelector {
public:
enum FactoryType {
DEFAULT, // DefaultRendererFactory.
MOJO, // MojoRendererFactory.
MEDIA_PLAYER, // MediaPlayerRendererClientFactory.
ADAPTIVE, // AdaptiveRendererFactory.
FACTORY_TYPE_MAX = ADAPTIVE,
};
RendererFactorySelector();
~RendererFactorySelector();
// NOTE: There should be at most one factory per factory type.
void AddFactory(FactoryType type, std::unique_ptr<RendererFactory> factory);
// Sets the base factory to be returned, when there are no signals telling us
// to select any specific factory.
// NOTE: |type| can be different than FactoryType::DEFAULT. DEFAULT is used to
// identify the DefaultRendererFactory, not to indicate that a factory should
// be used by default.
void SetBaseFactoryType(FactoryType type);
// SetBaseFactoryType() must be called before calling this method.
// NOTE: This only returns the base factory type at the moment.
RendererFactory* GetCurrentFactory();
private:
base::Optional<FactoryType> base_factory_type_;
std::unique_ptr<RendererFactory> factories_[FACTORY_TYPE_MAX + 1];
DISALLOW_COPY_AND_ASSIGN(RendererFactorySelector);
};
} // namespace media
#endif // MEDIA_BASE_RENDERER_FACTORY_H_
// Copyright 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 <memory>
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "media/base/renderer_factory_selector.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
class RendererFactorySelectorTest : public testing::Test {
public:
typedef RendererFactorySelector::FactoryType FactoryType;
class FakeFactory : public RendererFactory {
public:
FakeFactory(FactoryType type) : type_(type){};
std::unique_ptr<Renderer> CreateRenderer(
const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
const scoped_refptr<base::TaskRunner>& worker_task_runner,
AudioRendererSink* audio_renderer_sink,
VideoRendererSink* video_renderer_sink,
const RequestSurfaceCB& request_surface_cb) override {
return std::unique_ptr<Renderer>();
}
FactoryType factory_type() { return type_; }
private:
FactoryType type_;
};
RendererFactorySelectorTest(){};
void AddFactory(FactoryType type) {
selector_.AddFactory(type, base::MakeUnique<FakeFactory>(type));
};
FactoryType GetCurrentlySelectedFactoryType() {
return reinterpret_cast<FakeFactory*>(selector_.GetCurrentFactory())
->factory_type();
}
protected:
RendererFactorySelector selector_;
DISALLOW_COPY_AND_ASSIGN(RendererFactorySelectorTest);
};
TEST_F(RendererFactorySelectorTest, SetBaseFactory_SingleFactory) {
AddFactory(FactoryType::DEFAULT);
selector_.SetBaseFactoryType(FactoryType::DEFAULT);
EXPECT_EQ(FactoryType::DEFAULT, GetCurrentlySelectedFactoryType());
}
TEST_F(RendererFactorySelectorTest, SetBaseFactory_MultipleFactory) {
AddFactory(FactoryType::DEFAULT);
AddFactory(FactoryType::MOJO);
selector_.SetBaseFactoryType(FactoryType::DEFAULT);
EXPECT_EQ(FactoryType::DEFAULT, GetCurrentlySelectedFactoryType());
selector_.SetBaseFactoryType(FactoryType::MOJO);
EXPECT_EQ(FactoryType::MOJO, GetCurrentlySelectedFactoryType());
}
} // namespace media
......@@ -175,7 +175,7 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
blink::WebMediaPlayerClient* client,
blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
WebMediaPlayerDelegate* delegate,
std::unique_ptr<RendererFactory> renderer_factory,
std::unique_ptr<RendererFactorySelector> renderer_factory_selector,
linked_ptr<UrlIndex> url_index,
std::unique_ptr<WebMediaPlayerParams> params)
: frame_(frame),
......@@ -230,7 +230,7 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
#endif
volume_(1.0),
volume_multiplier_(1.0),
renderer_factory_(std::move(renderer_factory)),
renderer_factory_selector_(std::move(renderer_factory_selector)),
surface_manager_(params->surface_manager()),
overlay_surface_id_(SurfaceManager::kNoSurfaceID),
suppress_destruction_errors_(false),
......@@ -249,7 +249,7 @@ WebMediaPlayerImpl::WebMediaPlayerImpl(
params->embedded_media_experience_enabled()) {
DVLOG(1) << __func__;
DCHECK(!adjust_allocated_memory_cb_.is_null());
DCHECK(renderer_factory_);
DCHECK(renderer_factory_selector_);
DCHECK(client_);
DCHECK(delegate_);
......@@ -1725,7 +1725,7 @@ std::unique_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() {
request_surface_cb = BindToCurrentLoop(
base::Bind(&WebMediaPlayerImpl::OnSurfaceRequested, AsWeakPtr()));
#endif
return renderer_factory_->CreateRenderer(
return renderer_factory_selector_->GetCurrentFactory()->CreateRenderer(
media_task_runner_, worker_task_runner_, audio_source_provider_.get(),
compositor_, request_surface_cb);
}
......
......@@ -28,7 +28,7 @@
#include "media/base/media_observer.h"
#include "media/base/media_tracks.h"
#include "media/base/pipeline_impl.h"
#include "media/base/renderer_factory.h"
#include "media/base/renderer_factory_selector.h"
#include "media/base/surface_manager.h"
#include "media/base/text_track.h"
#include "media/blink/buffered_data_source_host_impl.h"
......@@ -92,13 +92,13 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
public base::SupportsWeakPtr<WebMediaPlayerImpl> {
public:
// Constructs a WebMediaPlayer implementation using Chromium's media stack.
// |delegate| and |renderer_factory| must not be null.
// |delegate| and |renderer_factory_selector| must not be null.
WebMediaPlayerImpl(
blink::WebLocalFrame* frame,
blink::WebMediaPlayerClient* client,
blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
WebMediaPlayerDelegate* delegate,
std::unique_ptr<RendererFactory> renderer_factory,
std::unique_ptr<RendererFactorySelector> renderer_factory_selector,
linked_ptr<UrlIndex> url_index,
std::unique_ptr<WebMediaPlayerParams> params);
~WebMediaPlayerImpl() override;
......@@ -294,7 +294,7 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
void OnSurfaceRequested(bool decoder_requires_restart_for_overlay,
const SurfaceCreatedCB& surface_created_cb);
// Creates a Renderer via the |renderer_factory_|.
// Creates a Renderer via the |renderer_factory_selector_|.
std::unique_ptr<Renderer> CreateRenderer();
// Finishes starting the pipeline due to a call to load().
......@@ -617,7 +617,7 @@ class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
double volume_;
double volume_multiplier_;
std::unique_ptr<RendererFactory> renderer_factory_;
std::unique_ptr<RendererFactorySelector> renderer_factory_selector_;
// For requesting surfaces on behalf of the Android H/W decoder in fullscreen.
// This will be null everywhere but Android.
......
......@@ -211,14 +211,19 @@ class WebMediaPlayerImplTest : public testing::Test {
void InitializeWebMediaPlayerImpl(bool allow_suspend) {
std::unique_ptr<MediaLog> media_log(new MediaLog());
std::unique_ptr<RendererFactory> renderer_factory(
new DefaultRendererFactory(
auto factory_selector = base::MakeUnique<RendererFactorySelector>();
factory_selector->AddFactory(
RendererFactorySelector::FactoryType::DEFAULT,
base::MakeUnique<DefaultRendererFactory>(
media_log.get(), nullptr,
DefaultRendererFactory::GetGpuFactoriesCB()));
factory_selector->SetBaseFactoryType(
RendererFactorySelector::FactoryType::DEFAULT);
wmpi_ = base::MakeUnique<WebMediaPlayerImpl>(
web_local_frame_, &client_, nullptr, &delegate_,
std::move(renderer_factory), url_index_,
std::move(factory_selector), url_index_,
base::MakeUnique<WebMediaPlayerParams>(
std::move(media_log), WebMediaPlayerParams::DeferLoadCB(),
scoped_refptr<SwitchableAudioRendererSink>(),
......
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