blob: 617ab40742d2221f8e81d6fe4c2cc60381780e91 [file] [log] [blame]
andrew@webrtc.orga7b57da2012-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
11#include "video_engine/vie_base_impl.h"
12
13#include <sstream>
14#include <string>
15
16#include "engine_configurations.h" // NOLINT
17#include "system_wrappers/interface/critical_section_wrapper.h"
18#include "modules/rtp_rtcp/interface/rtp_rtcp.h"
19#include "modules/video_coding/main/interface/video_coding.h"
20#include "modules/video_processing/main/interface/video_processing.h"
andrew@webrtc.orgb43b6112012-10-31 05:22:11 +000021#include "webrtc/modules/video_render/include/video_render.h"
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000022#include "system_wrappers/interface/trace.h"
23#include "video_engine/vie_channel.h"
24#include "video_engine/vie_channel_manager.h"
25#include "video_engine/vie_defines.h"
26#include "video_engine/vie_encoder.h"
27#include "video_engine/include/vie_errors.h"
28#include "video_engine/vie_impl.h"
29#include "video_engine/vie_input_manager.h"
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000030#include "video_engine/vie_shared_data.h"
31
32namespace webrtc {
33
34ViEBase* ViEBase::GetInterface(VideoEngine* video_engine) {
35 if (!video_engine) {
36 return NULL;
37 }
andrew@webrtc.orgd3d364e2013-05-09 02:12:07 +000038 VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000039 ViEBaseImpl* vie_base_impl = vie_impl;
40 (*vie_base_impl)++; // Increase ref count.
41
42 return vie_base_impl;
43}
44
45int ViEBaseImpl::Release() {
46 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, shared_data_.instance_id(),
47 "ViEBase::Release()");
48 (*this)--; // Decrease ref count.
49
pbos@webrtc.org2a5d2292013-04-09 13:41:51 +000050 int32_t ref_count = GetCount();
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000051 if (ref_count < 0) {
52 WEBRTC_TRACE(kTraceWarning, kTraceVideo, shared_data_.instance_id(),
53 "ViEBase release too many times");
54 shared_data_.SetLastError(kViEAPIDoesNotExist);
55 return -1;
56 }
57 WEBRTC_TRACE(kTraceInfo, kTraceVideo, shared_data_.instance_id(),
58 "ViEBase reference count: %d", ref_count);
59 return ref_count;
60}
61
62ViEBaseImpl::ViEBaseImpl() {
63 WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_.instance_id(),
64 "ViEBaseImpl::ViEBaseImpl() Ctor");
65}
66
67ViEBaseImpl::~ViEBaseImpl() {
68 WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_.instance_id(),
69 "ViEBaseImpl::ViEBaseImpl() Dtor");
70}
71
72int ViEBaseImpl::Init() {
73 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, shared_data_.instance_id(),
74 "Init");
75 if (shared_data_.Initialized()) {
76 WEBRTC_TRACE(kTraceWarning, kTraceVideo, shared_data_.instance_id(),
77 "Init called twice");
78 return 0;
79 }
80
81 shared_data_.SetInitialized();
82 return 0;
83}
84
85int ViEBaseImpl::SetVoiceEngine(VoiceEngine* voice_engine) {
86 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
87 "%s", __FUNCTION__);
88 if (!(shared_data_.Initialized())) {
89 shared_data_.SetLastError(kViENotInitialized);
90 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
91 "%s - ViE instance %d not initialized", __FUNCTION__,
92 shared_data_.instance_id());
93 return -1;
94 }
95
96 if (shared_data_.channel_manager()->SetVoiceEngine(voice_engine) != 0) {
97 shared_data_.SetLastError(kViEBaseVoEFailure);
98 return -1;
99 }
100 return 0;
101}
102
103int ViEBaseImpl::CreateChannel(int& video_channel) { // NOLINT
104 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
105 "%s", __FUNCTION__);
106
107 if (!(shared_data_.Initialized())) {
108 shared_data_.SetLastError(kViENotInitialized);
109 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
110 "%s - ViE instance %d not initialized", __FUNCTION__,
111 shared_data_.instance_id());
112 return -1;
113 }
114
115 if (shared_data_.channel_manager()->CreateChannel(&video_channel) == -1) {
116 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
117 "%s: Could not create channel", __FUNCTION__);
118 video_channel = -1;
119 shared_data_.SetLastError(kViEBaseChannelCreationFailed);
120 return -1;
121 }
122 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(shared_data_.instance_id()),
123 "%s: channel created: %d", __FUNCTION__, video_channel);
124 return 0;
125}
126
127int ViEBaseImpl::CreateChannel(int& video_channel, // NOLINT
128 int original_channel) {
129 return CreateChannel(video_channel, original_channel, true);
130}
131
132int ViEBaseImpl::CreateReceiveChannel(int& video_channel, // NOLINT
133 int original_channel) {
134 return CreateChannel(video_channel, original_channel, false);
135}
136
137int ViEBaseImpl::DeleteChannel(const int video_channel) {
138 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
139 "%s(%d)", __FUNCTION__, video_channel);
140
141 if (!(shared_data_.Initialized())) {
142 shared_data_.SetLastError(kViENotInitialized);
143 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
144 "%s - ViE instance %d not initialized", __FUNCTION__,
145 shared_data_.instance_id());
146 return -1;
147 }
148
149 {
150 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
151 ViEChannel* vie_channel = cs.Channel(video_channel);
152 if (!vie_channel) {
153 WEBRTC_TRACE(kTraceError, kTraceVideo,
154 ViEId(shared_data_.instance_id()),
155 "%s: channel %d doesn't exist", __FUNCTION__, video_channel);
156 shared_data_.SetLastError(kViEBaseInvalidChannelId);
157 return -1;
158 }
159
160 // Deregister the ViEEncoder if no other channel is using it.
161 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
162 if (cs.ChannelUsingViEEncoder(video_channel) == false) {
163 ViEInputManagerScoped is(*(shared_data_.input_manager()));
164 ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
165 if (provider) {
166 provider->DeregisterFrameCallback(vie_encoder);
167 }
168 }
169 }
170
171 if (shared_data_.channel_manager()->DeleteChannel(video_channel) == -1) {
172 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
173 "%s: Could not delete channel %d", __FUNCTION__,
174 video_channel);
175 shared_data_.SetLastError(kViEBaseUnknownError);
176 return -1;
177 }
178 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(shared_data_.instance_id()),
179 "%s: channel deleted: %d", __FUNCTION__, video_channel);
180 return 0;
181}
182
183int ViEBaseImpl::ConnectAudioChannel(const int video_channel,
184 const int audio_channel) {
185 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
186 "%s(%d)", __FUNCTION__, video_channel);
187
188 if (!(shared_data_.Initialized())) {
189 shared_data_.SetLastError(kViENotInitialized);
190 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
191 "%s - ViE instance %d not initialized", __FUNCTION__,
192 shared_data_.instance_id());
193 return -1;
194 }
195
196 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
197 if (!cs.Channel(video_channel)) {
198 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
199 "%s: channel %d doesn't exist", __FUNCTION__, video_channel);
200 shared_data_.SetLastError(kViEBaseInvalidChannelId);
201 return -1;
202 }
203
204 if (shared_data_.channel_manager()->ConnectVoiceChannel(video_channel,
205 audio_channel) != 0) {
206 shared_data_.SetLastError(kViEBaseVoEFailure);
207 return -1;
208 }
209 return 0;
210}
211
212int ViEBaseImpl::DisconnectAudioChannel(const int video_channel) {
213 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
214 "%s(%d)", __FUNCTION__, video_channel);
215 if (!(shared_data_.Initialized())) {
216 shared_data_.SetLastError(kViENotInitialized);
217 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
218 "%s - ViE instance %d not initialized", __FUNCTION__,
219 shared_data_.instance_id());
220 return -1;
221 }
222 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
223 if (!cs.Channel(video_channel)) {
224 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
225 "%s: channel %d doesn't exist", __FUNCTION__, video_channel);
226 shared_data_.SetLastError(kViEBaseInvalidChannelId);
227 return -1;
228 }
229
230 if (shared_data_.channel_manager()->DisconnectVoiceChannel(
231 video_channel) != 0) {
232 shared_data_.SetLastError(kViEBaseVoEFailure);
233 return -1;
234 }
235 return 0;
236}
237
238int ViEBaseImpl::StartSend(const int video_channel) {
239 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
240 ViEId(shared_data_.instance_id(), video_channel),
241 "%s(channel: %d)", __FUNCTION__, video_channel);
242
243 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
244 ViEChannel* vie_channel = cs.Channel(video_channel);
245 if (!vie_channel) {
246 WEBRTC_TRACE(kTraceError, kTraceVideo,
247 ViEId(shared_data_.instance_id(), video_channel),
248 "%s: Channel %d does not exist", __FUNCTION__, video_channel);
249 shared_data_.SetLastError(kViEBaseInvalidChannelId);
250 return -1;
251 }
252
253 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
254 assert(vie_encoder != NULL);
255 if (vie_encoder->Owner() != video_channel) {
256 WEBRTC_TRACE(kTraceError, kTraceVideo,
257 ViEId(shared_data_.instance_id(), video_channel),
258 "Can't start ssend on a receive only channel.");
259 shared_data_.SetLastError(kViEBaseReceiveOnlyChannel);
260 return -1;
261 }
262
263 // Pause and trigger a key frame.
264 vie_encoder->Pause();
pbos@webrtc.org2a5d2292013-04-09 13:41:51 +0000265 int32_t error = vie_channel->StartSend();
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000266 if (error != 0) {
267 vie_encoder->Restart();
268 WEBRTC_TRACE(kTraceError, kTraceVideo,
269 ViEId(shared_data_.instance_id(), video_channel),
270 "%s: Could not start sending on channel %d", __FUNCTION__,
271 video_channel);
272 if (error == kViEBaseAlreadySending) {
273 shared_data_.SetLastError(kViEBaseAlreadySending);
274 }
275 shared_data_.SetLastError(kViEBaseUnknownError);
276 return -1;
277 }
278 vie_encoder->SendKeyFrame();
279 vie_encoder->Restart();
280 return 0;
281}
282
283int ViEBaseImpl::StopSend(const int video_channel) {
284 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
285 ViEId(shared_data_.instance_id(), video_channel),
286 "%s(channel: %d)", __FUNCTION__, video_channel);
287
288 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
289 ViEChannel* vie_channel = cs.Channel(video_channel);
290 if (!vie_channel) {
291 WEBRTC_TRACE(kTraceError, kTraceVideo,
292 ViEId(shared_data_.instance_id(), video_channel),
293 "%s: Channel %d does not exist", __FUNCTION__, video_channel);
294 shared_data_.SetLastError(kViEBaseInvalidChannelId);
295 return -1;
296 }
297
pbos@webrtc.org2a5d2292013-04-09 13:41:51 +0000298 int32_t error = vie_channel->StopSend();
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000299 if (error != 0) {
300 WEBRTC_TRACE(kTraceError, kTraceVideo,
301 ViEId(shared_data_.instance_id(), video_channel),
302 "%s: Could not stop sending on channel %d", __FUNCTION__,
303 video_channel);
304 if (error == kViEBaseNotSending) {
305 shared_data_.SetLastError(kViEBaseNotSending);
306 } else {
307 shared_data_.SetLastError(kViEBaseUnknownError);
308 }
309 return -1;
310 }
311 return 0;
312}
313
314int ViEBaseImpl::StartReceive(const int video_channel) {
315 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
316 ViEId(shared_data_.instance_id(), video_channel),
317 "%s(channel: %d)", __FUNCTION__, video_channel);
318
319 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
320 ViEChannel* vie_channel = cs.Channel(video_channel);
321 if (!vie_channel) {
322 WEBRTC_TRACE(kTraceError, kTraceVideo,
323 ViEId(shared_data_.instance_id(), video_channel),
324 "%s: Channel %d does not exist", __FUNCTION__, video_channel);
325 shared_data_.SetLastError(kViEBaseInvalidChannelId);
326 return -1;
327 }
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000328 if (vie_channel->StartReceive() != 0) {
329 shared_data_.SetLastError(kViEBaseUnknownError);
330 return -1;
331 }
332 return 0;
333}
334
335int ViEBaseImpl::StopReceive(const int video_channel) {
336 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
337 ViEId(shared_data_.instance_id(), video_channel),
338 "%s(channel: %d)", __FUNCTION__, video_channel);
339
340 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
341 ViEChannel* vie_channel = cs.Channel(video_channel);
342 if (!vie_channel) {
343 WEBRTC_TRACE(kTraceError, kTraceVideo,
344 ViEId(shared_data_.instance_id(), video_channel),
345 "%s: Channel %d does not exist", __FUNCTION__, video_channel);
346 shared_data_.SetLastError(kViEBaseInvalidChannelId);
347 return -1;
348 }
349 if (vie_channel->StopReceive() != 0) {
350 shared_data_.SetLastError(kViEBaseUnknownError);
351 return -1;
352 }
353 return 0;
354}
355
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000356int ViEBaseImpl::GetVersion(char version[1024]) {
357 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
358 "GetVersion(version=?)");
359 assert(kViEVersionMaxMessageSize == 1024);
360 if (!version) {
361 shared_data_.SetLastError(kViEBaseInvalidArgument);
362 return -1;
363 }
364
365 // Add WebRTC Version.
366 std::stringstream version_stream;
elham@webrtc.orge0aad3c2013-05-03 23:11:37 +0000367 version_stream << "VideoEngine 3.30.0" << std::endl;
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000368
369 // Add build info.
370 version_stream << "Build: svn:" << WEBRTC_SVNREVISION << " " << BUILDINFO
371 << std::endl;
372
373#ifdef WEBRTC_EXTERNAL_TRANSPORT
374 version_stream << "External transport build" << std::endl;
375#endif
376 int version_length = version_stream.tellp();
377 assert(version_length < 1024);
378 memcpy(version, version_stream.str().c_str(), version_length);
379 version[version_length] = '\0';
380
381 WEBRTC_TRACE(kTraceStateInfo, kTraceVideo,
382 ViEId(shared_data_.instance_id()), "GetVersion() => %s",
383 version);
384 return 0;
385}
386
387int ViEBaseImpl::LastError() {
388 return shared_data_.LastErrorInternal();
389}
390
391int ViEBaseImpl::CreateChannel(int& video_channel, // NOLINT
392 int original_channel, bool sender) {
393 if (!(shared_data_.Initialized())) {
394 shared_data_.SetLastError(kViENotInitialized);
395 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
396 "%s - ViE instance %d not initialized", __FUNCTION__,
397 shared_data_.instance_id());
398 return -1;
399 }
400
401 ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
402 if (!cs.Channel(original_channel)) {
403 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
404 "%s - original_channel does not exist.", __FUNCTION__,
405 shared_data_.instance_id());
406 shared_data_.SetLastError(kViEBaseInvalidChannelId);
407 return -1;
408 }
409
410 if (shared_data_.channel_manager()->CreateChannel(&video_channel,
411 original_channel,
412 sender) == -1) {
413 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
414 "%s: Could not create channel", __FUNCTION__);
415 video_channel = -1;
416 shared_data_.SetLastError(kViEBaseChannelCreationFailed);
417 return -1;
418 }
419 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(shared_data_.instance_id()),
420 "%s: channel created: %d", __FUNCTION__, video_channel);
421 return 0;
422}
423
424} // namespace webrtc