blob: 6f35c24f619e65a651f75f0ae9ea098a4724f243 [file] [log] [blame]
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001/*
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.org281cff82013-05-17 13:44:48 +000011#include "webrtc/video_engine/vie_channel_manager.h"
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000012
henrik.lundin@webrtc.orgd2f95a82014-01-29 08:47:15 +000013#include "webrtc/common.h"
pbos@webrtc.org281cff82013-05-17 13:44:48 +000014#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.org022615b2014-04-07 10:56:31 +000018#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.org281cff82013-05-17 13:44:48 +000019#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.orgb015cbe2012-10-22 18:19:23 +000026
27namespace webrtc {
28
29ViEChannelManager::ViEChannelManager(
30 int engine_id,
31 int number_of_cores,
andresp@webrtc.orgac6d9192013-05-13 10:50:50 +000032 const Config& config)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000033 : 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.orgd2f95a82014-01-29 08:47:15 +000041 engine_config_(config) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000042 for (int idx = 0; idx < free_channel_ids_size_; idx++) {
43 free_channel_ids_[idx] = true;
44 }
45}
46
47ViEChannelManager::~ViEChannelManager() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000048 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
71void ViEChannelManager::SetModuleProcessThread(
72 ProcessThread* module_process_thread) {
73 assert(!module_process_thread_);
74 module_process_thread_ = module_process_thread;
75}
76
henrik.lundin@webrtc.orgd2f95a82014-01-29 08:47:15 +000077int ViEChannelManager::CreateChannel(int* channel_id,
78 const Config* channel_group_config) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000079 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.org46f72882013-12-16 12:24:44 +000088 ChannelGroup* group = new ChannelGroup(engine_id_, module_process_thread_,
henrik.lundin@webrtc.orgd2f95a82014-01-29 08:47:15 +000089 channel_group_config);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000090 BitrateController* bitrate_controller = group->GetBitrateController();
91 ViEEncoder* vie_encoder = new ViEEncoder(engine_id_, new_channel_id,
92 number_of_cores_,
henrik.lundin@webrtc.orgd2f95a82014-01-29 08:47:15 +000093 engine_config_,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000094 *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.orgc4af4cf2013-11-20 12:46:11 +0000103 RtcpRttStats* rtcp_rtt_stats =
104 group->GetCallStats()->rtcp_rtt_stats();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000105
106 if (!(vie_encoder->Init() &&
107 CreateChannelObject(new_channel_id, vie_encoder, bandwidth_observer,
asapersson@webrtc.orgc4af4cf2013-11-20 12:46:11 +0000108 remote_bitrate_estimator, rtcp_rtt_stats,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000109 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.orgb6d9cfc2012-10-25 11:30:29 +0000120 int idx = 0;
121 channel_map_[new_channel_id]->GetLocalSSRC(idx, &ssrc);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000122 encoder_state_feedback->AddEncoder(ssrc, vie_encoder);
mflodman@webrtc.orgb6d9cfc2012-10-25 11:30:29 +0000123 std::list<unsigned int> ssrcs;
124 ssrcs.push_back(ssrc);
125 vie_encoder->SetSsrcs(ssrcs);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000126 *channel_id = new_channel_id;
127 group->AddChannel(*channel_id);
128 channel_groups_.push_back(group);
mflodman@webrtc.org78696d32012-11-26 12:40:15 +0000129 // Register the channel to receive stats updates.
130 group->GetCallStats()->RegisterStatsObserver(
131 channel_map_[new_channel_id]->GetStatsObserver());
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000132 return 0;
133}
134
135int 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.orgb015cbe2012-10-22 18:19:23 +0000144 int new_channel_id = FreeChannelId();
145 if (new_channel_id == -1) {
146 return -1;
147 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000148 BitrateController* bitrate_controller = channel_group->GetBitrateController();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000149 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.orgc4af4cf2013-11-20 12:46:11 +0000155 RtcpRttStats* rtcp_rtt_stats =
156 channel_group->GetCallStats()->rtcp_rtt_stats();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000157
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.orgd2f95a82014-01-29 08:47:15 +0000162 engine_config_,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000163 *module_process_thread_,
164 bitrate_controller);
165 if (!(vie_encoder->Init() &&
pwestin@webrtc.org5e87b5f2012-11-13 21:12:39 +0000166 CreateChannelObject(
167 new_channel_id,
168 vie_encoder,
169 bandwidth_observer,
170 remote_bitrate_estimator,
asapersson@webrtc.orgc4af4cf2013-11-20 12:46:11 +0000171 rtcp_rtt_stats,
mflodman@webrtc.org78696d32012-11-26 12:40:15 +0000172 encoder_state_feedback->GetRtcpIntraFrameObserver(),
173 sender))) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000174 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.orgb6d9cfc2012-10-25 11:30:29 +0000179 int stream_idx = 0;
180 channel_map_[new_channel_id]->GetLocalSSRC(stream_idx, &ssrc);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000181 encoder_state_feedback->AddEncoder(ssrc, vie_encoder);
182 } else {
183 vie_encoder = ViEEncoderPtr(original_channel);
184 assert(vie_encoder);
185 if (!CreateChannelObject(
pwestin@webrtc.org5e87b5f2012-11-13 21:12:39 +0000186 new_channel_id,
187 vie_encoder,
188 bandwidth_observer,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000189 remote_bitrate_estimator,
asapersson@webrtc.orgc4af4cf2013-11-20 12:46:11 +0000190 rtcp_rtt_stats,
pwestin@webrtc.org5e87b5f2012-11-13 21:12:39 +0000191 encoder_state_feedback->GetRtcpIntraFrameObserver(),
192 sender)) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000193 vie_encoder = NULL;
194 }
195 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000196 if (!vie_encoder) {
197 ReturnChannelId(new_channel_id);
198 return -1;
199 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000200 *channel_id = new_channel_id;
201 channel_group->AddChannel(*channel_id);
mflodman@webrtc.org78696d32012-11-26 12:40:15 +0000202 // Register the channel to receive stats updates.
203 channel_group->GetCallStats()->RegisterStatsObserver(
204 channel_map_[new_channel_id]->GetStatsObserver());
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000205 return 0;
206}
207
208int 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.orgb015cbe2012-10-22 18:19:23 +0000222 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.org78696d32012-11-26 12:40:15 +0000235 group->GetCallStats()->DeregisterStatsObserver(
236 vie_channel->GetStatsObserver());
mflodman@webrtc.orgbea854a2013-04-22 12:41:57 +0000237 group->SetChannelRembStatus(channel_id, false, false, vie_channel);
mflodman@webrtc.orgff9854b2012-10-25 13:06:22 +0000238
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.orgb6d9cfc2012-10-25 11:30:29 +0000243
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000244 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.org022615b2014-04-07 10:56:31 +0000271 LOG(LS_VERBOSE) << "ViEEncoder deleted for channel " << channel_id;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000272 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.org022615b2014-04-07 10:56:31 +0000278 LOG(LS_VERBOSE) << "Channel group deleted for channel " << channel_id;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000279 delete group;
280 }
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000281 LOG(LS_VERBOSE) << "Channel deleted " << channel_id;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000282 return 0;
283}
284
285int 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.orgb015cbe2012-10-22 18:19:23 +0000296 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
312int ViEChannelManager::ConnectVoiceChannel(int channel_id,
313 int audio_channel_id) {
314 CriticalSectionScoped cs(channel_id_critsect_);
315 if (!voice_sync_interface_) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000316 LOG_F(LS_ERROR) << "No VoE set.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000317 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
326int 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
336VoiceEngine* ViEChannelManager::GetVoiceEngine() {
337 CriticalSectionScoped cs(channel_id_critsect_);
338 return voice_engine_;
339}
340
341bool 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.orgb015cbe2012-10-22 18:19:23 +0000350
mflodman@webrtc.orgbea854a2013-04-22 12:41:57 +0000351 return group->SetChannelRembStatus(channel_id, sender, receiver, channel);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000352}
353
solenberg@webrtc.org2f0c5f72014-03-26 14:32:47 +0000354bool 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.orgb6d9cfc2012-10-25 11:30:29 +0000367void ViEChannelManager::UpdateSsrcs(int channel_id,
368 const std::list<unsigned int>& ssrcs) {
369 CriticalSectionScoped cs(channel_id_critsect_);
solenberg@webrtc.orgf40e9b62013-05-27 16:02:56 +0000370 ChannelGroup* channel_group = FindGroup(channel_id);
mflodman@webrtc.orgb6d9cfc2012-10-25 11:30:29 +0000371 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.org7e63b042013-02-14 11:25:26 +0000379 // Remove a possible previous setting for this encoder before adding the new
380 // setting.
381 encoder_state_feedback->RemoveEncoder(encoder);
mflodman@webrtc.orgb6d9cfc2012-10-25 11:30:29 +0000382 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.org5d8c9542014-03-25 10:37:31 +0000388bool 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.org4d61a362014-05-02 12:35:37 +0000399bool 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
410bool 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.orgb50d6712014-05-12 22:09:27 +0000419 &ssrcs, estimated_bandwidth) || ssrcs.empty()) {
stefan@webrtc.org4d61a362014-05-02 12:35:37 +0000420 *estimated_bandwidth = 0;
421 }
422 return true;
423}
424
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000425bool ViEChannelManager::CreateChannelObject(
426 int channel_id,
427 ViEEncoder* vie_encoder,
428 RtcpBandwidthObserver* bandwidth_observer,
429 RemoteBitrateEstimator* remote_bitrate_estimator,
asapersson@webrtc.orgc4af4cf2013-11-20 12:46:11 +0000430 RtcpRttStats* rtcp_rtt_stats,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000431 RtcpIntraFrameObserver* intra_frame_observer,
432 bool sender) {
pwestin@webrtc.org5e87b5f2012-11-13 21:12:39 +0000433 PacedSender* paced_sender = vie_encoder->GetPacedSender();
434
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000435 // 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.orgd2f95a82014-01-29 08:47:15 +0000440 engine_config_,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000441 *module_process_thread_,
442 intra_frame_observer,
443 bandwidth_observer,
444 remote_bitrate_estimator,
asapersson@webrtc.orgc4af4cf2013-11-20 12:46:11 +0000445 rtcp_rtt_stats,
pwestin@webrtc.org5e87b5f2012-11-13 21:12:39 +0000446 paced_sender,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000447 send_rtp_rtcp_module,
448 sender);
449 if (vie_channel->Init() != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000450 delete vie_channel;
451 return false;
452 }
453 VideoCodec encoder;
454 if (vie_encoder->GetEncoder(&encoder) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000455 delete vie_channel;
456 return false;
457 }
458 if (sender && vie_channel->SetSendCodec(encoder) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000459 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
468ViEChannel* 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.org022615b2014-04-07 10:56:31 +0000472 LOG(LS_ERROR) << "Channel doesn't exist " << channel_id;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000473 return NULL;
474 }
475 return it->second;
476}
477
478ViEEncoder* 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
487int 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.org022615b2014-04-07 10:56:31 +0000497 LOG(LS_ERROR) << "Max number of channels reached.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000498 return -1;
499}
500
501void 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.org4d61a362014-05-02 12:35:37 +0000508ChannelGroup* ViEChannelManager::FindGroup(int channel_id) const {
509 for (ChannelGroups::const_iterator it = channel_groups_.begin();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000510 it != channel_groups_.end(); ++it) {
511 if ((*it)->HasChannel(channel_id)) {
512 return *it;
513 }
514 }
515 return NULL;
516}
517
518bool 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
540void 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
555ViEChannelManagerScoped::ViEChannelManagerScoped(
556 const ViEChannelManager& vie_channel_manager)
557 : ViEManagerScopedBase(vie_channel_manager) {
558}
559
560ViEChannel* ViEChannelManagerScoped::Channel(int vie_channel_id) const {
561 return static_cast<const ViEChannelManager*>(vie_manager_)->ViEChannelPtr(
562 vie_channel_id);
563}
564ViEEncoder* ViEChannelManagerScoped::Encoder(int vie_channel_id) const {
565 return static_cast<const ViEChannelManager*>(vie_manager_)->ViEEncoderPtr(
566 vie_channel_id);
567}
568
569bool ViEChannelManagerScoped::ChannelUsingViEEncoder(int channel_id) const {
570 return (static_cast<const ViEChannelManager*>(vie_manager_))->
571 ChannelUsingViEEncoder(channel_id);
572}
573
574void 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