0

[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:
halliwell
2016-08-29 23:24:02 -07:00
committed by Commit bot
parent 6f3528e034
commit f5a81bb909
9 changed files with 119 additions and 8 deletions

@ -82,7 +82,8 @@ static std::unique_ptr<::shell::Service> CreateMojoMediaApplication(
base::Bind(&CastContentBrowserClient::CreateMediaPipelineBackend,
base::Unretained(browser_client)),
base::Bind(&CastContentBrowserClient::CreateCdmFactory,
base::Unretained(browser_client))));
base::Unretained(browser_client)),
browser_client->GetVideoResolutionPolicy()));
return std::unique_ptr<::shell::Service>(
new ::media::MojoMediaApplication(std::move(mojo_media_client),
quit_closure));
@ -132,6 +133,11 @@ std::unique_ptr<CastService> CastContentBrowserClient::CreateCastService(
}
#if !defined(OS_ANDROID)
media::VideoResolutionPolicy*
CastContentBrowserClient::GetVideoResolutionPolicy() {
return nullptr;
}
scoped_refptr<base::SingleThreadTaskRunner>
CastContentBrowserClient::GetMediaTaskRunner() {
DCHECK(cast_browser_main_parts_);

@ -43,6 +43,7 @@ class MediaPipelineBackendManager;
struct MediaPipelineDeviceParams;
class MediaResourceTracker;
class VideoPlaneController;
class VideoResolutionPolicy;
}
namespace shell {
@ -74,6 +75,9 @@ class CastContentBrowserClient : public content::ContentBrowserClient {
media::VideoPlaneController* video_plane_controller);
#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.
scoped_refptr<base::SingleThreadTaskRunner> GetMediaTaskRunner();

@ -47,6 +47,8 @@ source_set("media") {
sources += [
"cma_message_filter_host.cc",
"cma_message_filter_host.h",
"video_resolution_policy.cc",
"video_resolution_policy.h",
]
}
}

@ -15,9 +15,11 @@ namespace media {
CastMojoMediaClient::CastMojoMediaClient(
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_cdm_factory_cb_(create_cdm_factory_cb) {}
create_cdm_factory_cb_(create_cdm_factory_cb),
video_resolution_policy_(video_resolution_policy) {}
CastMojoMediaClient::~CastMojoMediaClient() {}
@ -26,7 +28,8 @@ std::unique_ptr<::media::Renderer> CastMojoMediaClient::CreateRenderer(
scoped_refptr<::media::MediaLog> media_log,
const std::string& audio_device_id) {
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(

@ -11,13 +11,16 @@
namespace chromecast {
namespace media {
class VideoResolutionPolicy;
class CastMojoMediaClient : public ::media::MojoMediaClient {
public:
using CreateCdmFactoryCB =
base::Callback<std::unique_ptr<::media::CdmFactory>()>;
CastMojoMediaClient(const CreateMediaPipelineBackendCB& create_backend_cb,
const CreateCdmFactoryCB& create_cdm_factory_cb);
const CreateCdmFactoryCB& create_cdm_factory_cb,
VideoResolutionPolicy* video_resolution_policy);
~CastMojoMediaClient() override;
// MojoMediaClient overrides.
@ -31,6 +34,7 @@ class CastMojoMediaClient : public ::media::MojoMediaClient {
private:
const CreateMediaPipelineBackendCB create_backend_cb_;
const CreateCdmFactoryCB create_cdm_factory_cb_;
VideoResolutionPolicy* video_resolution_policy_;
DISALLOW_COPY_AND_ASSIGN(CastMojoMediaClient);
};

@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/single_thread_task_runner.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/cma/base/balanced_media_task_runner_factory.h"
#include "chromecast/media/cma/base/cma_logging.h"
@ -33,21 +34,29 @@ const base::TimeDelta kMaxDeltaFetcher(base::TimeDelta::FromMilliseconds(2000));
CastRenderer::CastRenderer(
const CreateMediaPipelineBackendCB& create_backend_cb,
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),
task_runner_(task_runner),
audio_device_id_(audio_device_id),
video_resolution_policy_(video_resolution_policy),
client_(nullptr),
cast_cdm_context_(nullptr),
media_task_runner_factory_(
new BalancedMediaTaskRunnerFactory(kMaxDeltaFetcher)),
weak_factory_(this) {
CMALOG(kLogControl) << __FUNCTION__ << ": " << this;
if (video_resolution_policy_)
video_resolution_policy_->AddObserver(this);
}
CastRenderer::~CastRenderer() {
CMALOG(kLogControl) << __FUNCTION__ << ": " << this;
DCHECK(task_runner_->BelongsToCurrentThread());
if (video_resolution_policy_)
video_resolution_policy_->RemoveObserver(this);
}
void CastRenderer::Initialize(
@ -206,6 +215,15 @@ bool CastRenderer::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) {
DCHECK(task_runner_->BelongsToCurrentThread());
client_->OnError(status);
@ -240,6 +258,9 @@ void CastRenderer::OnWaitingForDecryptionKey() {
void CastRenderer::OnVideoNaturalSizeChange(const gfx::Size& size) {
DCHECK(task_runner_->BelongsToCurrentThread());
client_->OnVideoNaturalSizeChange(size);
video_res_ = size;
OnVideoResolutionPolicyChanged();
}
void CastRenderer::OnVideoOpacityChange(bool opaque) {

@ -2,8 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// 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 "chromecast/browser/media/media_pipeline_backend_factory.h"
#include "chromecast/browser/media/video_resolution_policy.h"
#include "media/base/renderer.h"
#include "ui/gfx/geometry/size.h"
@ -23,11 +27,13 @@ class BalancedMediaTaskRunnerFactory;
class CastCdmContext;
class MediaPipelineImpl;
class CastRenderer : public ::media::Renderer {
class CastRenderer : public ::media::Renderer,
public VideoResolutionPolicy::Observer {
public:
CastRenderer(const CreateMediaPipelineBackendCB& create_backend_cb,
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;
// ::media::Renderer implementation.
@ -44,6 +50,9 @@ class CastRenderer : public ::media::Renderer {
bool HasAudio() final;
bool HasVideo() final;
// VideoResolutionPolicy::Observer implementation.
void OnVideoResolutionPolicyChanged() override;
private:
enum Stream { STREAM_AUDIO, STREAM_VIDEO };
void OnError(::media::PipelineStatus status);
@ -53,16 +62,19 @@ class CastRenderer : public ::media::Renderer {
void OnWaitingForDecryptionKey();
void OnVideoNaturalSizeChange(const gfx::Size& size);
void OnVideoOpacityChange(bool opaque);
void CheckVideoResolutionPolicy();
const CreateMediaPipelineBackendCB create_backend_cb_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
std::string audio_device_id_;
VideoResolutionPolicy* video_resolution_policy_;
::media::RendererClient* client_;
CastCdmContext* cast_cdm_context_;
scoped_refptr<BalancedMediaTaskRunnerFactory> media_task_runner_factory_;
std::unique_ptr<TaskRunnerImpl> backend_task_runner_;
std::unique_ptr<MediaPipelineImpl> pipeline_;
bool eos_[2];
gfx::Size video_res_;
base::WeakPtrFactory<CastRenderer> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CastRenderer);
@ -70,3 +82,5 @@ class CastRenderer : public ::media::Renderer {
} // namespace media
} // namespace chromecast
#endif // CHROMECAST_BROWSER_MEDIA_CAST_RENDERER_H_

@ -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

@ -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_