1 // Copyright (c) 2012 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 "remoting/protocol/session_config.h"
6
7 #include <algorithm>
8
9 namespace remoting {
10 namespace protocol {
11
12 const int kDefaultStreamVersion = 2;
13
14 // The control channel version that supports the "capabilities" message.
15 const int kControlStreamVersion = 3;
16 const int kControlStreamVersionNoCapabilities = kDefaultStreamVersion;
17
None()18 ChannelConfig ChannelConfig::None() {
19 return ChannelConfig();
20 }
21
ChannelConfig()22 ChannelConfig::ChannelConfig()
23 : transport(TRANSPORT_NONE),
24 version(0),
25 codec(CODEC_UNDEFINED) {
26 }
27
ChannelConfig(TransportType transport,int version,Codec codec)28 ChannelConfig::ChannelConfig(TransportType transport, int version, Codec codec)
29 : transport(transport),
30 version(version),
31 codec(codec) {
32 }
33
operator ==(const ChannelConfig & b) const34 bool ChannelConfig::operator==(const ChannelConfig& b) const {
35 // If the transport field is set to NONE then all other fields are irrelevant.
36 if (transport == ChannelConfig::TRANSPORT_NONE)
37 return transport == b.transport;
38 return transport == b.transport && version == b.version && codec == b.codec;
39 }
40
SessionConfig()41 SessionConfig::SessionConfig() {
42 }
43
SupportsCapabilities() const44 bool SessionConfig::SupportsCapabilities() const {
45 return control_config_.version >= kControlStreamVersion;
46 }
47
48 // static
ForTest()49 SessionConfig SessionConfig::ForTest() {
50 SessionConfig result;
51 result.set_control_config(ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
52 kControlStreamVersionNoCapabilities,
53 ChannelConfig::CODEC_UNDEFINED));
54 result.set_event_config(ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
55 kDefaultStreamVersion,
56 ChannelConfig::CODEC_UNDEFINED));
57 result.set_video_config(ChannelConfig(ChannelConfig::TRANSPORT_STREAM,
58 kDefaultStreamVersion,
59 ChannelConfig::CODEC_VP8));
60 result.set_audio_config(ChannelConfig(ChannelConfig::TRANSPORT_NONE,
61 kDefaultStreamVersion,
62 ChannelConfig::CODEC_UNDEFINED));
63 return result;
64 }
65
CandidateSessionConfig()66 CandidateSessionConfig::CandidateSessionConfig() { }
67
CandidateSessionConfig(const CandidateSessionConfig & config)68 CandidateSessionConfig::CandidateSessionConfig(
69 const CandidateSessionConfig& config)
70 : control_configs_(config.control_configs_),
71 event_configs_(config.event_configs_),
72 video_configs_(config.video_configs_),
73 audio_configs_(config.audio_configs_) {
74 }
75
~CandidateSessionConfig()76 CandidateSessionConfig::~CandidateSessionConfig() { }
77
Select(const CandidateSessionConfig * client_config,SessionConfig * result)78 bool CandidateSessionConfig::Select(
79 const CandidateSessionConfig* client_config,
80 SessionConfig* result) {
81 ChannelConfig control_config;
82 ChannelConfig event_config;
83 ChannelConfig video_config;
84 ChannelConfig audio_config;
85
86 if (!SelectCommonChannelConfig(
87 control_configs_, client_config->control_configs_, &control_config) ||
88 !SelectCommonChannelConfig(
89 event_configs_, client_config->event_configs_, &event_config) ||
90 !SelectCommonChannelConfig(
91 video_configs_, client_config->video_configs_, &video_config) ||
92 !SelectCommonChannelConfig(
93 audio_configs_, client_config->audio_configs_, &audio_config)) {
94 return false;
95 }
96
97 result->set_control_config(control_config);
98 result->set_event_config(event_config);
99 result->set_video_config(video_config);
100 result->set_audio_config(audio_config);
101
102 return true;
103 }
104
IsSupported(const SessionConfig & config) const105 bool CandidateSessionConfig::IsSupported(
106 const SessionConfig& config) const {
107 return
108 IsChannelConfigSupported(control_configs_, config.control_config()) &&
109 IsChannelConfigSupported(event_configs_, config.event_config()) &&
110 IsChannelConfigSupported(video_configs_, config.video_config()) &&
111 IsChannelConfigSupported(audio_configs_, config.audio_config());
112 }
113
GetFinalConfig(SessionConfig * result) const114 bool CandidateSessionConfig::GetFinalConfig(SessionConfig* result) const {
115 if (control_configs_.size() != 1 ||
116 event_configs_.size() != 1 ||
117 video_configs_.size() != 1 ||
118 audio_configs_.size() != 1) {
119 return false;
120 }
121
122 result->set_control_config(control_configs_.front());
123 result->set_event_config(event_configs_.front());
124 result->set_video_config(video_configs_.front());
125 result->set_audio_config(audio_configs_.front());
126
127 return true;
128 }
129
130 // static
SelectCommonChannelConfig(const std::vector<ChannelConfig> & host_configs,const std::vector<ChannelConfig> & client_configs,ChannelConfig * config)131 bool CandidateSessionConfig::SelectCommonChannelConfig(
132 const std::vector<ChannelConfig>& host_configs,
133 const std::vector<ChannelConfig>& client_configs,
134 ChannelConfig* config) {
135 // Usually each of these vectors will contain just several elements,
136 // so iterating over all of them is not a problem.
137 std::vector<ChannelConfig>::const_iterator it;
138 for (it = client_configs.begin(); it != client_configs.end(); ++it) {
139 if (IsChannelConfigSupported(host_configs, *it)) {
140 *config = *it;
141 return true;
142 }
143 }
144 return false;
145 }
146
147 // static
IsChannelConfigSupported(const std::vector<ChannelConfig> & vector,const ChannelConfig & value)148 bool CandidateSessionConfig::IsChannelConfigSupported(
149 const std::vector<ChannelConfig>& vector,
150 const ChannelConfig& value) {
151 return std::find(vector.begin(), vector.end(), value) != vector.end();
152 }
153
Clone() const154 scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::Clone() const {
155 return scoped_ptr<CandidateSessionConfig>(new CandidateSessionConfig(*this));
156 }
157
158 // static
CreateEmpty()159 scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateEmpty() {
160 return scoped_ptr<CandidateSessionConfig>(new CandidateSessionConfig());
161 }
162
163 // static
CreateFrom(const SessionConfig & config)164 scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateFrom(
165 const SessionConfig& config) {
166 scoped_ptr<CandidateSessionConfig> result = CreateEmpty();
167 result->mutable_control_configs()->push_back(config.control_config());
168 result->mutable_event_configs()->push_back(config.event_config());
169 result->mutable_video_configs()->push_back(config.video_config());
170 result->mutable_audio_configs()->push_back(config.audio_config());
171 return result.Pass();
172 }
173
174 // static
CreateDefault()175 scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateDefault() {
176 scoped_ptr<CandidateSessionConfig> result = CreateEmpty();
177
178 // Control channel.
179 result->mutable_control_configs()->push_back(
180 ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
181 kControlStreamVersion,
182 ChannelConfig::CODEC_UNDEFINED));
183 result->mutable_control_configs()->push_back(
184 ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
185 kControlStreamVersionNoCapabilities,
186 ChannelConfig::CODEC_UNDEFINED));
187
188 // Event channel.
189 result->mutable_event_configs()->push_back(
190 ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
191 kDefaultStreamVersion,
192 ChannelConfig::CODEC_UNDEFINED));
193
194 // Video channel.
195 result->mutable_video_configs()->push_back(
196 ChannelConfig(ChannelConfig::TRANSPORT_STREAM,
197 kDefaultStreamVersion,
198 ChannelConfig::CODEC_VP9));
199 result->mutable_video_configs()->push_back(
200 ChannelConfig(ChannelConfig::TRANSPORT_STREAM,
201 kDefaultStreamVersion,
202 ChannelConfig::CODEC_VP8));
203
204 // Audio channel.
205 result->mutable_audio_configs()->push_back(
206 ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
207 kDefaultStreamVersion,
208 ChannelConfig::CODEC_OPUS));
209 result->mutable_audio_configs()->push_back(ChannelConfig::None());
210
211 return result.Pass();
212 }
213
214 // static
DisableAudioChannel(CandidateSessionConfig * config)215 void CandidateSessionConfig::DisableAudioChannel(
216 CandidateSessionConfig* config) {
217 config->mutable_audio_configs()->clear();
218 config->mutable_audio_configs()->push_back(ChannelConfig());
219 }
220
221 // static
DisableVideoCodec(CandidateSessionConfig * config,ChannelConfig::Codec codec)222 void CandidateSessionConfig::DisableVideoCodec(
223 CandidateSessionConfig* config,
224 ChannelConfig::Codec codec) {
225 std ::vector<ChannelConfig>::iterator i;
226 for (i = config->mutable_video_configs()->begin();
227 i != config->mutable_video_configs()->end();) {
228 if (i->codec == codec) {
229 i = config->mutable_video_configs()->erase(i);
230 } else {
231 ++i;
232 }
233 }
234 }
235
236 } // namespace protocol
237 } // namespace remoting
238