13842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz// Copyright (c) 2012 The Chromium Authors. All rights reserved.
23842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz// Use of this source code is governed by a BSD-style license that can be
30613d4c6800dbd47c26c90eb49883f45bd1fd77cArun Sharma// found in the LICENSE file.
43842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
53842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz#include "remoting/protocol/session_config.h"
63842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
73842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz#include <algorithm>
83842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
93842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitznamespace remoting {
103842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitznamespace protocol {
113842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
123842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzconst int kDefaultStreamVersion = 2;
133842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzconst int kControlStreamVersion = 3;
143842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
153842dac7333e42aa44531eda34ba55200b99ccf8Daniel JacobowitzChannelConfig ChannelConfig::None() {
163842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  return ChannelConfig();
173842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz}
183842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
193842dac7333e42aa44531eda34ba55200b99ccf8Daniel JacobowitzChannelConfig::ChannelConfig()
203842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    : transport(TRANSPORT_NONE),
213842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      version(0),
223842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      codec(CODEC_UNDEFINED) {
233842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz}
243842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
253842dac7333e42aa44531eda34ba55200b99ccf8Daniel JacobowitzChannelConfig::ChannelConfig(TransportType transport, int version, Codec codec)
263842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    : transport(transport),
273842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      version(version),
283842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz      codec(codec) {
29049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch}
3025aeae9adf3c55fb38752434d948ebc42f3ea465Ken Werner
3125aeae9adf3c55fb38752434d948ebc42f3ea465Ken Wernerbool ChannelConfig::operator==(const ChannelConfig& b) const {
3225aeae9adf3c55fb38752434d948ebc42f3ea465Ken Werner  // If the transport field is set to NONE then all other fields are irrelevant.
33049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch  if (transport == ChannelConfig::TRANSPORT_NONE)
349533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner    return transport == b.transport;
3525aeae9adf3c55fb38752434d948ebc42f3ea465Ken Werner  return transport == b.transport && version == b.version && codec == b.codec;
3625aeae9adf3c55fb38752434d948ebc42f3ea465Ken Werner}
379533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner
389533ea1a6adc91276cd779c598f5718c773c44c9Ken WernerSessionConfig::SessionConfig() {
3925aeae9adf3c55fb38752434d948ebc42f3ea465Ken Werner}
4025aeae9adf3c55fb38752434d948ebc42f3ea465Ken Werner
4125aeae9adf3c55fb38752434d948ebc42f3ea465Ken Werner// static
4225aeae9adf3c55fb38752434d948ebc42f3ea465Ken WernerSessionConfig SessionConfig::ForTest() {
439533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner  SessionConfig result;
449533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner  result.set_control_config(ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
4525aeae9adf3c55fb38752434d948ebc42f3ea465Ken Werner                                          kControlStreamVersion,
4625aeae9adf3c55fb38752434d948ebc42f3ea465Ken Werner                                          ChannelConfig::CODEC_UNDEFINED));
4725aeae9adf3c55fb38752434d948ebc42f3ea465Ken Werner  result.set_event_config(ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
483842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz                                        kDefaultStreamVersion,
499533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner                                        ChannelConfig::CODEC_UNDEFINED));
509533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner  result.set_video_config(ChannelConfig(ChannelConfig::TRANSPORT_STREAM,
513842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz                                        kDefaultStreamVersion,
523842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz                                        ChannelConfig::CODEC_VP8));
533842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz  result.set_audio_config(ChannelConfig(ChannelConfig::TRANSPORT_NONE,
54049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch                                        kDefaultStreamVersion,
55049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch                                        ChannelConfig::CODEC_UNDEFINED));
56049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch  return result;
57049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch}
58049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch
59049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T WelchCandidateSessionConfig::CandidateSessionConfig() { }
60049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch
61049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T WelchCandidateSessionConfig::CandidateSessionConfig(
62049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch    const CandidateSessionConfig& config)
63049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch    : control_configs_(config.control_configs_),
64049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch      event_configs_(config.event_configs_),
65049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch      video_configs_(config.video_configs_),
66049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch      audio_configs_(config.audio_configs_) {
679533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner}
68049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch
6923c6aa9a54d0a220fb2557197c555b2684c93876Christopher FerrisCandidateSessionConfig::~CandidateSessionConfig() { }
7023c6aa9a54d0a220fb2557197c555b2684c93876Christopher Ferris
7123c6aa9a54d0a220fb2557197c555b2684c93876Christopher Ferrisbool CandidateSessionConfig::Select(
729533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner    const CandidateSessionConfig* client_config,
739533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner    SessionConfig* result) {
749533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner  ChannelConfig control_config;
759533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner  ChannelConfig event_config;
769533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner  ChannelConfig video_config;
779533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner  ChannelConfig audio_config;
789533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner
799533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner  if (!SelectCommonChannelConfig(
809533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner          control_configs_, client_config->control_configs_, &control_config) ||
819533ea1a6adc91276cd779c598f5718c773c44c9Ken Werner      !SelectCommonChannelConfig(
82eac65dc9b8cc18fa4c65c0485878a11c470357b6Matt Fischer          event_configs_, client_config->event_configs_, &event_config) ||
83eac65dc9b8cc18fa4c65c0485878a11c470357b6Matt Fischer      !SelectCommonChannelConfig(
84eac65dc9b8cc18fa4c65c0485878a11c470357b6Matt Fischer          video_configs_, client_config->video_configs_, &video_config) ||
85049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch      !SelectCommonChannelConfig(
863842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz          audio_configs_, client_config->audio_configs_, &audio_config)) {
873842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz    return false;
88049e2ba1b9734ec027765cd9449cb29a9bc0d974Zachary T Welch  }
893842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz
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
98bool 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
107bool 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
124bool 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
141bool 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
147scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::Clone() const {
148  return scoped_ptr<CandidateSessionConfig>(new CandidateSessionConfig(*this));
149}
150
151// static
152scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateEmpty() {
153  return scoped_ptr<CandidateSessionConfig>(new CandidateSessionConfig());
154}
155
156// static
157scoped_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
168scoped_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
201void CandidateSessionConfig::DisableAudioChannel() {
202  mutable_audio_configs()->clear();
203  mutable_audio_configs()->push_back(ChannelConfig());
204}
205
206void 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