Commit 8dfac453 authored by Thomas Guilbert's avatar Thomas Guilbert Committed by Commit Bot

Add OnRemotePlayStateChange to RendererClient

There is no way for a FlingingRenderer (which corresponds 1:1 with a
video playing remotely on a cast device) to signal to WMPI that an
external device has paused/resumed the video.

This CL adds the necessary plumbing for FlingingRenderer to send state
changes back to media::Pipeline, via the RendererClient interface.

Two follow up CLs are planned: adding OnRemotePlayStateChange to
Pipeline::Client, and adding the logic to keep WMPI's play/pause state
in sync with the externally playing video.

Bug: 790766
Change-Id: I85bb77d85000d7913bc9e7f52048daf527e1c8c7
Reviewed-on: https://chromium-review.googlesource.com/c/1412806Reviewed-by: default avatarKen Buchanan <kenrb@chromium.org>
Reviewed-by: default avatarXiaohan Wang <xhwang@chromium.org>
Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Commit-Queue: Thomas Guilbert <tguilbert@chromium.org>
Auto-Submit: Thomas Guilbert <tguilbert@chromium.org>
Cr-Commit-Position: refs/heads/master@{#625423}
parent 34fbd242
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "base/version.h" #include "base/version.h"
#include "media/base/media_controller.h" #include "media/base/media_controller.h"
#include "media/base/mock_filters.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -27,20 +28,6 @@ class MockMediaController : public media::MediaController { ...@@ -27,20 +28,6 @@ class MockMediaController : public media::MediaController {
MOCK_METHOD1(Seek, void(base::TimeDelta)); MOCK_METHOD1(Seek, void(base::TimeDelta));
}; };
class MockRendererClient : public media::RendererClient {
public:
MOCK_METHOD1(OnError, void(media::PipelineStatus));
MOCK_METHOD0(OnEnded, void());
MOCK_METHOD1(OnStatisticsUpdate, void(const media::PipelineStatistics&));
MOCK_METHOD1(OnBufferingStateChange, void(media::BufferingState));
MOCK_METHOD1(OnWaiting, void(media::WaitingReason));
MOCK_METHOD1(OnAudioConfigChange, void(const media::AudioDecoderConfig&));
MOCK_METHOD1(OnVideoConfigChange, void(const media::VideoDecoderConfig&));
MOCK_METHOD1(OnVideoNaturalSizeChange, void(const gfx::Size&));
MOCK_METHOD1(OnVideoOpacityChange, void(bool));
MOCK_METHOD1(OnDurationChange, void(base::TimeDelta));
};
class MockFlingingController : public media::FlingingController { class MockFlingingController : public media::FlingingController {
public: public:
explicit MockFlingingController(media::MediaController* media_controller) explicit MockFlingingController(media::MediaController* media_controller)
...@@ -72,7 +59,7 @@ class FlingingRendererTest : public testing::Test { ...@@ -72,7 +59,7 @@ class FlingingRendererTest : public testing::Test {
} }
protected: protected:
NiceMock<MockRendererClient> renderer_client_; NiceMock<media::MockRendererClient> renderer_client_;
std::unique_ptr<MockMediaController> media_controller_; std::unique_ptr<MockMediaController> media_controller_;
StrictMock<MockFlingingController>* flinging_controller_; StrictMock<MockFlingingController>* flinging_controller_;
std::unique_ptr<FlingingRenderer> renderer_; std::unique_ptr<FlingingRenderer> renderer_;
......
...@@ -173,4 +173,10 @@ void MediaPlayerRendererClient::OnDurationChange(base::TimeDelta duration) { ...@@ -173,4 +173,10 @@ void MediaPlayerRendererClient::OnDurationChange(base::TimeDelta duration) {
client_->OnDurationChange(duration); client_->OnDurationChange(duration);
} }
void MediaPlayerRendererClient::OnRemotePlayStateChange(
media::MediaStatus::State state) {
// Only used with the FlingingRenderer.
NOTREACHED();
}
} // namespace content } // namespace content
...@@ -68,6 +68,7 @@ class CONTENT_EXPORT MediaPlayerRendererClient : public media::Renderer, ...@@ -68,6 +68,7 @@ class CONTENT_EXPORT MediaPlayerRendererClient : public media::Renderer,
void OnVideoNaturalSizeChange(const gfx::Size& size) override; void OnVideoNaturalSizeChange(const gfx::Size& size) override;
void OnVideoOpacityChange(bool opaque) override; void OnVideoOpacityChange(bool opaque) override;
void OnDurationChange(base::TimeDelta duration) override; void OnDurationChange(base::TimeDelta duration) override;
void OnRemotePlayStateChange(media::MediaStatus::State state) override;
// Called on |compositor_task_runner_| whenever |stream_texture_wrapper_| has // Called on |compositor_task_runner_| whenever |stream_texture_wrapper_| has
// a new frame. // a new frame.
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "media/base/encryption_scheme.h" #include "media/base/encryption_scheme.h"
#include "media/base/hdr_metadata.h" #include "media/base/hdr_metadata.h"
#include "media/base/media_log_event.h" #include "media/base/media_log_event.h"
#include "media/base/media_status.h"
#include "media/base/output_device_info.h" #include "media/base/output_device_info.h"
#include "media/base/overlay_info.h" #include "media/base/overlay_info.h"
#include "media/base/pipeline_status.h" #include "media/base/pipeline_status.h"
...@@ -110,6 +111,9 @@ IPC_ENUM_TRAITS_MAX_VALUE(media::HdcpVersion, ...@@ -110,6 +111,9 @@ IPC_ENUM_TRAITS_MAX_VALUE(media::HdcpVersion,
IPC_ENUM_TRAITS_MAX_VALUE(media::MediaLogEvent::Type, IPC_ENUM_TRAITS_MAX_VALUE(media::MediaLogEvent::Type,
media::MediaLogEvent::TYPE_LAST) media::MediaLogEvent::TYPE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(media::MediaStatus::State,
media::MediaStatus::State::STATE_MAX)
IPC_ENUM_TRAITS_MAX_VALUE(media::OutputDeviceStatus, IPC_ENUM_TRAITS_MAX_VALUE(media::OutputDeviceStatus,
media::OUTPUT_DEVICE_STATUS_MAX) media::OUTPUT_DEVICE_STATUS_MAX)
......
...@@ -16,7 +16,14 @@ namespace media { ...@@ -16,7 +16,14 @@ namespace media {
// TODO(https://crbug.com/820277): Deduplicate media_router::MediaStatus. // TODO(https://crbug.com/820277): Deduplicate media_router::MediaStatus.
struct MEDIA_EXPORT MediaStatus { struct MEDIA_EXPORT MediaStatus {
public: public:
enum class State { UNKNOWN, PLAYING, PAUSED, BUFFERING, STOPPED }; enum class State {
UNKNOWN,
PLAYING,
PAUSED,
BUFFERING,
STOPPED,
STATE_MAX = STOPPED,
};
MediaStatus(); MediaStatus();
MediaStatus(const MediaStatus& other); MediaStatus(const MediaStatus& other);
......
...@@ -263,6 +263,7 @@ class MockRendererClient : public RendererClient { ...@@ -263,6 +263,7 @@ class MockRendererClient : public RendererClient {
MOCK_METHOD1(OnVideoNaturalSizeChange, void(const gfx::Size&)); MOCK_METHOD1(OnVideoNaturalSizeChange, void(const gfx::Size&));
MOCK_METHOD1(OnVideoOpacityChange, void(bool)); MOCK_METHOD1(OnVideoOpacityChange, void(bool));
MOCK_METHOD1(OnDurationChange, void(base::TimeDelta)); MOCK_METHOD1(OnDurationChange, void(base::TimeDelta));
MOCK_METHOD1(OnRemotePlayStateChange, void(MediaStatus::State state));
}; };
class MockVideoRenderer : public VideoRenderer { class MockVideoRenderer : public VideoRenderer {
......
...@@ -138,6 +138,7 @@ class PipelineImpl::RendererWrapper : public DemuxerHost, ...@@ -138,6 +138,7 @@ class PipelineImpl::RendererWrapper : public DemuxerHost,
void OnVideoNaturalSizeChange(const gfx::Size& size) final; void OnVideoNaturalSizeChange(const gfx::Size& size) final;
void OnVideoOpacityChange(bool opaque) final; void OnVideoOpacityChange(bool opaque) final;
void OnDurationChange(base::TimeDelta duration) final; void OnDurationChange(base::TimeDelta duration) final;
void OnRemotePlayStateChange(MediaStatus::State state) final;
// Common handlers for notifications from renderers and demuxer. // Common handlers for notifications from renderers and demuxer.
void OnPipelineError(PipelineStatus error); void OnPipelineError(PipelineStatus error);
...@@ -767,6 +768,13 @@ void PipelineImpl::RendererWrapper::OnDurationChange(base::TimeDelta duration) { ...@@ -767,6 +768,13 @@ void PipelineImpl::RendererWrapper::OnDurationChange(base::TimeDelta duration) {
SetDuration(duration); SetDuration(duration);
} }
void PipelineImpl::RendererWrapper::OnRemotePlayStateChange(
MediaStatus::State state) {
DCHECK(media_task_runner_->BelongsToCurrentThread());
// TODO(tguilbert): post change to Pipeline
}
void PipelineImpl::RendererWrapper::OnPipelineError(PipelineStatus error) { void PipelineImpl::RendererWrapper::OnPipelineError(PipelineStatus error) {
DCHECK(media_task_runner_->BelongsToCurrentThread()); DCHECK(media_task_runner_->BelongsToCurrentThread());
DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!";
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "media/base/audio_decoder_config.h" #include "media/base/audio_decoder_config.h"
#include "media/base/media_status.h"
#include "media/base/pipeline_status.h" #include "media/base/pipeline_status.h"
#include "media/base/video_decoder_config.h" #include "media/base/video_decoder_config.h"
#include "media/base/waiting.h" #include "media/base/waiting.h"
...@@ -49,6 +50,12 @@ class RendererClient { ...@@ -49,6 +50,12 @@ class RendererClient {
// Executed when video metadata is first read, and whenever it changes. // Executed when video metadata is first read, and whenever it changes.
// Only used when we are using a URL demuxer (e.g. for MediaPlayerRenderer). // Only used when we are using a URL demuxer (e.g. for MediaPlayerRenderer).
virtual void OnDurationChange(base::TimeDelta duration) = 0; virtual void OnDurationChange(base::TimeDelta duration) = 0;
// Executed when the status of a video playing remotely is changed, without
// the change originating from the media::Pipeline that owns |this|.
// Only used with the FlingingRenderer, when an external device play/pauses
// videos, and WMPI needs to be updated accordingly.
virtual void OnRemotePlayStateChange(media::MediaStatus::State state) = 0;
}; };
} // namespace media } // namespace media
......
...@@ -282,6 +282,11 @@ void MojoRenderer::OnDurationChange(base::TimeDelta duration) { ...@@ -282,6 +282,11 @@ void MojoRenderer::OnDurationChange(base::TimeDelta duration) {
client_->OnDurationChange(duration); client_->OnDurationChange(duration);
} }
void MojoRenderer::OnRemotePlayStateChange(media::MediaStatus::State state) {
DVLOG(2) << __func__ << ": state" << (int)state;
client_->OnRemotePlayStateChange(state);
}
void MojoRenderer::OnVideoOpacityChange(bool opaque) { void MojoRenderer::OnVideoOpacityChange(bool opaque) {
DVLOG(2) << __func__ << ": " << opaque; DVLOG(2) << __func__ << ": " << opaque;
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
......
...@@ -85,6 +85,7 @@ class MojoRenderer : public Renderer, public mojom::RendererClient { ...@@ -85,6 +85,7 @@ class MojoRenderer : public Renderer, public mojom::RendererClient {
void OnWaiting(WaitingReason reason) override; void OnWaiting(WaitingReason reason) override;
void OnStatisticsUpdate(const PipelineStatistics& stats) override; void OnStatisticsUpdate(const PipelineStatistics& stats) override;
void OnDurationChange(base::TimeDelta duration) override; void OnDurationChange(base::TimeDelta duration) override;
void OnRemotePlayStateChange(media::MediaStatus::State state) override;
// Binds |remote_renderer_| to the mojo message pipe. Can be called multiple // Binds |remote_renderer_| to the mojo message pipe. Can be called multiple
// times. If an error occurs during connection, OnConnectionError will be // times. If an error occurs during connection, OnConnectionError will be
......
...@@ -78,6 +78,10 @@ enum EncryptionMode; ...@@ -78,6 +78,10 @@ enum EncryptionMode;
[Native] [Native]
enum MediaContainerName; enum MediaContainerName;
// See media/base/media_status.h for description.
[Native]
enum MediaStatusState;
// This defines a mojo transport format for media::EncryptionPattern // This defines a mojo transport format for media::EncryptionPattern
// See media/base/encryption_pattern.h for description. // See media/base/encryption_pattern.h for description.
struct EncryptionPattern { struct EncryptionPattern {
......
...@@ -15,6 +15,7 @@ public_headers = [ ...@@ -15,6 +15,7 @@ public_headers = [
"//media/base/encryption_scheme.h", "//media/base/encryption_scheme.h",
"//media/base/hdr_metadata.h", "//media/base/hdr_metadata.h",
"//media/base/media_log_event.h", "//media/base/media_log_event.h",
"//media/base/media_status.h",
"//media/base/output_device_info.h", "//media/base/output_device_info.h",
"//media/base/pipeline_status.h", "//media/base/pipeline_status.h",
"//media/base/sample_format.h", "//media/base/sample_format.h",
...@@ -57,4 +58,5 @@ type_mappings = [ ...@@ -57,4 +58,5 @@ type_mappings = [
"media.mojom.WaitingReason=media::WaitingReason", "media.mojom.WaitingReason=media::WaitingReason",
"media.mojom.WatchTimeKey=media::WatchTimeKey", "media.mojom.WatchTimeKey=media::WatchTimeKey",
"media.mojom.EncryptionPattern=media::EncryptionPattern", "media.mojom.EncryptionPattern=media::EncryptionPattern",
"media.mojom.MediaStatusState=media::MediaStatus::State",
] ]
...@@ -94,4 +94,10 @@ interface RendererClient { ...@@ -94,4 +94,10 @@ interface RendererClient {
// Executed the first time the metadata is updated, and whenever the duration // Executed the first time the metadata is updated, and whenever the duration
// changes. // changes.
OnDurationChange(mojo_base.mojom.TimeDelta duration); OnDurationChange(mojo_base.mojom.TimeDelta duration);
// Executed whenever a renderer receives notification of a status change that
// was not originated by its owner.
// Only used with the FlingingRenderer (when external devices play/pause the
// video playing remotely).
OnRemotePlayStateChange(MediaStatusState state);
}; };
...@@ -108,6 +108,7 @@ class MockRendererClient : public mojom::RendererClient { ...@@ -108,6 +108,7 @@ class MockRendererClient : public mojom::RendererClient {
void(const media::PipelineStatistics& stats)); void(const media::PipelineStatistics& stats));
MOCK_METHOD1(OnWaiting, void(WaitingReason)); MOCK_METHOD1(OnWaiting, void(WaitingReason));
MOCK_METHOD1(OnDurationChange, void(base::TimeDelta duration)); MOCK_METHOD1(OnDurationChange, void(base::TimeDelta duration));
MOCK_METHOD1(OnRemotePlayStateChange, void(MediaStatus::State state));
private: private:
DISALLOW_COPY_AND_ASSIGN(MockRendererClient); DISALLOW_COPY_AND_ASSIGN(MockRendererClient);
......
...@@ -195,6 +195,10 @@ void MojoRendererService::OnDurationChange(base::TimeDelta duration) { ...@@ -195,6 +195,10 @@ void MojoRendererService::OnDurationChange(base::TimeDelta duration) {
client_->OnDurationChange(duration); client_->OnDurationChange(duration);
} }
void MojoRendererService::OnRemotePlayStateChange(MediaStatus::State state) {
client_->OnRemotePlayStateChange(state);
}
void MojoRendererService::OnVideoOpacityChange(bool opaque) { void MojoRendererService::OnVideoOpacityChange(bool opaque) {
DVLOG(2) << __func__ << "(" << opaque << ")"; DVLOG(2) << __func__ << "(" << opaque << ")";
client_->OnVideoOpacityChange(opaque); client_->OnVideoOpacityChange(opaque);
......
...@@ -92,6 +92,7 @@ class MEDIA_MOJO_EXPORT MojoRendererService : public mojom::Renderer, ...@@ -92,6 +92,7 @@ class MEDIA_MOJO_EXPORT MojoRendererService : public mojom::Renderer,
void OnVideoNaturalSizeChange(const gfx::Size& size) final; void OnVideoNaturalSizeChange(const gfx::Size& size) final;
void OnVideoOpacityChange(bool opaque) final; void OnVideoOpacityChange(bool opaque) final;
void OnDurationChange(base::TimeDelta duration) final; void OnDurationChange(base::TimeDelta duration) final;
void OnRemotePlayStateChange(MediaStatus::State state) final;
// Called when the MediaResourceShim is ready to go (has a config, // Called when the MediaResourceShim is ready to go (has a config,
// pipe handle, etc) and can be handed off to a renderer for use. // pipe handle, etc) and can be handed off to a renderer for use.
......
...@@ -92,6 +92,7 @@ class RendererClientImpl final : public RendererClient { ...@@ -92,6 +92,7 @@ class RendererClientImpl final : public RendererClient {
MOCK_METHOD1(OnVideoNaturalSizeChange, void(const gfx::Size& size)); MOCK_METHOD1(OnVideoNaturalSizeChange, void(const gfx::Size& size));
MOCK_METHOD1(OnVideoOpacityChange, void(bool opaque)); MOCK_METHOD1(OnVideoOpacityChange, void(bool opaque));
MOCK_METHOD1(OnDurationChange, void(base::TimeDelta duration)); MOCK_METHOD1(OnDurationChange, void(base::TimeDelta duration));
MOCK_METHOD1(OnRemotePlayStateChange, void(MediaStatus::State state));
void DelegateOnStatisticsUpdate(const PipelineStatistics& stats) { void DelegateOnStatisticsUpdate(const PipelineStatistics& stats) {
stats_ = stats; stats_ = stats;
......
...@@ -326,5 +326,10 @@ void Receiver::OnDurationChange(base::TimeDelta duration) { ...@@ -326,5 +326,10 @@ void Receiver::OnDurationChange(base::TimeDelta duration) {
rpc_broker_->SendMessageToRemote(std::move(rpc)); rpc_broker_->SendMessageToRemote(std::move(rpc));
} }
void Receiver::OnRemotePlayStateChange(MediaStatus::State state) {
// Only used with the FlingingRenderer.
NOTREACHED();
}
} // namespace remoting } // namespace remoting
} // namespace media } // namespace media
...@@ -41,6 +41,7 @@ class Receiver final : public RendererClient { ...@@ -41,6 +41,7 @@ class Receiver final : public RendererClient {
void OnVideoNaturalSizeChange(const gfx::Size& size) override; void OnVideoNaturalSizeChange(const gfx::Size& size) override;
void OnVideoOpacityChange(bool opaque) override; void OnVideoOpacityChange(bool opaque) override;
void OnDurationChange(base::TimeDelta duration) override; void OnDurationChange(base::TimeDelta duration) override;
void OnRemotePlayStateChange(MediaStatus::State state) override;
void OnReceivedRpc(std::unique_ptr<pb::RpcMessage> message); void OnReceivedRpc(std::unique_ptr<pb::RpcMessage> message);
void OnReceivedBuffer(DemuxerStream::Type type, void OnReceivedBuffer(DemuxerStream::Type type,
......
...@@ -194,6 +194,7 @@ class AudioRendererImplTest : public ::testing::Test, public RendererClient { ...@@ -194,6 +194,7 @@ class AudioRendererImplTest : public ::testing::Test, public RendererClient {
MOCK_METHOD1(OnVideoNaturalSizeChange, void(const gfx::Size&)); MOCK_METHOD1(OnVideoNaturalSizeChange, void(const gfx::Size&));
MOCK_METHOD1(OnVideoOpacityChange, void(bool)); MOCK_METHOD1(OnVideoOpacityChange, void(bool));
MOCK_METHOD1(OnDurationChange, void(base::TimeDelta)); MOCK_METHOD1(OnDurationChange, void(base::TimeDelta));
MOCK_METHOD1(OnRemotePlayStateChange, void(MediaStatus::State state));
void InitializeRenderer(DemuxerStream* demuxer_stream, void InitializeRenderer(DemuxerStream* demuxer_stream,
const PipelineStatusCB& pipeline_status_cb) { const PipelineStatusCB& pipeline_status_cb) {
......
...@@ -72,6 +72,10 @@ class RendererImpl::RendererClientInternal final : public RendererClient { ...@@ -72,6 +72,10 @@ class RendererImpl::RendererClientInternal final : public RendererClient {
// the DemuxerHost interface. // the DemuxerHost interface.
NOTREACHED(); NOTREACHED();
} }
void OnRemotePlayStateChange(MediaStatus::State state) override {
// Only used with FlingingRenderer.
NOTREACHED();
}
private: private:
DemuxerStream::Type type_; DemuxerStream::Type type_;
......
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