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
11#include "webrtc/video_engine/vie_base_impl.h"
12
13#include <sstream>
14#include <string>
15#include <utility>
16
17#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"
21#include "webrtc/modules/video_render/include/video_render.h"
22#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
23#include "webrtc/system_wrappers/interface/logging.h"
24#include "webrtc/video_engine/include/vie_errors.h"
25#include "webrtc/video_engine/vie_capturer.h"
26#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"
33
34namespace webrtc {
35
36ViEBase* ViEBase::GetInterface(VideoEngine* video_engine) {
37  if (!video_engine) {
38    return NULL;
39  }
40  VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
41  ViEBaseImpl* vie_base_impl = vie_impl;
42  (*vie_base_impl)++;  // Increase ref count.
43
44  return vie_base_impl;
45}
46
47int ViEBaseImpl::Release() {
48  (*this)--;  // Decrease ref count.
49
50  int32_t ref_count = GetCount();
51  if (ref_count < 0) {
52    LOG(LS_WARNING) << "ViEBase released too many times.";
53    return -1;
54  }
55  return ref_count;
56}
57
58ViEBaseImpl::ViEBaseImpl(const Config& config)
59    : shared_data_(config) {}
60
61ViEBaseImpl::~ViEBaseImpl() {}
62
63int ViEBaseImpl::Init() {
64  return 0;
65}
66
67int ViEBaseImpl::SetVoiceEngine(VoiceEngine* voice_engine) {
68  LOG_F(LS_INFO) << "SetVoiceEngine";
69  if (shared_data_.channel_manager()->SetVoiceEngine(voice_engine) != 0) {
70    shared_data_.SetLastError(kViEBaseVoEFailure);
71    return -1;
72  }
73  return 0;
74}
75
76int ViEBaseImpl::RegisterCpuOveruseObserver(int video_channel,
77                                            CpuOveruseObserver* observer) {
78  LOG_F(LS_INFO) << "RegisterCpuOveruseObserver on channel " << video_channel;
79  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
80  ViEChannel* vie_channel = cs.Channel(video_channel);
81  if (!vie_channel) {
82    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
101int 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) {
106    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
124int 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);
141      return 0;
142    }
143  }
144  return -1;
145}
146
147void 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
155int ViEBaseImpl::CreateChannel(int& video_channel) {  // NOLINT
156  return CreateChannel(video_channel, static_cast<const Config*>(NULL));
157}
158
159int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
160                               const Config* config) {
161  if (shared_data_.channel_manager()->CreateChannel(&video_channel,
162                                                    config) == -1) {
163    video_channel = -1;
164    shared_data_.SetLastError(kViEBaseChannelCreationFailed);
165    return -1;
166  }
167  LOG(LS_INFO) << "Video channel created: " << video_channel;
168  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) {
182  {
183    ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
184    ViEChannel* vie_channel = cs.Channel(video_channel);
185    if (!vie_channel) {
186      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) {
202    shared_data_.SetLastError(kViEBaseUnknownError);
203    return -1;
204  }
205  LOG(LS_INFO) << "Channel deleted " << video_channel;
206  return 0;
207}
208
209int ViEBaseImpl::ConnectAudioChannel(const int video_channel,
210                                     const int audio_channel) {
211  LOG_F(LS_INFO) << "ConnectAudioChannel, video channel " << video_channel
212                 << ", audio channel " << audio_channel;
213  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
214  if (!cs.Channel(video_channel)) {
215    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) {
228  LOG_F(LS_INFO) << "DisconnectAudioChannel " << video_channel;
229  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
230  if (!cs.Channel(video_channel)) {
231    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) {
244  LOG_F(LS_INFO) << "StartSend: " << video_channel;
245  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
246  ViEChannel* vie_channel = cs.Channel(video_channel);
247  if (!vie_channel) {
248    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) {
255    LOG_F(LS_ERROR) <<  "Can't start send on a receive only channel.";
256    shared_data_.SetLastError(kViEBaseReceiveOnlyChannel);
257    return -1;
258  }
259
260  // Pause and trigger a key frame.
261  vie_encoder->Pause();
262  int32_t error = vie_channel->StartSend();
263  if (error != 0) {
264    vie_encoder->Restart();
265    if (error == kViEBaseAlreadySending) {
266      shared_data_.SetLastError(kViEBaseAlreadySending);
267    }
268    LOG_F(LS_ERROR) << "Could not start sending " << video_channel;
269    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) {
278  LOG_F(LS_INFO) << "StopSend " << video_channel;
279
280  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
281  ViEChannel* vie_channel = cs.Channel(video_channel);
282  if (!vie_channel) {
283    shared_data_.SetLastError(kViEBaseInvalidChannelId);
284    return -1;
285  }
286
287  int32_t error = vie_channel->StopSend();
288  if (error != 0) {
289    if (error == kViEBaseNotSending) {
290      shared_data_.SetLastError(kViEBaseNotSending);
291    } else {
292      LOG_F(LS_ERROR) << "Could not stop sending " << video_channel;
293      shared_data_.SetLastError(kViEBaseUnknownError);
294    }
295    return -1;
296  }
297  return 0;
298}
299
300int ViEBaseImpl::StartReceive(const int video_channel) {
301  LOG_F(LS_INFO) << "StartReceive " << video_channel;
302
303  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
304  ViEChannel* vie_channel = cs.Channel(video_channel);
305  if (!vie_channel) {
306    shared_data_.SetLastError(kViEBaseInvalidChannelId);
307    return -1;
308  }
309  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) {
317  LOG_F(LS_INFO) << "StopReceive " << video_channel;
318  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
319  ViEChannel* vie_channel = cs.Channel(video_channel);
320  if (!vie_channel) {
321    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
331int ViEBaseImpl::GetVersion(char version[1024]) {
332  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;
340  version_stream << "VideoEngine 38" << std::endl;
341
342  // Add build info.
343  version_stream << "Build: " << BUILDINFO << std::endl;
344
345  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';
349  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) {
358  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
359  if (!cs.Channel(original_channel)) {
360    shared_data_.SetLastError(kViEBaseInvalidChannelId);
361    return -1;
362  }
363
364  if (shared_data_.channel_manager()->CreateChannel(&video_channel,
365                                                    original_channel,
366                                                    sender) == -1) {
367    video_channel = -1;
368    shared_data_.SetLastError(kViEBaseChannelCreationFailed);
369    return -1;
370  }
371  LOG_F(LS_INFO) << "VideoChannel created: " << video_channel
372                 << ", base channel " << original_channel
373                 << ", is send channel : " << sender;
374  return 0;
375}
376
377}  // namespace webrtc
378