| Index: media/remoting/receiver.cc | 
| diff --git a/media/remoting/receiver.cc b/media/remoting/receiver.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..90dd78b2791bd045dfc9653347043a24605503b2 | 
| --- /dev/null | 
| +++ b/media/remoting/receiver.cc | 
| @@ -0,0 +1,304 @@ | 
| +// 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/remoting/receiver.h" | 
| + | 
| +#include "base/bind.h" | 
| +#include "base/callback.h" | 
| +#include "media/base/decoder_buffer.h" | 
| +#include "media/base/renderer.h" | 
| +#include "media/remoting/proto_enum_utils.h" | 
| +#include "media/remoting/stream_provider.h" | 
| + | 
| +namespace media { | 
| +namespace remoting { | 
| +namespace { | 
| + | 
| +// The period to send the TimeUpdate RPC message to update the media time on | 
| +// sender side. | 
| +constexpr base::TimeDelta kTimeUpdateInterval = | 
| +    base::TimeDelta::FromMilliseconds(250); | 
| + | 
| +}  // namespace | 
| + | 
| +Receiver::Receiver(std::unique_ptr<Renderer> renderer, RpcBroker* rpc_broker) | 
| +    : renderer_(std::move(renderer)), | 
| +      rpc_broker_(rpc_broker), | 
| +      rpc_handle_(rpc_broker_->GetUniqueHandle()), | 
| +      weak_factory_(this) { | 
| +  DCHECK(renderer_); | 
| +  DCHECK(rpc_broker_); | 
| +  rpc_broker_->RegisterMessageReceiverCallback( | 
| +      rpc_handle_, | 
| +      base::Bind(&Receiver::OnReceivedRpc, weak_factory_.GetWeakPtr())); | 
| +  rpc_broker_->RegisterMessageReceiverCallback( | 
| +      RpcBroker::kAcquireHandle, | 
| +      base::Bind(&Receiver::OnReceivedRpc, weak_factory_.GetWeakPtr())); | 
| +} | 
| + | 
| +Receiver::~Receiver() { | 
| +  rpc_broker_->UnregisterMessageReceiverCallback(rpc_handle_); | 
| +  rpc_broker_->UnregisterMessageReceiverCallback(RpcBroker::kAcquireHandle); | 
| +} | 
| + | 
| +void Receiver::OnReceivedRpc(std::unique_ptr<pb::RpcMessage> message) { | 
| +  DCHECK(message); | 
| +  switch (message->proc()) { | 
| +    case pb::RpcMessage::RPC_ACQUIRE_RENDERER: | 
| +      AcquireRenderer(std::move(message)); | 
| +      break; | 
| +    case pb::RpcMessage::RPC_R_FLUSHUNTIL: | 
| +      FlushUntil(std::move(message)); | 
| +      break; | 
| +    case pb::RpcMessage::RPC_R_STARTPLAYINGFROM: | 
| +      StartPlayingFrom(std::move(message)); | 
| +      break; | 
| +    case pb::RpcMessage::RPC_R_SETPLAYBACKRATE: | 
| +      SetPlaybackRate(std::move(message)); | 
| +      break; | 
| +    case pb::RpcMessage::RPC_R_SETVOLUME: | 
| +      SetVolume(std::move(message)); | 
| +      break; | 
| +    case pb::RpcMessage::RPC_R_INITIALIZE: | 
| +      Initialize(std::move(message)); | 
| +      break; | 
| +    default: | 
| +      VLOG(1) << __func__ << ": Unknow RPC message. proc=" << message->proc(); | 
| +  } | 
| +} | 
| + | 
| +void Receiver::AcquireRenderer(std::unique_ptr<pb::RpcMessage> message) { | 
| +  DVLOG(3) << __func__ << ": Receives RPC_ACQUIRE_RENDERER with remote_handle= " | 
| +           << message->integer_value(); | 
| + | 
| +  remote_handle_ = message->integer_value(); | 
| +  if (stream_provider_) { | 
| +    VLOG(1) << "Acquire renderer error: Already aquired."; | 
| +    OnError(PipelineStatus::PIPELINE_ERROR_DECODE); | 
| +    return; | 
| +  } | 
| + | 
| +  stream_provider_.reset(new StreamProvider( | 
| +      rpc_broker_, base::Bind(&Receiver::OnError, weak_factory_.GetWeakPtr(), | 
| +                              PipelineStatus::PIPELINE_ERROR_DECODE))); | 
| + | 
| +  DVLOG(3) << __func__ | 
| +           << ": Issues RPC_ACQUIRE_RENDERER_DONE RPC message. remote_handle=" | 
| +           << remote_handle_ << " rpc_handle=" << rpc_handle_; | 
| +  std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | 
| +  rpc->set_handle(remote_handle_); | 
| +  rpc->set_proc(pb::RpcMessage::RPC_ACQUIRE_RENDERER_DONE); | 
| +  rpc->set_integer_value(rpc_handle_); | 
| +  rpc_broker_->SendMessageToRemote(std::move(rpc)); | 
| +} | 
| + | 
| +void Receiver::Initialize(std::unique_ptr<pb::RpcMessage> message) { | 
| +  DCHECK(stream_provider_); | 
| +  DVLOG(3) << __func__ << ": Receives RPC_R_INITIALIZE with callback handle= " | 
| +           << message->renderer_initialize_rpc().callback_handle(); | 
| +  DCHECK(message->renderer_initialize_rpc().callback_handle() == | 
| +         remote_handle_); | 
| +  if (!stream_provider_) | 
| +    OnRendererInitialized(PipelineStatus::PIPELINE_ERROR_INITIALIZATION_FAILED); | 
| + | 
| +  stream_provider_->Initialize( | 
| +      message->renderer_initialize_rpc().audio_demuxer_handle(), | 
| +      message->renderer_initialize_rpc().video_demuxer_handle(), | 
| +      base::Bind(&Receiver::OnStreamInitialized, weak_factory_.GetWeakPtr())); | 
| +} | 
| + | 
| +void Receiver::OnStreamInitialized() { | 
| +  DCHECK(stream_provider_); | 
| +  renderer_->Initialize( | 
| +      stream_provider_.get(), this, | 
| +      base::Bind(&Receiver::OnRendererInitialized, weak_factory_.GetWeakPtr())); | 
| +} | 
| + | 
| +void Receiver::OnRendererInitialized(PipelineStatus status) { | 
| +  DVLOG(3) << __func__ << ": Issues RPC_R_INITIALIZE_CALLBACK RPC message." | 
| +           << "remote_handle=" << remote_handle_; | 
| + | 
| +  std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | 
| +  rpc->set_handle(remote_handle_); | 
| +  rpc->set_proc(pb::RpcMessage::RPC_R_INITIALIZE_CALLBACK); | 
| +  rpc->set_boolean_value(status == PIPELINE_OK); | 
| +  rpc_broker_->SendMessageToRemote(std::move(rpc)); | 
| +} | 
| + | 
| +void Receiver::SetPlaybackRate(std::unique_ptr<pb::RpcMessage> message) { | 
| +  const double playback_rate = message->double_value(); | 
| +  DVLOG(3) << __func__ | 
| +           << ": Receives RPC_R_SETPLAYBACKRATE with rate=" << playback_rate; | 
| +  renderer_->SetPlaybackRate(playback_rate); | 
| + | 
| +  if (playback_rate == 0.0) { | 
| +    if (time_update_timer_.IsRunning()) { | 
| +      time_update_timer_.Stop(); | 
| +      // Send one final media time update since the sender will not get any | 
| +      // until playback resumes. | 
| +      SendMediaTimeUpdate(); | 
| +    } | 
| +  } else { | 
| +    ScheduleMediaTimeUpdates(); | 
| +  } | 
| +} | 
| + | 
| +void Receiver::FlushUntil(std::unique_ptr<pb::RpcMessage> message) { | 
| +  DVLOG(3) << __func__ << ": Receives RPC_R_FLUSHUNTIL RPC message."; | 
| + | 
| +  const pb::RendererFlushUntil flush_message = | 
| +      message->renderer_flushuntil_rpc(); | 
| +  DCHECK_EQ(flush_message.callback_handle(), remote_handle_); | 
| +  if (stream_provider_) { | 
| +    if (flush_message.has_audio_count()) { | 
| +      stream_provider_->FlushUntil(DemuxerStream::AUDIO, | 
| +                                   flush_message.audio_count()); | 
| +    } | 
| +    if (flush_message.has_video_count()) { | 
| +      stream_provider_->FlushUntil(DemuxerStream::VIDEO, | 
| +                                   flush_message.video_count()); | 
| +    } | 
| +  } | 
| +  time_update_timer_.Stop(); | 
| +  renderer_->Flush( | 
| +      base::Bind(&Receiver::OnFlushDone, weak_factory_.GetWeakPtr())); | 
| +} | 
| + | 
| +void Receiver::OnFlushDone() { | 
| +  DVLOG(3) << __func__ << ": Issues RPC_R_FLUSHUNTIL_CALLBACK RPC message."; | 
| + | 
| +  std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | 
| +  rpc->set_handle(remote_handle_); | 
| +  rpc->set_proc(pb::RpcMessage::RPC_R_FLUSHUNTIL_CALLBACK); | 
| +  rpc_broker_->SendMessageToRemote(std::move(rpc)); | 
| +} | 
| + | 
| +void Receiver::StartPlayingFrom(std::unique_ptr<pb::RpcMessage> message) { | 
| +  DVLOG(3) << __func__ << ": Receives RPC_R_STARTPLAYINGFROM message."; | 
| +  base::TimeDelta time = | 
| +      base::TimeDelta::FromMicroseconds(message->integer64_value()); | 
| +  renderer_->StartPlayingFrom(time); | 
| +  ScheduleMediaTimeUpdates(); | 
| +} | 
| + | 
| +void Receiver::ScheduleMediaTimeUpdates() { | 
| +  if (time_update_timer_.IsRunning()) | 
| +    return; | 
| +  SendMediaTimeUpdate(); | 
| +  time_update_timer_.Start( | 
| +      FROM_HERE, kTimeUpdateInterval, | 
| +      base::Bind(&Receiver::SendMediaTimeUpdate, weak_factory_.GetWeakPtr())); | 
| +} | 
| + | 
| +void Receiver::SetVolume(std::unique_ptr<pb::RpcMessage> message) { | 
| +  DVLOG(3) << __func__ << ": Receives RPC_R_SETVOLUME message."; | 
| +  renderer_->SetVolume(message->double_value()); | 
| +} | 
| + | 
| +void Receiver::SendMediaTimeUpdate() { | 
| +  // Issues RPC_RC_ONTIMEUPDATE RPC message. | 
| +  std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | 
| +  rpc->set_handle(remote_handle_); | 
| +  rpc->set_proc(pb::RpcMessage::RPC_RC_ONTIMEUPDATE); | 
| +  auto* message = rpc->mutable_rendererclient_ontimeupdate_rpc(); | 
| +  base::TimeDelta media_time = renderer_->GetMediaTime(); | 
| +  message->set_time_usec(media_time.InMicroseconds()); | 
| +  base::TimeDelta max_time = media_time; | 
| +  message->set_max_time_usec(max_time.InMicroseconds()); | 
| +  DVLOG(3) << __func__ << ": Issues RPC_RC_ONTIMEUPDATE message." | 
| +           << " media_time = " << media_time.InMicroseconds() | 
| +           << " max_time= " << max_time.InMicroseconds(); | 
| +  rpc_broker_->SendMessageToRemote(std::move(rpc)); | 
| +} | 
| + | 
| +void Receiver::OnReceivedBuffer(DemuxerStream::Type type, | 
| +                                scoped_refptr<DecoderBuffer> buffer) { | 
| +  DVLOG(3) << __func__ | 
| +           << ": type=" << (type == DemuxerStream::AUDIO ? "Audio" : "Video"); | 
| +  DCHECK(stream_provider_); | 
| +  stream_provider_->AppendBuffer(type, buffer); | 
| +} | 
| + | 
| +void Receiver::OnError(PipelineStatus status) { | 
| +  VLOG(1) << __func__ << ": Issues RPC_RC_ONERROR message."; | 
| +  std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | 
| +  rpc->set_handle(remote_handle_); | 
| +  rpc->set_proc(pb::RpcMessage::RPC_RC_ONERROR); | 
| +  rpc_broker_->SendMessageToRemote(std::move(rpc)); | 
| +} | 
| + | 
| +void Receiver::OnEnded() { | 
| +  DVLOG(3) << __func__ << ": Issues RPC_RC_ONENDED message."; | 
| +  std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | 
| +  rpc->set_handle(remote_handle_); | 
| +  rpc->set_proc(pb::RpcMessage::RPC_RC_ONENDED); | 
| +  rpc_broker_->SendMessageToRemote(std::move(rpc)); | 
| +  time_update_timer_.Stop(); | 
| +} | 
| + | 
| +void Receiver::OnStatisticsUpdate(const PipelineStatistics& stats) { | 
| +  DVLOG(3) << __func__ << ": Issues RPC_RC_ONSTATISTICSUPDATE message."; | 
| +  std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | 
| +  rpc->set_handle(remote_handle_); | 
| +  rpc->set_proc(pb::RpcMessage::RPC_RC_ONSTATISTICSUPDATE); | 
| +  auto* message = rpc->mutable_rendererclient_onstatisticsupdate_rpc(); | 
| +  message->set_audio_bytes_decoded(stats.audio_bytes_decoded); | 
| +  message->set_video_bytes_decoded(stats.video_bytes_decoded); | 
| +  message->set_video_frames_decoded(stats.video_frames_decoded); | 
| +  message->set_video_frames_dropped(stats.video_frames_dropped); | 
| +  message->set_audio_memory_usage(stats.audio_memory_usage); | 
| +  message->set_video_memory_usage(stats.video_memory_usage); | 
| +  rpc_broker_->SendMessageToRemote(std::move(rpc)); | 
| +} | 
| + | 
| +void Receiver::OnBufferingStateChange(BufferingState state) { | 
| +  DVLOG(3) << __func__ | 
| +           << ": Issues RPC_RC_ONBUFFERINGSTATECHANGE message: state=" << state; | 
| +  std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | 
| +  rpc->set_handle(remote_handle_); | 
| +  rpc->set_proc(pb::RpcMessage::RPC_RC_ONBUFFERINGSTATECHANGE); | 
| +  auto* message = rpc->mutable_rendererclient_onbufferingstatechange_rpc(); | 
| +  message->set_state(ToProtoMediaBufferingState(state).value()); | 
| +  rpc_broker_->SendMessageToRemote(std::move(rpc)); | 
| +} | 
| + | 
| +void Receiver::OnWaitingForDecryptionKey() { | 
| +  DVLOG(3) << __func__ << ": Issues RPC_RC_ONWAITINGFORDECRYPTIONKEY message."; | 
| +  std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | 
| +  rpc->set_handle(remote_handle_); | 
| +  rpc->set_proc(pb::RpcMessage::RPC_RC_ONWAITINGFORDECRYPTIONKEY); | 
| +  rpc_broker_->SendMessageToRemote(std::move(rpc)); | 
| +} | 
| + | 
| +void Receiver::OnVideoNaturalSizeChange(const gfx::Size& size) { | 
| +  DVLOG(3) << __func__ << ": Issues RPC_RC_ONVIDEONATURALSIZECHANGE message."; | 
| +  std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | 
| +  rpc->set_handle(remote_handle_); | 
| +  rpc->set_proc(pb::RpcMessage::RPC_RC_ONVIDEONATURALSIZECHANGE); | 
| +  auto* message = rpc->mutable_rendererclient_onvideonatualsizechange_rpc(); | 
| +  message->set_width(size.width()); | 
| +  message->set_height(size.height()); | 
| +  rpc_broker_->SendMessageToRemote(std::move(rpc)); | 
| +} | 
| + | 
| +void Receiver::OnVideoOpacityChange(bool opaque) { | 
| +  DVLOG(3) << __func__ << ": Issues RPC_RC_ONVIDEOOPACITYCHANGE message."; | 
| +  std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | 
| +  rpc->set_handle(remote_handle_); | 
| +  rpc->set_proc(pb::RpcMessage::RPC_RC_ONVIDEOOPACITYCHANGE); | 
| +  rpc->set_boolean_value(opaque); | 
| +  rpc_broker_->SendMessageToRemote(std::move(rpc)); | 
| +} | 
| + | 
| +void Receiver::OnDurationChange(base::TimeDelta duration) { | 
| +  DVLOG(3) << __func__ << ": Issues RPC_RC_ONDURATIONCHANGE message."; | 
| +  std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); | 
| +  rpc->set_handle(remote_handle_); | 
| +  rpc->set_proc(pb::RpcMessage::RPC_RC_ONDURATIONCHANGE); | 
| +  rpc->set_integer_value(duration.InMicroseconds()); | 
| +  rpc_broker_->SendMessageToRemote(std::move(rpc)); | 
| +} | 
| + | 
| +}  // namespace remoting | 
| +}  // namespace media | 
|  |