1 // Copyright 2021 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cast/standalone_sender/remoting_sender.h"
6
7 #include <utility>
8
9 #include "cast/streaming/message_fields.h"
10
11 namespace openscreen {
12 namespace cast {
13
14 namespace {
15
ToProtoCodec(VideoCodec value)16 VideoDecoderConfig::Codec ToProtoCodec(VideoCodec value) {
17 switch (value) {
18 case VideoCodec::kHevc:
19 return VideoDecoderConfig_Codec_kCodecHEVC;
20 case VideoCodec::kH264:
21 return VideoDecoderConfig_Codec_kCodecH264;
22 case VideoCodec::kVp8:
23 return VideoDecoderConfig_Codec_kCodecVP8;
24 case VideoCodec::kVp9:
25 return VideoDecoderConfig_Codec_kCodecVP9;
26 case VideoCodec::kAv1:
27 return VideoDecoderConfig_Codec_kCodecAV1;
28 default:
29 return VideoDecoderConfig_Codec_kUnknownVideoCodec;
30 }
31 }
32
ToProtoCodec(AudioCodec value)33 AudioDecoderConfig::Codec ToProtoCodec(AudioCodec value) {
34 switch (value) {
35 case AudioCodec::kAac:
36 return AudioDecoderConfig_Codec_kCodecAAC;
37 case AudioCodec::kOpus:
38 return AudioDecoderConfig_Codec_kCodecOpus;
39 default:
40 return AudioDecoderConfig_Codec_kUnknownAudioCodec;
41 }
42 }
43
44 } // namespace
45
46 RemotingSender::Client::~Client() = default;
47
RemotingSender(RpcMessenger * messenger,AudioCodec audio_codec,VideoCodec video_codec,Client * client)48 RemotingSender::RemotingSender(RpcMessenger* messenger,
49 AudioCodec audio_codec,
50 VideoCodec video_codec,
51 Client* client)
52 : messenger_(messenger),
53 audio_codec_(audio_codec),
54 video_codec_(video_codec),
55 client_(client) {
56 OSP_DCHECK(client_);
57 messenger_->RegisterMessageReceiverCallback(
58 RpcMessenger::kAcquireRendererHandle,
59 [this](std::unique_ptr<RpcMessage> message) {
60 OSP_DCHECK(message);
61 this->OnMessage(*message);
62 });
63 }
64
~RemotingSender()65 RemotingSender::~RemotingSender() {
66 messenger_->UnregisterMessageReceiverCallback(
67 RpcMessenger::kAcquireRendererHandle);
68 }
69
OnMessage(const RpcMessage & message)70 void RemotingSender::OnMessage(const RpcMessage& message) {
71 if (!message.has_proc()) {
72 return;
73 }
74 if (message.proc() == RpcMessage_RpcProc_RPC_DS_INITIALIZE) {
75 OSP_VLOG << "Received initialize message";
76 OnInitializeMessage(message);
77 } else if (message.proc() == RpcMessage_RpcProc_RPC_R_SETPLAYBACKRATE) {
78 OSP_VLOG << "Received playback rate message: " << message.double_value();
79 OnPlaybackRateMessage(message);
80 }
81 }
82
OnInitializeMessage(const RpcMessage & message)83 void RemotingSender::OnInitializeMessage(const RpcMessage& message) {
84 receiver_handle_ = message.integer_value();
85
86 RpcMessage callback_message;
87 callback_message.set_handle(receiver_handle_);
88 callback_message.set_proc(RpcMessage::RPC_DS_INITIALIZE_CALLBACK);
89
90 auto* callback_body =
91 callback_message.mutable_demuxerstream_initializecb_rpc();
92
93 // In Chrome, separate calls are used for the audio and video configs, but
94 // for simplicity's sake we combine them here.
95 callback_body->mutable_audio_decoder_config()->set_codec(
96 ToProtoCodec(audio_codec_));
97 callback_body->mutable_video_decoder_config()->set_codec(
98 ToProtoCodec(video_codec_));
99
100 OSP_DLOG_INFO << "Initializing receiver handle " << receiver_handle_
101 << " with audio codec " << CodecToString(audio_codec_)
102 << " and video codec " << CodecToString(video_codec_);
103 messenger_->SendMessageToRemote(callback_message);
104
105 client_->OnReady();
106 }
107
OnPlaybackRateMessage(const RpcMessage & message)108 void RemotingSender::OnPlaybackRateMessage(const RpcMessage& message) {
109 client_->OnPlaybackRateChange(message.double_value());
110 }
111
112 } // namespace cast
113 } // namespace openscreen
114