blob: e05a5cb4c9ee3bb021146338a17d97cd62f451e5 [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_base_impl.h"
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000012
13#include <sstream>
14#include <string>
mflodman@webrtc.orgdadfc9e2013-12-13 09:40:45 +000015#include <utility>
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000016
pbos@webrtc.org281cff82013-05-17 13:44:48 +000017#include "webrtc/engine_configurations.h"
18#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
19#include "webrtc/modules/video_coding/main/interface/video_coding.h"
20#include "webrtc/modules/video_processing/main/interface/video_processing.h"
andrew@webrtc.org07e96da2012-10-31 05:22:11 +000021#include "webrtc/modules/video_render/include/video_render.h"
pbos@webrtc.org281cff82013-05-17 13:44:48 +000022#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000023#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.org281cff82013-05-17 13:44:48 +000024#include "webrtc/video_engine/include/vie_errors.h"
mflodman@webrtc.orgbf76ae22013-07-23 11:35:00 +000025#include "webrtc/video_engine/vie_capturer.h"
pbos@webrtc.org281cff82013-05-17 13:44:48 +000026#include "webrtc/video_engine/vie_channel.h"
27#include "webrtc/video_engine/vie_channel_manager.h"
28#include "webrtc/video_engine/vie_defines.h"
29#include "webrtc/video_engine/vie_encoder.h"
30#include "webrtc/video_engine/vie_impl.h"
31#include "webrtc/video_engine/vie_input_manager.h"
32#include "webrtc/video_engine/vie_shared_data.h"
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000033
34namespace webrtc {
35
36ViEBase* ViEBase::GetInterface(VideoEngine* video_engine) {
37 if (!video_engine) {
38 return NULL;
39 }
andrew@webrtc.org7ab72682013-05-09 02:12:07 +000040 VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000041 ViEBaseImpl* vie_base_impl = vie_impl;
42 (*vie_base_impl)++; // Increase ref count.
43
44 return vie_base_impl;
45}
46
47int ViEBaseImpl::Release() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000048 (*this)--; // Decrease ref count.
49
pbos@webrtc.org67879bc2013-04-09 13:41:51 +000050 int32_t ref_count = GetCount();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000051 if (ref_count < 0) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000052 LOG(LS_WARNING) << "ViEBase released too many times.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000053 return -1;
54 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000055 return ref_count;
56}
57
andresp@webrtc.orgac6d9192013-05-13 10:50:50 +000058ViEBaseImpl::ViEBaseImpl(const Config& config)
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000059 : shared_data_(config) {}
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000060
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000061ViEBaseImpl::~ViEBaseImpl() {}
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000062
63int ViEBaseImpl::Init() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000064 return 0;
65}
66
67int ViEBaseImpl::SetVoiceEngine(VoiceEngine* voice_engine) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000068 LOG_F(LS_INFO) << "SetVoiceEngine";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000069 if (shared_data_.channel_manager()->SetVoiceEngine(voice_engine) != 0) {
70 shared_data_.SetLastError(kViEBaseVoEFailure);
71 return -1;
72 }
73 return 0;
74}
75
mflodman@webrtc.orgbf76ae22013-07-23 11:35:00 +000076int ViEBaseImpl::RegisterCpuOveruseObserver(int video_channel,
77 CpuOveruseObserver* observer) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000078 LOG_F(LS_INFO) << "RegisterCpuOveruseObserver on channel " << video_channel;
mflodman@webrtc.orgbf76ae22013-07-23 11:35:00 +000079 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
80 ViEChannel* vie_channel = cs.Channel(video_channel);
81 if (!vie_channel) {
mflodman@webrtc.orgbf76ae22013-07-23 11:35:00 +000082 shared_data_.SetLastError(kViEBaseInvalidChannelId);
83 return -1;
84 }
85 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
86 assert(vie_encoder);
87
88 ViEInputManagerScoped is(*(shared_data_.input_manager()));
89 ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
90 if (provider) {
91 ViECapturer* capturer = is.Capture(provider->Id());
92 assert(capturer);
93 capturer->RegisterCpuOveruseObserver(observer);
94 }
95
96 shared_data_.overuse_observers()->insert(
97 std::pair<int, CpuOveruseObserver*>(video_channel, observer));
98 return 0;
99}
100
asapersson@webrtc.org9da327c2014-03-20 13:15:01 +0000101int ViEBaseImpl::SetCpuOveruseOptions(int video_channel,
102 const CpuOveruseOptions& options) {
103 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
104 ViEChannel* vie_channel = cs.Channel(video_channel);
105 if (!vie_channel) {
asapersson@webrtc.org9da327c2014-03-20 13:15:01 +0000106 shared_data_.SetLastError(kViEBaseInvalidChannelId);
107 return -1;
108 }
109 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
110 assert(vie_encoder);
111
112 ViEInputManagerScoped is(*(shared_data_.input_manager()));
113 ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
114 if (provider) {
115 ViECapturer* capturer = is.Capture(provider->Id());
116 if (capturer) {
117 capturer->SetCpuOveruseOptions(options);
118 return 0;
119 }
120 }
121 return -1;
122}
123
asapersson@webrtc.org4e954362014-05-27 07:43:15 +0000124int ViEBaseImpl::GetCpuOveruseMetrics(int video_channel,
125 CpuOveruseMetrics* metrics) {
126 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
127 ViEChannel* vie_channel = cs.Channel(video_channel);
128 if (!vie_channel) {
129 shared_data_.SetLastError(kViEBaseInvalidChannelId);
130 return -1;
131 }
132 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
133 assert(vie_encoder);
134
135 ViEInputManagerScoped is(*(shared_data_.input_manager()));
136 ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
137 if (provider) {
138 ViECapturer* capturer = is.Capture(provider->Id());
139 if (capturer) {
140 capturer->GetCpuOveruseMetrics(metrics);
asapersson@webrtc.org47475852013-11-20 13:51:40 +0000141 return 0;
142 }
143 }
144 return -1;
145}
146
stefan@webrtc.org55b0f2e2014-07-11 13:44:02 +0000147void ViEBaseImpl::RegisterSendSideDelayObserver(
148 int channel, SendSideDelayObserver* observer) {
149 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
150 ViEChannel* vie_channel = cs.Channel(channel);
151 assert(vie_channel);
152 vie_channel->RegisterSendSideDelayObserver(observer);
153}
154
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000155int ViEBaseImpl::CreateChannel(int& video_channel) { // NOLINT
henrik.lundin@webrtc.orgd2f95a82014-01-29 08:47:15 +0000156 return CreateChannel(video_channel, static_cast<const Config*>(NULL));
157}
158
159int ViEBaseImpl::CreateChannel(int& video_channel, // NOLINT
160 const Config* config) {
henrik.lundin@webrtc.orgd2f95a82014-01-29 08:47:15 +0000161 if (shared_data_.channel_manager()->CreateChannel(&video_channel,
162 config) == -1) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000163 video_channel = -1;
164 shared_data_.SetLastError(kViEBaseChannelCreationFailed);
165 return -1;
166 }
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000167 LOG(LS_INFO) << "Video channel created: " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000168 return 0;
169}
170
171int ViEBaseImpl::CreateChannel(int& video_channel, // NOLINT
172 int original_channel) {
173 return CreateChannel(video_channel, original_channel, true);
174}
175
176int ViEBaseImpl::CreateReceiveChannel(int& video_channel, // NOLINT
177 int original_channel) {
178 return CreateChannel(video_channel, original_channel, false);
179}
180
181int ViEBaseImpl::DeleteChannel(const int video_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000182 {
183 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
184 ViEChannel* vie_channel = cs.Channel(video_channel);
185 if (!vie_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000186 shared_data_.SetLastError(kViEBaseInvalidChannelId);
187 return -1;
188 }
189
190 // Deregister the ViEEncoder if no other channel is using it.
191 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
192 if (cs.ChannelUsingViEEncoder(video_channel) == false) {
193 ViEInputManagerScoped is(*(shared_data_.input_manager()));
194 ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
195 if (provider) {
196 provider->DeregisterFrameCallback(vie_encoder);
197 }
198 }
199 }
200
201 if (shared_data_.channel_manager()->DeleteChannel(video_channel) == -1) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000202 shared_data_.SetLastError(kViEBaseUnknownError);
203 return -1;
204 }
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000205 LOG(LS_INFO) << "Channel deleted " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000206 return 0;
207}
208
209int ViEBaseImpl::ConnectAudioChannel(const int video_channel,
210 const int audio_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000211 LOG_F(LS_INFO) << "ConnectAudioChannel, video channel " << video_channel
212 << ", audio channel " << audio_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000213 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
214 if (!cs.Channel(video_channel)) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000215 shared_data_.SetLastError(kViEBaseInvalidChannelId);
216 return -1;
217 }
218
219 if (shared_data_.channel_manager()->ConnectVoiceChannel(video_channel,
220 audio_channel) != 0) {
221 shared_data_.SetLastError(kViEBaseVoEFailure);
222 return -1;
223 }
224 return 0;
225}
226
227int ViEBaseImpl::DisconnectAudioChannel(const int video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000228 LOG_F(LS_INFO) << "DisconnectAudioChannel " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000229 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
230 if (!cs.Channel(video_channel)) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000231 shared_data_.SetLastError(kViEBaseInvalidChannelId);
232 return -1;
233 }
234
235 if (shared_data_.channel_manager()->DisconnectVoiceChannel(
236 video_channel) != 0) {
237 shared_data_.SetLastError(kViEBaseVoEFailure);
238 return -1;
239 }
240 return 0;
241}
242
243int ViEBaseImpl::StartSend(const int video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000244 LOG_F(LS_INFO) << "StartSend: " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000245 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
246 ViEChannel* vie_channel = cs.Channel(video_channel);
247 if (!vie_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000248 shared_data_.SetLastError(kViEBaseInvalidChannelId);
249 return -1;
250 }
251
252 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
253 assert(vie_encoder != NULL);
254 if (vie_encoder->Owner() != video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000255 LOG_F(LS_ERROR) << "Can't start send on a receive only channel.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000256 shared_data_.SetLastError(kViEBaseReceiveOnlyChannel);
257 return -1;
258 }
259
260 // Pause and trigger a key frame.
261 vie_encoder->Pause();
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000262 int32_t error = vie_channel->StartSend();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000263 if (error != 0) {
264 vie_encoder->Restart();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000265 if (error == kViEBaseAlreadySending) {
266 shared_data_.SetLastError(kViEBaseAlreadySending);
267 }
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000268 LOG_F(LS_ERROR) << "Could not start sending " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000269 shared_data_.SetLastError(kViEBaseUnknownError);
270 return -1;
271 }
272 vie_encoder->SendKeyFrame();
273 vie_encoder->Restart();
274 return 0;
275}
276
277int ViEBaseImpl::StopSend(const int video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000278 LOG_F(LS_INFO) << "StopSend " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000279
280 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
281 ViEChannel* vie_channel = cs.Channel(video_channel);
282 if (!vie_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000283 shared_data_.SetLastError(kViEBaseInvalidChannelId);
284 return -1;
285 }
286
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000287 int32_t error = vie_channel->StopSend();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000288 if (error != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000289 if (error == kViEBaseNotSending) {
290 shared_data_.SetLastError(kViEBaseNotSending);
291 } else {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000292 LOG_F(LS_ERROR) << "Could not stop sending " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000293 shared_data_.SetLastError(kViEBaseUnknownError);
294 }
295 return -1;
296 }
297 return 0;
298}
299
300int ViEBaseImpl::StartReceive(const int video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000301 LOG_F(LS_INFO) << "StartReceive " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000302
303 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
304 ViEChannel* vie_channel = cs.Channel(video_channel);
305 if (!vie_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000306 shared_data_.SetLastError(kViEBaseInvalidChannelId);
307 return -1;
308 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000309 if (vie_channel->StartReceive() != 0) {
310 shared_data_.SetLastError(kViEBaseUnknownError);
311 return -1;
312 }
313 return 0;
314}
315
316int ViEBaseImpl::StopReceive(const int video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000317 LOG_F(LS_INFO) << "StopReceive " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000318 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
319 ViEChannel* vie_channel = cs.Channel(video_channel);
320 if (!vie_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000321 shared_data_.SetLastError(kViEBaseInvalidChannelId);
322 return -1;
323 }
324 if (vie_channel->StopReceive() != 0) {
325 shared_data_.SetLastError(kViEBaseUnknownError);
326 return -1;
327 }
328 return 0;
329}
330
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000331int ViEBaseImpl::GetVersion(char version[1024]) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000332 assert(kViEVersionMaxMessageSize == 1024);
333 if (!version) {
334 shared_data_.SetLastError(kViEBaseInvalidArgument);
335 return -1;
336 }
337
338 // Add WebRTC Version.
339 std::stringstream version_stream;
tnakamura@webrtc.org225eac02014-08-20 22:44:18 +0000340 version_stream << "VideoEngine 38" << std::endl;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000341
342 // Add build info.
andrew@webrtc.orgc7d73632013-12-04 17:00:44 +0000343 version_stream << "Build: " << BUILDINFO << std::endl;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000344
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000345 int version_length = version_stream.tellp();
346 assert(version_length < 1024);
347 memcpy(version, version_stream.str().c_str(), version_length);
348 version[version_length] = '\0';
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000349 return 0;
350}
351
352int ViEBaseImpl::LastError() {
353 return shared_data_.LastErrorInternal();
354}
355
356int ViEBaseImpl::CreateChannel(int& video_channel, // NOLINT
357 int original_channel, bool sender) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000358 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
359 if (!cs.Channel(original_channel)) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000360 shared_data_.SetLastError(kViEBaseInvalidChannelId);
361 return -1;
362 }
363
364 if (shared_data_.channel_manager()->CreateChannel(&video_channel,
365 original_channel,
366 sender) == -1) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000367 video_channel = -1;
368 shared_data_.SetLastError(kViEBaseChannelCreationFailed);
369 return -1;
370 }
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000371 LOG_F(LS_INFO) << "VideoChannel created: " << video_channel
372 << ", base channel " << original_channel
373 << ", is send channel : " << sender;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000374 return 0;
375}
376
377} // namespace webrtc