andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
pbos@webrtc.org | 281cff8 | 2013-05-17 13:44:48 +0000 | [diff] [blame] | 11 | #include "webrtc/video_engine/vie_channel_manager.h" |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 12 | |
henrik.lundin@webrtc.org | d2f95a8 | 2014-01-29 08:47:15 +0000 | [diff] [blame] | 13 | #include "webrtc/common.h" |
pbos@webrtc.org | 281cff8 | 2013-05-17 13:44:48 +0000 | [diff] [blame] | 14 | #include "webrtc/engine_configurations.h" |
| 15 | #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" |
| 16 | #include "webrtc/modules/utility/interface/process_thread.h" |
| 17 | #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" |
mflodman@webrtc.org | 022615b | 2014-04-07 10:56:31 +0000 | [diff] [blame] | 18 | #include "webrtc/system_wrappers/interface/logging.h" |
pbos@webrtc.org | 281cff8 | 2013-05-17 13:44:48 +0000 | [diff] [blame] | 19 | #include "webrtc/video_engine/call_stats.h" |
| 20 | #include "webrtc/video_engine/encoder_state_feedback.h" |
| 21 | #include "webrtc/video_engine/vie_channel.h" |
| 22 | #include "webrtc/video_engine/vie_defines.h" |
| 23 | #include "webrtc/video_engine/vie_encoder.h" |
| 24 | #include "webrtc/video_engine/vie_remb.h" |
| 25 | #include "webrtc/voice_engine/include/voe_video_sync.h" |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 26 | |
| 27 | namespace webrtc { |
| 28 | |
| 29 | ViEChannelManager::ViEChannelManager( |
| 30 | int engine_id, |
| 31 | int number_of_cores, |
andresp@webrtc.org | ac6d919 | 2013-05-13 10:50:50 +0000 | [diff] [blame] | 32 | const Config& config) |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 33 | : channel_id_critsect_(CriticalSectionWrapper::CreateCriticalSection()), |
| 34 | engine_id_(engine_id), |
| 35 | number_of_cores_(number_of_cores), |
| 36 | free_channel_ids_(new bool[kViEMaxNumberOfChannels]), |
| 37 | free_channel_ids_size_(kViEMaxNumberOfChannels), |
| 38 | voice_sync_interface_(NULL), |
| 39 | voice_engine_(NULL), |
| 40 | module_process_thread_(NULL), |
henrik.lundin@webrtc.org | d2f95a8 | 2014-01-29 08:47:15 +0000 | [diff] [blame] | 41 | engine_config_(config) { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 42 | for (int idx = 0; idx < free_channel_ids_size_; idx++) { |
| 43 | free_channel_ids_[idx] = true; |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | ViEChannelManager::~ViEChannelManager() { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 48 | while (channel_map_.size() > 0) { |
| 49 | ChannelMap::iterator it = channel_map_.begin(); |
| 50 | // DeleteChannel will erase this channel from the map and invalidate |it|. |
| 51 | DeleteChannel(it->first); |
| 52 | } |
| 53 | |
| 54 | if (voice_sync_interface_) { |
| 55 | voice_sync_interface_->Release(); |
| 56 | } |
| 57 | if (channel_id_critsect_) { |
| 58 | delete channel_id_critsect_; |
| 59 | channel_id_critsect_ = NULL; |
| 60 | } |
| 61 | if (free_channel_ids_) { |
| 62 | delete[] free_channel_ids_; |
| 63 | free_channel_ids_ = NULL; |
| 64 | free_channel_ids_size_ = 0; |
| 65 | } |
| 66 | assert(channel_groups_.empty()); |
| 67 | assert(channel_map_.empty()); |
| 68 | assert(vie_encoder_map_.empty()); |
| 69 | } |
| 70 | |
| 71 | void ViEChannelManager::SetModuleProcessThread( |
| 72 | ProcessThread* module_process_thread) { |
| 73 | assert(!module_process_thread_); |
| 74 | module_process_thread_ = module_process_thread; |
| 75 | } |
| 76 | |
henrik.lundin@webrtc.org | d2f95a8 | 2014-01-29 08:47:15 +0000 | [diff] [blame] | 77 | int ViEChannelManager::CreateChannel(int* channel_id, |
| 78 | const Config* channel_group_config) { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 79 | CriticalSectionScoped cs(channel_id_critsect_); |
| 80 | |
| 81 | // Get a new channel id. |
| 82 | int new_channel_id = FreeChannelId(); |
| 83 | if (new_channel_id == -1) { |
| 84 | return -1; |
| 85 | } |
| 86 | |
| 87 | // Create a new channel group and add this channel. |
pbos@webrtc.org | 46f7288 | 2013-12-16 12:24:44 +0000 | [diff] [blame] | 88 | ChannelGroup* group = new ChannelGroup(engine_id_, module_process_thread_, |
henrik.lundin@webrtc.org | d2f95a8 | 2014-01-29 08:47:15 +0000 | [diff] [blame] | 89 | channel_group_config); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 90 | BitrateController* bitrate_controller = group->GetBitrateController(); |
| 91 | ViEEncoder* vie_encoder = new ViEEncoder(engine_id_, new_channel_id, |
| 92 | number_of_cores_, |
henrik.lundin@webrtc.org | d2f95a8 | 2014-01-29 08:47:15 +0000 | [diff] [blame] | 93 | engine_config_, |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 94 | *module_process_thread_, |
| 95 | bitrate_controller); |
| 96 | |
| 97 | RtcpBandwidthObserver* bandwidth_observer = |
| 98 | bitrate_controller->CreateRtcpBandwidthObserver(); |
| 99 | RemoteBitrateEstimator* remote_bitrate_estimator = |
| 100 | group->GetRemoteBitrateEstimator(); |
| 101 | EncoderStateFeedback* encoder_state_feedback = |
| 102 | group->GetEncoderStateFeedback(); |
asapersson@webrtc.org | c4af4cf | 2013-11-20 12:46:11 +0000 | [diff] [blame] | 103 | RtcpRttStats* rtcp_rtt_stats = |
| 104 | group->GetCallStats()->rtcp_rtt_stats(); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 105 | |
| 106 | if (!(vie_encoder->Init() && |
| 107 | CreateChannelObject(new_channel_id, vie_encoder, bandwidth_observer, |
asapersson@webrtc.org | c4af4cf | 2013-11-20 12:46:11 +0000 | [diff] [blame] | 108 | remote_bitrate_estimator, rtcp_rtt_stats, |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 109 | encoder_state_feedback->GetRtcpIntraFrameObserver(), |
| 110 | true))) { |
| 111 | delete vie_encoder; |
| 112 | vie_encoder = NULL; |
| 113 | ReturnChannelId(new_channel_id); |
| 114 | delete group; |
| 115 | return -1; |
| 116 | } |
| 117 | |
| 118 | // Add ViEEncoder to EncoderFeedBackObserver. |
| 119 | unsigned int ssrc = 0; |
mflodman@webrtc.org | b6d9cfc | 2012-10-25 11:30:29 +0000 | [diff] [blame] | 120 | int idx = 0; |
| 121 | channel_map_[new_channel_id]->GetLocalSSRC(idx, &ssrc); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 122 | encoder_state_feedback->AddEncoder(ssrc, vie_encoder); |
mflodman@webrtc.org | b6d9cfc | 2012-10-25 11:30:29 +0000 | [diff] [blame] | 123 | std::list<unsigned int> ssrcs; |
| 124 | ssrcs.push_back(ssrc); |
| 125 | vie_encoder->SetSsrcs(ssrcs); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 126 | *channel_id = new_channel_id; |
| 127 | group->AddChannel(*channel_id); |
| 128 | channel_groups_.push_back(group); |
mflodman@webrtc.org | 78696d3 | 2012-11-26 12:40:15 +0000 | [diff] [blame] | 129 | // Register the channel to receive stats updates. |
| 130 | group->GetCallStats()->RegisterStatsObserver( |
| 131 | channel_map_[new_channel_id]->GetStatsObserver()); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 132 | return 0; |
| 133 | } |
| 134 | |
| 135 | int ViEChannelManager::CreateChannel(int* channel_id, |
| 136 | int original_channel, |
| 137 | bool sender) { |
| 138 | CriticalSectionScoped cs(channel_id_critsect_); |
| 139 | |
| 140 | ChannelGroup* channel_group = FindGroup(original_channel); |
| 141 | if (!channel_group) { |
| 142 | return -1; |
| 143 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 144 | int new_channel_id = FreeChannelId(); |
| 145 | if (new_channel_id == -1) { |
| 146 | return -1; |
| 147 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 148 | BitrateController* bitrate_controller = channel_group->GetBitrateController(); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 149 | RtcpBandwidthObserver* bandwidth_observer = |
| 150 | bitrate_controller->CreateRtcpBandwidthObserver(); |
| 151 | RemoteBitrateEstimator* remote_bitrate_estimator = |
| 152 | channel_group->GetRemoteBitrateEstimator(); |
| 153 | EncoderStateFeedback* encoder_state_feedback = |
| 154 | channel_group->GetEncoderStateFeedback(); |
asapersson@webrtc.org | c4af4cf | 2013-11-20 12:46:11 +0000 | [diff] [blame] | 155 | RtcpRttStats* rtcp_rtt_stats = |
| 156 | channel_group->GetCallStats()->rtcp_rtt_stats(); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 157 | |
| 158 | ViEEncoder* vie_encoder = NULL; |
| 159 | if (sender) { |
| 160 | // We need to create a new ViEEncoder. |
| 161 | vie_encoder = new ViEEncoder(engine_id_, new_channel_id, number_of_cores_, |
henrik.lundin@webrtc.org | d2f95a8 | 2014-01-29 08:47:15 +0000 | [diff] [blame] | 162 | engine_config_, |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 163 | *module_process_thread_, |
| 164 | bitrate_controller); |
| 165 | if (!(vie_encoder->Init() && |
pwestin@webrtc.org | 5e87b5f | 2012-11-13 21:12:39 +0000 | [diff] [blame] | 166 | CreateChannelObject( |
| 167 | new_channel_id, |
| 168 | vie_encoder, |
| 169 | bandwidth_observer, |
| 170 | remote_bitrate_estimator, |
asapersson@webrtc.org | c4af4cf | 2013-11-20 12:46:11 +0000 | [diff] [blame] | 171 | rtcp_rtt_stats, |
mflodman@webrtc.org | 78696d3 | 2012-11-26 12:40:15 +0000 | [diff] [blame] | 172 | encoder_state_feedback->GetRtcpIntraFrameObserver(), |
| 173 | sender))) { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 174 | delete vie_encoder; |
| 175 | vie_encoder = NULL; |
| 176 | } |
| 177 | // Register the ViEEncoder to get key frame requests for this channel. |
| 178 | unsigned int ssrc = 0; |
mflodman@webrtc.org | b6d9cfc | 2012-10-25 11:30:29 +0000 | [diff] [blame] | 179 | int stream_idx = 0; |
| 180 | channel_map_[new_channel_id]->GetLocalSSRC(stream_idx, &ssrc); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 181 | encoder_state_feedback->AddEncoder(ssrc, vie_encoder); |
| 182 | } else { |
| 183 | vie_encoder = ViEEncoderPtr(original_channel); |
| 184 | assert(vie_encoder); |
| 185 | if (!CreateChannelObject( |
pwestin@webrtc.org | 5e87b5f | 2012-11-13 21:12:39 +0000 | [diff] [blame] | 186 | new_channel_id, |
| 187 | vie_encoder, |
| 188 | bandwidth_observer, |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 189 | remote_bitrate_estimator, |
asapersson@webrtc.org | c4af4cf | 2013-11-20 12:46:11 +0000 | [diff] [blame] | 190 | rtcp_rtt_stats, |
pwestin@webrtc.org | 5e87b5f | 2012-11-13 21:12:39 +0000 | [diff] [blame] | 191 | encoder_state_feedback->GetRtcpIntraFrameObserver(), |
| 192 | sender)) { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 193 | vie_encoder = NULL; |
| 194 | } |
| 195 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 196 | if (!vie_encoder) { |
| 197 | ReturnChannelId(new_channel_id); |
| 198 | return -1; |
| 199 | } |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 200 | *channel_id = new_channel_id; |
| 201 | channel_group->AddChannel(*channel_id); |
mflodman@webrtc.org | 78696d3 | 2012-11-26 12:40:15 +0000 | [diff] [blame] | 202 | // Register the channel to receive stats updates. |
| 203 | channel_group->GetCallStats()->RegisterStatsObserver( |
| 204 | channel_map_[new_channel_id]->GetStatsObserver()); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 205 | return 0; |
| 206 | } |
| 207 | |
| 208 | int ViEChannelManager::DeleteChannel(int channel_id) { |
| 209 | ViEChannel* vie_channel = NULL; |
| 210 | ViEEncoder* vie_encoder = NULL; |
| 211 | ChannelGroup* group = NULL; |
| 212 | { |
| 213 | // Write lock to make sure no one is using the channel. |
| 214 | ViEManagerWriteScoped wl(this); |
| 215 | |
| 216 | // Protect the maps. |
| 217 | CriticalSectionScoped cs(channel_id_critsect_); |
| 218 | |
| 219 | ChannelMap::iterator c_it = channel_map_.find(channel_id); |
| 220 | if (c_it == channel_map_.end()) { |
| 221 | // No such channel. |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 222 | return -1; |
| 223 | } |
| 224 | vie_channel = c_it->second; |
| 225 | channel_map_.erase(c_it); |
| 226 | |
| 227 | ReturnChannelId(channel_id); |
| 228 | |
| 229 | // Find the encoder object. |
| 230 | EncoderMap::iterator e_it = vie_encoder_map_.find(channel_id); |
| 231 | assert(e_it != vie_encoder_map_.end()); |
| 232 | vie_encoder = e_it->second; |
| 233 | |
| 234 | group = FindGroup(channel_id); |
mflodman@webrtc.org | 78696d3 | 2012-11-26 12:40:15 +0000 | [diff] [blame] | 235 | group->GetCallStats()->DeregisterStatsObserver( |
| 236 | vie_channel->GetStatsObserver()); |
mflodman@webrtc.org | bea854a | 2013-04-22 12:41:57 +0000 | [diff] [blame] | 237 | group->SetChannelRembStatus(channel_id, false, false, vie_channel); |
mflodman@webrtc.org | ff9854b | 2012-10-25 13:06:22 +0000 | [diff] [blame] | 238 | |
| 239 | // Remove the feedback if we're owning the encoder. |
| 240 | if (vie_encoder->channel_id() == channel_id) { |
| 241 | group->GetEncoderStateFeedback()->RemoveEncoder(vie_encoder); |
| 242 | } |
mflodman@webrtc.org | b6d9cfc | 2012-10-25 11:30:29 +0000 | [diff] [blame] | 243 | |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 244 | unsigned int remote_ssrc = 0; |
| 245 | vie_channel->GetRemoteSSRC(&remote_ssrc); |
| 246 | group->RemoveChannel(channel_id, remote_ssrc); |
| 247 | |
| 248 | // Check if other channels are using the same encoder. |
| 249 | if (ChannelUsingViEEncoder(channel_id)) { |
| 250 | vie_encoder = NULL; |
| 251 | } else { |
| 252 | // Delete later when we've released the critsect. |
| 253 | } |
| 254 | |
| 255 | // We can't erase the item before we've checked for other channels using |
| 256 | // same ViEEncoder. |
| 257 | vie_encoder_map_.erase(e_it); |
| 258 | |
| 259 | if (group->Empty()) { |
| 260 | channel_groups_.remove(group); |
| 261 | } else { |
| 262 | group = NULL; // Prevent group from being deleted. |
| 263 | } |
| 264 | } |
| 265 | delete vie_channel; |
| 266 | // Leave the write critsect before deleting the objects. |
| 267 | // Deleting a channel can cause other objects, such as renderers, to be |
| 268 | // deleted, which might take time. |
| 269 | // If statment just to show that this object is not always deleted. |
| 270 | if (vie_encoder) { |
mflodman@webrtc.org | 022615b | 2014-04-07 10:56:31 +0000 | [diff] [blame] | 271 | LOG(LS_VERBOSE) << "ViEEncoder deleted for channel " << channel_id; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 272 | delete vie_encoder; |
| 273 | } |
| 274 | // If statment just to show that this object is not always deleted. |
| 275 | if (group) { |
| 276 | // Delete the group if empty last since the encoder holds a pointer to the |
| 277 | // BitrateController object that the group owns. |
mflodman@webrtc.org | 022615b | 2014-04-07 10:56:31 +0000 | [diff] [blame] | 278 | LOG(LS_VERBOSE) << "Channel group deleted for channel " << channel_id; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 279 | delete group; |
| 280 | } |
mflodman@webrtc.org | 022615b | 2014-04-07 10:56:31 +0000 | [diff] [blame] | 281 | LOG(LS_VERBOSE) << "Channel deleted " << channel_id; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 282 | return 0; |
| 283 | } |
| 284 | |
| 285 | int ViEChannelManager::SetVoiceEngine(VoiceEngine* voice_engine) { |
| 286 | // Write lock to make sure no one is using the channel. |
| 287 | ViEManagerWriteScoped wl(this); |
| 288 | |
| 289 | CriticalSectionScoped cs(channel_id_critsect_); |
| 290 | |
| 291 | VoEVideoSync* sync_interface = NULL; |
| 292 | if (voice_engine) { |
| 293 | // Get new sync interface. |
| 294 | sync_interface = VoEVideoSync::GetInterface(voice_engine); |
| 295 | if (!sync_interface) { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 296 | return -1; |
| 297 | } |
| 298 | } |
| 299 | |
| 300 | for (ChannelMap::iterator it = channel_map_.begin(); it != channel_map_.end(); |
| 301 | ++it) { |
| 302 | it->second->SetVoiceChannel(-1, sync_interface); |
| 303 | } |
| 304 | if (voice_sync_interface_) { |
| 305 | voice_sync_interface_->Release(); |
| 306 | } |
| 307 | voice_engine_ = voice_engine; |
| 308 | voice_sync_interface_ = sync_interface; |
| 309 | return 0; |
| 310 | } |
| 311 | |
| 312 | int ViEChannelManager::ConnectVoiceChannel(int channel_id, |
| 313 | int audio_channel_id) { |
| 314 | CriticalSectionScoped cs(channel_id_critsect_); |
| 315 | if (!voice_sync_interface_) { |
mflodman@webrtc.org | 022615b | 2014-04-07 10:56:31 +0000 | [diff] [blame] | 316 | LOG_F(LS_ERROR) << "No VoE set."; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 317 | return -1; |
| 318 | } |
| 319 | ViEChannel* channel = ViEChannelPtr(channel_id); |
| 320 | if (!channel) { |
| 321 | return -1; |
| 322 | } |
| 323 | return channel->SetVoiceChannel(audio_channel_id, voice_sync_interface_); |
| 324 | } |
| 325 | |
| 326 | int ViEChannelManager::DisconnectVoiceChannel(int channel_id) { |
| 327 | CriticalSectionScoped cs(channel_id_critsect_); |
| 328 | ViEChannel* channel = ViEChannelPtr(channel_id); |
| 329 | if (channel) { |
| 330 | channel->SetVoiceChannel(-1, NULL); |
| 331 | return 0; |
| 332 | } |
| 333 | return -1; |
| 334 | } |
| 335 | |
| 336 | VoiceEngine* ViEChannelManager::GetVoiceEngine() { |
| 337 | CriticalSectionScoped cs(channel_id_critsect_); |
| 338 | return voice_engine_; |
| 339 | } |
| 340 | |
| 341 | bool ViEChannelManager::SetRembStatus(int channel_id, bool sender, |
| 342 | bool receiver) { |
| 343 | CriticalSectionScoped cs(channel_id_critsect_); |
| 344 | ChannelGroup* group = FindGroup(channel_id); |
| 345 | if (!group) { |
| 346 | return false; |
| 347 | } |
| 348 | ViEChannel* channel = ViEChannelPtr(channel_id); |
| 349 | assert(channel); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 350 | |
mflodman@webrtc.org | bea854a | 2013-04-22 12:41:57 +0000 | [diff] [blame] | 351 | return group->SetChannelRembStatus(channel_id, sender, receiver, channel); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 352 | } |
| 353 | |
solenberg@webrtc.org | 2f0c5f7 | 2014-03-26 14:32:47 +0000 | [diff] [blame] | 354 | bool ViEChannelManager::SetReservedTransmitBitrate( |
| 355 | int channel_id, uint32_t reserved_transmit_bitrate_bps) { |
| 356 | CriticalSectionScoped cs(channel_id_critsect_); |
| 357 | ChannelGroup* group = FindGroup(channel_id); |
| 358 | if (!group) { |
| 359 | return false; |
| 360 | } |
| 361 | |
| 362 | BitrateController* bitrate_controller = group->GetBitrateController(); |
| 363 | bitrate_controller->SetReservedBitrate(reserved_transmit_bitrate_bps); |
| 364 | return true; |
| 365 | } |
| 366 | |
mflodman@webrtc.org | b6d9cfc | 2012-10-25 11:30:29 +0000 | [diff] [blame] | 367 | void ViEChannelManager::UpdateSsrcs(int channel_id, |
| 368 | const std::list<unsigned int>& ssrcs) { |
| 369 | CriticalSectionScoped cs(channel_id_critsect_); |
solenberg@webrtc.org | f40e9b6 | 2013-05-27 16:02:56 +0000 | [diff] [blame] | 370 | ChannelGroup* channel_group = FindGroup(channel_id); |
mflodman@webrtc.org | b6d9cfc | 2012-10-25 11:30:29 +0000 | [diff] [blame] | 371 | if (channel_group == NULL) { |
| 372 | return; |
| 373 | } |
| 374 | ViEEncoder* encoder = ViEEncoderPtr(channel_id); |
| 375 | assert(encoder); |
| 376 | |
| 377 | EncoderStateFeedback* encoder_state_feedback = |
| 378 | channel_group->GetEncoderStateFeedback(); |
mflodman@webrtc.org | 7e63b04 | 2013-02-14 11:25:26 +0000 | [diff] [blame] | 379 | // Remove a possible previous setting for this encoder before adding the new |
| 380 | // setting. |
| 381 | encoder_state_feedback->RemoveEncoder(encoder); |
mflodman@webrtc.org | b6d9cfc | 2012-10-25 11:30:29 +0000 | [diff] [blame] | 382 | for (std::list<unsigned int>::const_iterator it = ssrcs.begin(); |
| 383 | it != ssrcs.end(); ++it) { |
| 384 | encoder_state_feedback->AddEncoder(*it, encoder); |
| 385 | } |
| 386 | } |
| 387 | |
stefan@webrtc.org | 5d8c954 | 2014-03-25 10:37:31 +0000 | [diff] [blame] | 388 | bool ViEChannelManager::SetBandwidthEstimationConfig( |
| 389 | int channel_id, const webrtc::Config& config) { |
| 390 | CriticalSectionScoped cs(channel_id_critsect_); |
| 391 | ChannelGroup* group = FindGroup(channel_id); |
| 392 | if (!group) { |
| 393 | return false; |
| 394 | } |
| 395 | group->SetBandwidthEstimationConfig(config); |
| 396 | return true; |
| 397 | } |
| 398 | |
stefan@webrtc.org | 4d61a36 | 2014-05-02 12:35:37 +0000 | [diff] [blame] | 399 | bool ViEChannelManager::GetEstimatedSendBandwidth( |
| 400 | int channel_id, uint32_t* estimated_bandwidth) const { |
| 401 | CriticalSectionScoped cs(channel_id_critsect_); |
| 402 | ChannelGroup* group = FindGroup(channel_id); |
| 403 | if (!group) { |
| 404 | return false; |
| 405 | } |
| 406 | group->GetBitrateController()->AvailableBandwidth(estimated_bandwidth); |
| 407 | return true; |
| 408 | } |
| 409 | |
| 410 | bool ViEChannelManager::GetEstimatedReceiveBandwidth( |
| 411 | int channel_id, uint32_t* estimated_bandwidth) const { |
| 412 | CriticalSectionScoped cs(channel_id_critsect_); |
| 413 | ChannelGroup* group = FindGroup(channel_id); |
| 414 | if (!group) { |
| 415 | return false; |
| 416 | } |
| 417 | std::vector<unsigned int> ssrcs; |
| 418 | if (!group->GetRemoteBitrateEstimator()->LatestEstimate( |
stefan@webrtc.org | b50d671 | 2014-05-12 22:09:27 +0000 | [diff] [blame] | 419 | &ssrcs, estimated_bandwidth) || ssrcs.empty()) { |
stefan@webrtc.org | 4d61a36 | 2014-05-02 12:35:37 +0000 | [diff] [blame] | 420 | *estimated_bandwidth = 0; |
| 421 | } |
| 422 | return true; |
| 423 | } |
| 424 | |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 425 | bool ViEChannelManager::CreateChannelObject( |
| 426 | int channel_id, |
| 427 | ViEEncoder* vie_encoder, |
| 428 | RtcpBandwidthObserver* bandwidth_observer, |
| 429 | RemoteBitrateEstimator* remote_bitrate_estimator, |
asapersson@webrtc.org | c4af4cf | 2013-11-20 12:46:11 +0000 | [diff] [blame] | 430 | RtcpRttStats* rtcp_rtt_stats, |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 431 | RtcpIntraFrameObserver* intra_frame_observer, |
| 432 | bool sender) { |
pwestin@webrtc.org | 5e87b5f | 2012-11-13 21:12:39 +0000 | [diff] [blame] | 433 | PacedSender* paced_sender = vie_encoder->GetPacedSender(); |
| 434 | |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 435 | // Register the channel at the encoder. |
| 436 | RtpRtcp* send_rtp_rtcp_module = vie_encoder->SendRtpRtcpModule(); |
| 437 | |
| 438 | ViEChannel* vie_channel = new ViEChannel(channel_id, engine_id_, |
| 439 | number_of_cores_, |
henrik.lundin@webrtc.org | d2f95a8 | 2014-01-29 08:47:15 +0000 | [diff] [blame] | 440 | engine_config_, |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 441 | *module_process_thread_, |
| 442 | intra_frame_observer, |
| 443 | bandwidth_observer, |
| 444 | remote_bitrate_estimator, |
asapersson@webrtc.org | c4af4cf | 2013-11-20 12:46:11 +0000 | [diff] [blame] | 445 | rtcp_rtt_stats, |
pwestin@webrtc.org | 5e87b5f | 2012-11-13 21:12:39 +0000 | [diff] [blame] | 446 | paced_sender, |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 447 | send_rtp_rtcp_module, |
| 448 | sender); |
| 449 | if (vie_channel->Init() != 0) { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 450 | delete vie_channel; |
| 451 | return false; |
| 452 | } |
| 453 | VideoCodec encoder; |
| 454 | if (vie_encoder->GetEncoder(&encoder) != 0) { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 455 | delete vie_channel; |
| 456 | return false; |
| 457 | } |
| 458 | if (sender && vie_channel->SetSendCodec(encoder) != 0) { |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 459 | delete vie_channel; |
| 460 | return false; |
| 461 | } |
| 462 | // Store the channel, add it to the channel group and save the vie_encoder. |
| 463 | channel_map_[channel_id] = vie_channel; |
| 464 | vie_encoder_map_[channel_id] = vie_encoder; |
| 465 | return true; |
| 466 | } |
| 467 | |
| 468 | ViEChannel* ViEChannelManager::ViEChannelPtr(int channel_id) const { |
| 469 | CriticalSectionScoped cs(channel_id_critsect_); |
| 470 | ChannelMap::const_iterator it = channel_map_.find(channel_id); |
| 471 | if (it == channel_map_.end()) { |
mflodman@webrtc.org | 022615b | 2014-04-07 10:56:31 +0000 | [diff] [blame] | 472 | LOG(LS_ERROR) << "Channel doesn't exist " << channel_id; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 473 | return NULL; |
| 474 | } |
| 475 | return it->second; |
| 476 | } |
| 477 | |
| 478 | ViEEncoder* ViEChannelManager::ViEEncoderPtr(int video_channel_id) const { |
| 479 | CriticalSectionScoped cs(channel_id_critsect_); |
| 480 | EncoderMap::const_iterator it = vie_encoder_map_.find(video_channel_id); |
| 481 | if (it == vie_encoder_map_.end()) { |
| 482 | return NULL; |
| 483 | } |
| 484 | return it->second; |
| 485 | } |
| 486 | |
| 487 | int ViEChannelManager::FreeChannelId() { |
| 488 | int idx = 0; |
| 489 | while (idx < free_channel_ids_size_) { |
| 490 | if (free_channel_ids_[idx] == true) { |
| 491 | // We've found a free id, allocate it and return. |
| 492 | free_channel_ids_[idx] = false; |
| 493 | return idx + kViEChannelIdBase; |
| 494 | } |
| 495 | idx++; |
| 496 | } |
mflodman@webrtc.org | 022615b | 2014-04-07 10:56:31 +0000 | [diff] [blame] | 497 | LOG(LS_ERROR) << "Max number of channels reached."; |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 498 | return -1; |
| 499 | } |
| 500 | |
| 501 | void ViEChannelManager::ReturnChannelId(int channel_id) { |
| 502 | CriticalSectionScoped cs(channel_id_critsect_); |
| 503 | assert(channel_id < kViEMaxNumberOfChannels + kViEChannelIdBase && |
| 504 | channel_id >= kViEChannelIdBase); |
| 505 | free_channel_ids_[channel_id - kViEChannelIdBase] = true; |
| 506 | } |
| 507 | |
stefan@webrtc.org | 4d61a36 | 2014-05-02 12:35:37 +0000 | [diff] [blame] | 508 | ChannelGroup* ViEChannelManager::FindGroup(int channel_id) const { |
| 509 | for (ChannelGroups::const_iterator it = channel_groups_.begin(); |
andrew@webrtc.org | b015cbe | 2012-10-22 18:19:23 +0000 | [diff] [blame] | 510 | it != channel_groups_.end(); ++it) { |
| 511 | if ((*it)->HasChannel(channel_id)) { |
| 512 | return *it; |
| 513 | } |
| 514 | } |
| 515 | return NULL; |
| 516 | } |
| 517 | |
| 518 | bool ViEChannelManager::ChannelUsingViEEncoder(int channel_id) const { |
| 519 | CriticalSectionScoped cs(channel_id_critsect_); |
| 520 | EncoderMap::const_iterator orig_it = vie_encoder_map_.find(channel_id); |
| 521 | if (orig_it == vie_encoder_map_.end()) { |
| 522 | // No ViEEncoder for this channel. |
| 523 | return false; |
| 524 | } |
| 525 | |
| 526 | // Loop through all other channels to see if anyone points at the same |
| 527 | // ViEEncoder. |
| 528 | for (EncoderMap::const_iterator comp_it = vie_encoder_map_.begin(); |
| 529 | comp_it != vie_encoder_map_.end(); ++comp_it) { |
| 530 | // Make sure we're not comparing the same channel with itself. |
| 531 | if (comp_it->first != channel_id) { |
| 532 | if (comp_it->second == orig_it->second) { |
| 533 | return true; |
| 534 | } |
| 535 | } |
| 536 | } |
| 537 | return false; |
| 538 | } |
| 539 | |
| 540 | void ViEChannelManager::ChannelsUsingViEEncoder(int channel_id, |
| 541 | ChannelList* channels) const { |
| 542 | CriticalSectionScoped cs(channel_id_critsect_); |
| 543 | EncoderMap::const_iterator orig_it = vie_encoder_map_.find(channel_id); |
| 544 | |
| 545 | for (ChannelMap::const_iterator c_it = channel_map_.begin(); |
| 546 | c_it != channel_map_.end(); ++c_it) { |
| 547 | EncoderMap::const_iterator comp_it = vie_encoder_map_.find(c_it->first); |
| 548 | assert(comp_it != vie_encoder_map_.end()); |
| 549 | if (comp_it->second == orig_it->second) { |
| 550 | channels->push_back(c_it->second); |
| 551 | } |
| 552 | } |
| 553 | } |
| 554 | |
| 555 | ViEChannelManagerScoped::ViEChannelManagerScoped( |
| 556 | const ViEChannelManager& vie_channel_manager) |
| 557 | : ViEManagerScopedBase(vie_channel_manager) { |
| 558 | } |
| 559 | |
| 560 | ViEChannel* ViEChannelManagerScoped::Channel(int vie_channel_id) const { |
| 561 | return static_cast<const ViEChannelManager*>(vie_manager_)->ViEChannelPtr( |
| 562 | vie_channel_id); |
| 563 | } |
| 564 | ViEEncoder* ViEChannelManagerScoped::Encoder(int vie_channel_id) const { |
| 565 | return static_cast<const ViEChannelManager*>(vie_manager_)->ViEEncoderPtr( |
| 566 | vie_channel_id); |
| 567 | } |
| 568 | |
| 569 | bool ViEChannelManagerScoped::ChannelUsingViEEncoder(int channel_id) const { |
| 570 | return (static_cast<const ViEChannelManager*>(vie_manager_))-> |
| 571 | ChannelUsingViEEncoder(channel_id); |
| 572 | } |
| 573 | |
| 574 | void ViEChannelManagerScoped::ChannelsUsingViEEncoder( |
| 575 | int channel_id, ChannelList* channels) const { |
| 576 | (static_cast<const ViEChannelManager*>(vie_manager_))-> |
| 577 | ChannelsUsingViEEncoder(channel_id, channels); |
| 578 | } |
| 579 | |
| 580 | } // namespace webrtc |