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 18 ChannelConfig ChannelConfig::None() { 19 return ChannelConfig(); 20 } 21 22 ChannelConfig::ChannelConfig() 23 : transport(TRANSPORT_NONE), 24 version(0), 25 codec(CODEC_UNDEFINED) { 26 } 27 28 ChannelConfig::ChannelConfig(TransportType transport, int version, Codec codec) 29 : transport(transport), 30 version(version), 31 codec(codec) { 32 } 33 34 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 41 SessionConfig::SessionConfig() { 42 } 43 44 bool SessionConfig::SupportsCapabilities() const { 45 return control_config_.version >= kControlStreamVersion; 46 } 47 48 // static 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 66 CandidateSessionConfig::CandidateSessionConfig() { } 67 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 76 CandidateSessionConfig::~CandidateSessionConfig() { } 77 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 105 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 114 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 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 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 154 scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::Clone() const { 155 return scoped_ptr<CandidateSessionConfig>(new CandidateSessionConfig(*this)); 156 } 157 158 // static 159 scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateEmpty() { 160 return scoped_ptr<CandidateSessionConfig>(new CandidateSessionConfig()); 161 } 162 163 // static 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 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 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 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