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