| // Copyright (c) 2012 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 "remoting/protocol/session_config.h" |
| |
| #include <algorithm> |
| |
| namespace remoting { |
| namespace protocol { |
| |
| const int kDefaultStreamVersion = 2; |
| |
| // The control channel version that supports the "capabilities" message. |
| const int kControlStreamVersion = 3; |
| const int kControlStreamVersionNoCapabilities = kDefaultStreamVersion; |
| |
| ChannelConfig ChannelConfig::None() { |
| return ChannelConfig(); |
| } |
| |
| ChannelConfig::ChannelConfig() |
| : transport(TRANSPORT_NONE), |
| version(0), |
| codec(CODEC_UNDEFINED) { |
| } |
| |
| ChannelConfig::ChannelConfig(TransportType transport, int version, Codec codec) |
| : transport(transport), |
| version(version), |
| codec(codec) { |
| } |
| |
| bool ChannelConfig::operator==(const ChannelConfig& b) const { |
| // If the transport field is set to NONE then all other fields are irrelevant. |
| if (transport == ChannelConfig::TRANSPORT_NONE) |
| return transport == b.transport; |
| return transport == b.transport && version == b.version && codec == b.codec; |
| } |
| |
| SessionConfig::SessionConfig() { |
| } |
| |
| bool SessionConfig::SupportsCapabilities() const { |
| return control_config_.version >= kControlStreamVersion; |
| } |
| |
| // static |
| SessionConfig SessionConfig::ForTest() { |
| SessionConfig result; |
| result.set_control_config(ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, |
| kControlStreamVersion, |
| ChannelConfig::CODEC_UNDEFINED)); |
| result.set_event_config(ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, |
| kDefaultStreamVersion, |
| ChannelConfig::CODEC_UNDEFINED)); |
| result.set_video_config(ChannelConfig(ChannelConfig::TRANSPORT_STREAM, |
| kDefaultStreamVersion, |
| ChannelConfig::CODEC_VP8)); |
| result.set_audio_config(ChannelConfig(ChannelConfig::TRANSPORT_NONE, |
| kDefaultStreamVersion, |
| ChannelConfig::CODEC_UNDEFINED)); |
| return result; |
| } |
| |
| CandidateSessionConfig::CandidateSessionConfig() { } |
| |
| CandidateSessionConfig::CandidateSessionConfig( |
| const CandidateSessionConfig& config) |
| : control_configs_(config.control_configs_), |
| event_configs_(config.event_configs_), |
| video_configs_(config.video_configs_), |
| audio_configs_(config.audio_configs_) { |
| } |
| |
| CandidateSessionConfig::~CandidateSessionConfig() { } |
| |
| bool CandidateSessionConfig::Select( |
| const CandidateSessionConfig* client_config, |
| SessionConfig* result) { |
| ChannelConfig control_config; |
| ChannelConfig event_config; |
| ChannelConfig video_config; |
| ChannelConfig audio_config; |
| |
| if (!SelectCommonChannelConfig( |
| control_configs_, client_config->control_configs_, &control_config) || |
| !SelectCommonChannelConfig( |
| event_configs_, client_config->event_configs_, &event_config) || |
| !SelectCommonChannelConfig( |
| video_configs_, client_config->video_configs_, &video_config) || |
| !SelectCommonChannelConfig( |
| audio_configs_, client_config->audio_configs_, &audio_config)) { |
| return false; |
| } |
| |
| result->set_control_config(control_config); |
| result->set_event_config(event_config); |
| result->set_video_config(video_config); |
| result->set_audio_config(audio_config); |
| |
| return true; |
| } |
| |
| bool CandidateSessionConfig::IsSupported( |
| const SessionConfig& config) const { |
| return |
| IsChannelConfigSupported(control_configs_, config.control_config()) && |
| IsChannelConfigSupported(event_configs_, config.event_config()) && |
| IsChannelConfigSupported(video_configs_, config.video_config()) && |
| IsChannelConfigSupported(audio_configs_, config.audio_config()); |
| } |
| |
| bool CandidateSessionConfig::GetFinalConfig(SessionConfig* result) const { |
| if (control_configs_.size() != 1 || |
| event_configs_.size() != 1 || |
| video_configs_.size() != 1 || |
| audio_configs_.size() != 1) { |
| return false; |
| } |
| |
| result->set_control_config(control_configs_.front()); |
| result->set_event_config(event_configs_.front()); |
| result->set_video_config(video_configs_.front()); |
| result->set_audio_config(audio_configs_.front()); |
| |
| return true; |
| } |
| |
| // static |
| bool CandidateSessionConfig::SelectCommonChannelConfig( |
| const std::list<ChannelConfig>& host_configs, |
| const std::list<ChannelConfig>& client_configs, |
| ChannelConfig* config) { |
| // Usually each of these vectors will contain just several elements, |
| // so iterating over all of them is not a problem. |
| std::list<ChannelConfig>::const_iterator it; |
| for (it = client_configs.begin(); it != client_configs.end(); ++it) { |
| if (IsChannelConfigSupported(host_configs, *it)) { |
| *config = *it; |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| // static |
| bool CandidateSessionConfig::IsChannelConfigSupported( |
| const std::list<ChannelConfig>& vector, |
| const ChannelConfig& value) { |
| return std::find(vector.begin(), vector.end(), value) != vector.end(); |
| } |
| |
| scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::Clone() const { |
| return scoped_ptr<CandidateSessionConfig>(new CandidateSessionConfig(*this)); |
| } |
| |
| // static |
| scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateEmpty() { |
| return scoped_ptr<CandidateSessionConfig>(new CandidateSessionConfig()); |
| } |
| |
| // static |
| scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateFrom( |
| const SessionConfig& config) { |
| scoped_ptr<CandidateSessionConfig> result = CreateEmpty(); |
| result->mutable_control_configs()->push_back(config.control_config()); |
| result->mutable_event_configs()->push_back(config.event_config()); |
| result->mutable_video_configs()->push_back(config.video_config()); |
| result->mutable_audio_configs()->push_back(config.audio_config()); |
| return result.Pass(); |
| } |
| |
| // static |
| scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateDefault() { |
| scoped_ptr<CandidateSessionConfig> result = CreateEmpty(); |
| |
| // Control channel. |
| result->mutable_control_configs()->push_back( |
| ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, |
| kControlStreamVersion, |
| ChannelConfig::CODEC_UNDEFINED)); |
| result->mutable_control_configs()->push_back( |
| ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, |
| kControlStreamVersionNoCapabilities, |
| ChannelConfig::CODEC_UNDEFINED)); |
| |
| // Event channel. |
| result->mutable_event_configs()->push_back( |
| ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, |
| kDefaultStreamVersion, |
| ChannelConfig::CODEC_UNDEFINED)); |
| |
| // Video channel. |
| result->mutable_video_configs()->push_back( |
| ChannelConfig(ChannelConfig::TRANSPORT_STREAM, |
| kDefaultStreamVersion, |
| ChannelConfig::CODEC_VP8)); |
| |
| // Audio channel. |
| result->mutable_audio_configs()->push_back( |
| ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, |
| kDefaultStreamVersion, |
| ChannelConfig::CODEC_OPUS)); |
| result->mutable_audio_configs()->push_back(ChannelConfig::None()); |
| |
| return result.Pass(); |
| } |
| |
| void CandidateSessionConfig::DisableAudioChannel() { |
| mutable_audio_configs()->clear(); |
| mutable_audio_configs()->push_back(ChannelConfig()); |
| } |
| |
| void CandidateSessionConfig::EnableVideoCodec(ChannelConfig::Codec codec) { |
| mutable_video_configs()->push_front( |
| ChannelConfig(ChannelConfig::TRANSPORT_STREAM, |
| kDefaultStreamVersion, |
| codec)); |
| } |
| |
| } // namespace protocol |
| } // namespace remoting |