[Chromecast] Support blocking some video resolutions
This allows playback to be blocked based on certain conditions including video resolution (see linked bug + internal CL). BUG=internal b/31055542 Review-Url: https://codereview.chromium.org/2277853002 Cr-Commit-Position: refs/heads/master@{#415218}
This commit is contained in:
@@ -82,7 +82,8 @@ static std::unique_ptr<::shell::Service> CreateMojoMediaApplication(
|
|||||||
base::Bind(&CastContentBrowserClient::CreateMediaPipelineBackend,
|
base::Bind(&CastContentBrowserClient::CreateMediaPipelineBackend,
|
||||||
base::Unretained(browser_client)),
|
base::Unretained(browser_client)),
|
||||||
base::Bind(&CastContentBrowserClient::CreateCdmFactory,
|
base::Bind(&CastContentBrowserClient::CreateCdmFactory,
|
||||||
base::Unretained(browser_client))));
|
base::Unretained(browser_client)),
|
||||||
|
browser_client->GetVideoResolutionPolicy()));
|
||||||
return std::unique_ptr<::shell::Service>(
|
return std::unique_ptr<::shell::Service>(
|
||||||
new ::media::MojoMediaApplication(std::move(mojo_media_client),
|
new ::media::MojoMediaApplication(std::move(mojo_media_client),
|
||||||
quit_closure));
|
quit_closure));
|
||||||
@@ -132,6 +133,11 @@ std::unique_ptr<CastService> CastContentBrowserClient::CreateCastService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(OS_ANDROID)
|
#if !defined(OS_ANDROID)
|
||||||
|
media::VideoResolutionPolicy*
|
||||||
|
CastContentBrowserClient::GetVideoResolutionPolicy() {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
scoped_refptr<base::SingleThreadTaskRunner>
|
scoped_refptr<base::SingleThreadTaskRunner>
|
||||||
CastContentBrowserClient::GetMediaTaskRunner() {
|
CastContentBrowserClient::GetMediaTaskRunner() {
|
||||||
DCHECK(cast_browser_main_parts_);
|
DCHECK(cast_browser_main_parts_);
|
||||||
|
@@ -43,6 +43,7 @@ class MediaPipelineBackendManager;
|
|||||||
struct MediaPipelineDeviceParams;
|
struct MediaPipelineDeviceParams;
|
||||||
class MediaResourceTracker;
|
class MediaResourceTracker;
|
||||||
class VideoPlaneController;
|
class VideoPlaneController;
|
||||||
|
class VideoResolutionPolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace shell {
|
namespace shell {
|
||||||
@@ -74,6 +75,9 @@ class CastContentBrowserClient : public content::ContentBrowserClient {
|
|||||||
media::VideoPlaneController* video_plane_controller);
|
media::VideoPlaneController* video_plane_controller);
|
||||||
|
|
||||||
#if !defined(OS_ANDROID)
|
#if !defined(OS_ANDROID)
|
||||||
|
// Gets object for enforcing video resolution policy restrictions.
|
||||||
|
virtual media::VideoResolutionPolicy* GetVideoResolutionPolicy();
|
||||||
|
|
||||||
// Returns the task runner that must be used for media IO.
|
// Returns the task runner that must be used for media IO.
|
||||||
scoped_refptr<base::SingleThreadTaskRunner> GetMediaTaskRunner();
|
scoped_refptr<base::SingleThreadTaskRunner> GetMediaTaskRunner();
|
||||||
|
|
||||||
|
@@ -47,6 +47,8 @@ source_set("media") {
|
|||||||
sources += [
|
sources += [
|
||||||
"cma_message_filter_host.cc",
|
"cma_message_filter_host.cc",
|
||||||
"cma_message_filter_host.h",
|
"cma_message_filter_host.h",
|
||||||
|
"video_resolution_policy.cc",
|
||||||
|
"video_resolution_policy.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,9 +15,11 @@ namespace media {
|
|||||||
|
|
||||||
CastMojoMediaClient::CastMojoMediaClient(
|
CastMojoMediaClient::CastMojoMediaClient(
|
||||||
const CreateMediaPipelineBackendCB& create_backend_cb,
|
const CreateMediaPipelineBackendCB& create_backend_cb,
|
||||||
const CreateCdmFactoryCB& create_cdm_factory_cb)
|
const CreateCdmFactoryCB& create_cdm_factory_cb,
|
||||||
|
VideoResolutionPolicy* video_resolution_policy)
|
||||||
: create_backend_cb_(create_backend_cb),
|
: create_backend_cb_(create_backend_cb),
|
||||||
create_cdm_factory_cb_(create_cdm_factory_cb) {}
|
create_cdm_factory_cb_(create_cdm_factory_cb),
|
||||||
|
video_resolution_policy_(video_resolution_policy) {}
|
||||||
|
|
||||||
CastMojoMediaClient::~CastMojoMediaClient() {}
|
CastMojoMediaClient::~CastMojoMediaClient() {}
|
||||||
|
|
||||||
@@ -26,7 +28,8 @@ std::unique_ptr<::media::Renderer> CastMojoMediaClient::CreateRenderer(
|
|||||||
scoped_refptr<::media::MediaLog> media_log,
|
scoped_refptr<::media::MediaLog> media_log,
|
||||||
const std::string& audio_device_id) {
|
const std::string& audio_device_id) {
|
||||||
return base::MakeUnique<chromecast::media::CastRenderer>(
|
return base::MakeUnique<chromecast::media::CastRenderer>(
|
||||||
create_backend_cb_, std::move(media_task_runner), audio_device_id);
|
create_backend_cb_, std::move(media_task_runner), audio_device_id,
|
||||||
|
video_resolution_policy_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<::media::CdmFactory> CastMojoMediaClient::CreateCdmFactory(
|
std::unique_ptr<::media::CdmFactory> CastMojoMediaClient::CreateCdmFactory(
|
||||||
|
@@ -11,13 +11,16 @@
|
|||||||
namespace chromecast {
|
namespace chromecast {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
|
class VideoResolutionPolicy;
|
||||||
|
|
||||||
class CastMojoMediaClient : public ::media::MojoMediaClient {
|
class CastMojoMediaClient : public ::media::MojoMediaClient {
|
||||||
public:
|
public:
|
||||||
using CreateCdmFactoryCB =
|
using CreateCdmFactoryCB =
|
||||||
base::Callback<std::unique_ptr<::media::CdmFactory>()>;
|
base::Callback<std::unique_ptr<::media::CdmFactory>()>;
|
||||||
|
|
||||||
CastMojoMediaClient(const CreateMediaPipelineBackendCB& create_backend_cb,
|
CastMojoMediaClient(const CreateMediaPipelineBackendCB& create_backend_cb,
|
||||||
const CreateCdmFactoryCB& create_cdm_factory_cb);
|
const CreateCdmFactoryCB& create_cdm_factory_cb,
|
||||||
|
VideoResolutionPolicy* video_resolution_policy);
|
||||||
~CastMojoMediaClient() override;
|
~CastMojoMediaClient() override;
|
||||||
|
|
||||||
// MojoMediaClient overrides.
|
// MojoMediaClient overrides.
|
||||||
@@ -31,6 +34,7 @@ class CastMojoMediaClient : public ::media::MojoMediaClient {
|
|||||||
private:
|
private:
|
||||||
const CreateMediaPipelineBackendCB create_backend_cb_;
|
const CreateMediaPipelineBackendCB create_backend_cb_;
|
||||||
const CreateCdmFactoryCB create_cdm_factory_cb_;
|
const CreateCdmFactoryCB create_cdm_factory_cb_;
|
||||||
|
VideoResolutionPolicy* video_resolution_policy_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CastMojoMediaClient);
|
DISALLOW_COPY_AND_ASSIGN(CastMojoMediaClient);
|
||||||
};
|
};
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
#include "base/single_thread_task_runner.h"
|
#include "base/single_thread_task_runner.h"
|
||||||
#include "chromecast/base/task_runner_impl.h"
|
#include "chromecast/base/task_runner_impl.h"
|
||||||
|
#include "chromecast/browser/media/video_resolution_policy.h"
|
||||||
#include "chromecast/media/cdm/cast_cdm_context.h"
|
#include "chromecast/media/cdm/cast_cdm_context.h"
|
||||||
#include "chromecast/media/cma/base/balanced_media_task_runner_factory.h"
|
#include "chromecast/media/cma/base/balanced_media_task_runner_factory.h"
|
||||||
#include "chromecast/media/cma/base/cma_logging.h"
|
#include "chromecast/media/cma/base/cma_logging.h"
|
||||||
@@ -33,21 +34,29 @@ const base::TimeDelta kMaxDeltaFetcher(base::TimeDelta::FromMilliseconds(2000));
|
|||||||
CastRenderer::CastRenderer(
|
CastRenderer::CastRenderer(
|
||||||
const CreateMediaPipelineBackendCB& create_backend_cb,
|
const CreateMediaPipelineBackendCB& create_backend_cb,
|
||||||
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
|
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
|
||||||
const std::string& audio_device_id)
|
const std::string& audio_device_id,
|
||||||
|
VideoResolutionPolicy* video_resolution_policy)
|
||||||
: create_backend_cb_(create_backend_cb),
|
: create_backend_cb_(create_backend_cb),
|
||||||
task_runner_(task_runner),
|
task_runner_(task_runner),
|
||||||
audio_device_id_(audio_device_id),
|
audio_device_id_(audio_device_id),
|
||||||
|
video_resolution_policy_(video_resolution_policy),
|
||||||
client_(nullptr),
|
client_(nullptr),
|
||||||
cast_cdm_context_(nullptr),
|
cast_cdm_context_(nullptr),
|
||||||
media_task_runner_factory_(
|
media_task_runner_factory_(
|
||||||
new BalancedMediaTaskRunnerFactory(kMaxDeltaFetcher)),
|
new BalancedMediaTaskRunnerFactory(kMaxDeltaFetcher)),
|
||||||
weak_factory_(this) {
|
weak_factory_(this) {
|
||||||
CMALOG(kLogControl) << __FUNCTION__ << ": " << this;
|
CMALOG(kLogControl) << __FUNCTION__ << ": " << this;
|
||||||
|
|
||||||
|
if (video_resolution_policy_)
|
||||||
|
video_resolution_policy_->AddObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CastRenderer::~CastRenderer() {
|
CastRenderer::~CastRenderer() {
|
||||||
CMALOG(kLogControl) << __FUNCTION__ << ": " << this;
|
CMALOG(kLogControl) << __FUNCTION__ << ": " << this;
|
||||||
DCHECK(task_runner_->BelongsToCurrentThread());
|
DCHECK(task_runner_->BelongsToCurrentThread());
|
||||||
|
|
||||||
|
if (video_resolution_policy_)
|
||||||
|
video_resolution_policy_->RemoveObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CastRenderer::Initialize(
|
void CastRenderer::Initialize(
|
||||||
@@ -206,6 +215,15 @@ bool CastRenderer::HasVideo() {
|
|||||||
return pipeline_->HasVideo();
|
return pipeline_->HasVideo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CastRenderer::OnVideoResolutionPolicyChanged() {
|
||||||
|
DCHECK(task_runner_->BelongsToCurrentThread());
|
||||||
|
if (!video_resolution_policy_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (video_resolution_policy_->ShouldBlock(video_res_))
|
||||||
|
OnError(::media::PIPELINE_ERROR_DECODE);
|
||||||
|
}
|
||||||
|
|
||||||
void CastRenderer::OnError(::media::PipelineStatus status) {
|
void CastRenderer::OnError(::media::PipelineStatus status) {
|
||||||
DCHECK(task_runner_->BelongsToCurrentThread());
|
DCHECK(task_runner_->BelongsToCurrentThread());
|
||||||
client_->OnError(status);
|
client_->OnError(status);
|
||||||
@@ -240,6 +258,9 @@ void CastRenderer::OnWaitingForDecryptionKey() {
|
|||||||
void CastRenderer::OnVideoNaturalSizeChange(const gfx::Size& size) {
|
void CastRenderer::OnVideoNaturalSizeChange(const gfx::Size& size) {
|
||||||
DCHECK(task_runner_->BelongsToCurrentThread());
|
DCHECK(task_runner_->BelongsToCurrentThread());
|
||||||
client_->OnVideoNaturalSizeChange(size);
|
client_->OnVideoNaturalSizeChange(size);
|
||||||
|
|
||||||
|
video_res_ = size;
|
||||||
|
OnVideoResolutionPolicyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CastRenderer::OnVideoOpacityChange(bool opaque) {
|
void CastRenderer::OnVideoOpacityChange(bool opaque) {
|
||||||
|
@@ -2,8 +2,12 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef CHROMECAST_BROWSER_MEDIA_CAST_RENDERER_H_
|
||||||
|
#define CHROMECAST_BROWSER_MEDIA_CAST_RENDERER_H_
|
||||||
|
|
||||||
#include "base/memory/weak_ptr.h"
|
#include "base/memory/weak_ptr.h"
|
||||||
#include "chromecast/browser/media/media_pipeline_backend_factory.h"
|
#include "chromecast/browser/media/media_pipeline_backend_factory.h"
|
||||||
|
#include "chromecast/browser/media/video_resolution_policy.h"
|
||||||
#include "media/base/renderer.h"
|
#include "media/base/renderer.h"
|
||||||
#include "ui/gfx/geometry/size.h"
|
#include "ui/gfx/geometry/size.h"
|
||||||
|
|
||||||
@@ -23,11 +27,13 @@ class BalancedMediaTaskRunnerFactory;
|
|||||||
class CastCdmContext;
|
class CastCdmContext;
|
||||||
class MediaPipelineImpl;
|
class MediaPipelineImpl;
|
||||||
|
|
||||||
class CastRenderer : public ::media::Renderer {
|
class CastRenderer : public ::media::Renderer,
|
||||||
|
public VideoResolutionPolicy::Observer {
|
||||||
public:
|
public:
|
||||||
CastRenderer(const CreateMediaPipelineBackendCB& create_backend_cb,
|
CastRenderer(const CreateMediaPipelineBackendCB& create_backend_cb,
|
||||||
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
|
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
|
||||||
const std::string& audio_device_id);
|
const std::string& audio_device_id,
|
||||||
|
VideoResolutionPolicy* video_resolution_policy);
|
||||||
~CastRenderer() final;
|
~CastRenderer() final;
|
||||||
|
|
||||||
// ::media::Renderer implementation.
|
// ::media::Renderer implementation.
|
||||||
@@ -44,6 +50,9 @@ class CastRenderer : public ::media::Renderer {
|
|||||||
bool HasAudio() final;
|
bool HasAudio() final;
|
||||||
bool HasVideo() final;
|
bool HasVideo() final;
|
||||||
|
|
||||||
|
// VideoResolutionPolicy::Observer implementation.
|
||||||
|
void OnVideoResolutionPolicyChanged() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Stream { STREAM_AUDIO, STREAM_VIDEO };
|
enum Stream { STREAM_AUDIO, STREAM_VIDEO };
|
||||||
void OnError(::media::PipelineStatus status);
|
void OnError(::media::PipelineStatus status);
|
||||||
@@ -53,16 +62,19 @@ class CastRenderer : public ::media::Renderer {
|
|||||||
void OnWaitingForDecryptionKey();
|
void OnWaitingForDecryptionKey();
|
||||||
void OnVideoNaturalSizeChange(const gfx::Size& size);
|
void OnVideoNaturalSizeChange(const gfx::Size& size);
|
||||||
void OnVideoOpacityChange(bool opaque);
|
void OnVideoOpacityChange(bool opaque);
|
||||||
|
void CheckVideoResolutionPolicy();
|
||||||
|
|
||||||
const CreateMediaPipelineBackendCB create_backend_cb_;
|
const CreateMediaPipelineBackendCB create_backend_cb_;
|
||||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
||||||
std::string audio_device_id_;
|
std::string audio_device_id_;
|
||||||
|
VideoResolutionPolicy* video_resolution_policy_;
|
||||||
::media::RendererClient* client_;
|
::media::RendererClient* client_;
|
||||||
CastCdmContext* cast_cdm_context_;
|
CastCdmContext* cast_cdm_context_;
|
||||||
scoped_refptr<BalancedMediaTaskRunnerFactory> media_task_runner_factory_;
|
scoped_refptr<BalancedMediaTaskRunnerFactory> media_task_runner_factory_;
|
||||||
std::unique_ptr<TaskRunnerImpl> backend_task_runner_;
|
std::unique_ptr<TaskRunnerImpl> backend_task_runner_;
|
||||||
std::unique_ptr<MediaPipelineImpl> pipeline_;
|
std::unique_ptr<MediaPipelineImpl> pipeline_;
|
||||||
bool eos_[2];
|
bool eos_[2];
|
||||||
|
gfx::Size video_res_;
|
||||||
base::WeakPtrFactory<CastRenderer> weak_factory_;
|
base::WeakPtrFactory<CastRenderer> weak_factory_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CastRenderer);
|
DISALLOW_COPY_AND_ASSIGN(CastRenderer);
|
||||||
@@ -70,3 +82,5 @@ class CastRenderer : public ::media::Renderer {
|
|||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
} // namespace chromecast
|
} // namespace chromecast
|
||||||
|
|
||||||
|
#endif // CHROMECAST_BROWSER_MEDIA_CAST_RENDERER_H_
|
||||||
|
13
chromecast/browser/media/video_resolution_policy.cc
Normal file
13
chromecast/browser/media/video_resolution_policy.cc
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2016 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 "chromecast/browser/media/video_resolution_policy.h"
|
||||||
|
|
||||||
|
namespace chromecast {
|
||||||
|
namespace media {
|
||||||
|
|
||||||
|
VideoResolutionPolicy::~VideoResolutionPolicy() {}
|
||||||
|
|
||||||
|
} // namespace media
|
||||||
|
} // namespace chromecast
|
44
chromecast/browser/media/video_resolution_policy.h
Normal file
44
chromecast/browser/media/video_resolution_policy.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2016 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 CHROMECAST_BROWSER_MEDIA_VIDEO_RESOLUTION_POLICY_H_
|
||||||
|
#define CHROMECAST_BROWSER_MEDIA_VIDEO_RESOLUTION_POLICY_H_
|
||||||
|
|
||||||
|
#include "base/macros.h"
|
||||||
|
|
||||||
|
namespace gfx {
|
||||||
|
class Size;
|
||||||
|
} // namespace gfx
|
||||||
|
|
||||||
|
namespace chromecast {
|
||||||
|
namespace media {
|
||||||
|
|
||||||
|
// Interface allowing renderer to check for whether certain video resolutions
|
||||||
|
// should have playback blocked.
|
||||||
|
// TODO(halliwell): remove this mechanism once we have PR3.
|
||||||
|
class VideoResolutionPolicy {
|
||||||
|
public:
|
||||||
|
// Observer allows policy subclass to notify renderer when some
|
||||||
|
// conditions have changed. Renderer should re-check current
|
||||||
|
// resolution.
|
||||||
|
class Observer {
|
||||||
|
public:
|
||||||
|
virtual void OnVideoResolutionPolicyChanged() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~Observer() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~VideoResolutionPolicy();
|
||||||
|
|
||||||
|
virtual void AddObserver(Observer* observer) = 0;
|
||||||
|
virtual void RemoveObserver(Observer* observer) = 0;
|
||||||
|
|
||||||
|
virtual bool ShouldBlock(const gfx::Size& size) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace media
|
||||||
|
} // namespace chromecast
|
||||||
|
|
||||||
|
#endif // CHROMECAST_BROWSER_MEDIA_VIDEO_RESOLUTION_POLICY_H_
|
Reference in New Issue
Block a user