blob: 81736d64e968a93585e6d53c63fe39181af751c4 [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_codec_impl.h"
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000012
mflodman@webrtc.orgb6d9cfc2012-10-25 11:30:29 +000013#include <list>
14
pbos@webrtc.org281cff82013-05-17 13:44:48 +000015#include "webrtc/engine_configurations.h"
16#include "webrtc/modules/video_coding/main/interface/video_coding.h"
17#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.org281cff82013-05-17 13:44:48 +000018#include "webrtc/video_engine/include/vie_errors.h"
19#include "webrtc/video_engine/vie_capturer.h"
20#include "webrtc/video_engine/vie_channel.h"
21#include "webrtc/video_engine/vie_channel_manager.h"
22#include "webrtc/video_engine/vie_defines.h"
23#include "webrtc/video_engine/vie_encoder.h"
24#include "webrtc/video_engine/vie_impl.h"
25#include "webrtc/video_engine/vie_input_manager.h"
26#include "webrtc/video_engine/vie_shared_data.h"
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000027
28namespace webrtc {
29
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000030static void LogCodec(const VideoCodec& codec) {
31 LOG(LS_INFO) << "CodecType " << codec.codecType
asapersson@webrtc.org1d95c5a2014-04-25 07:02:52 +000032 << ", pl_type " << static_cast<int>(codec.plType)
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000033 << ", resolution " << codec.width
34 << " x " << codec.height
35 << ", start br " << codec.startBitrate
36 << ", min br " << codec.minBitrate
37 << ", max br " << codec.maxBitrate
asapersson@webrtc.org1d95c5a2014-04-25 07:02:52 +000038 << ", max fps " << static_cast<int>(codec.maxFramerate)
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000039 << ", max qp " << codec.qpMax
40 << ", number of streams "
asapersson@webrtc.org1d95c5a2014-04-25 07:02:52 +000041 << static_cast<int>(codec.numberOfSimulcastStreams);
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000042 if (codec.codecType == kVideoCodecVP8) {
43 LOG(LS_INFO) << "VP8 specific settings";
asapersson@webrtc.org1d95c5a2014-04-25 07:02:52 +000044 LOG(LS_INFO) << "pictureLossIndicationOn "
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000045 << codec.codecSpecific.VP8.pictureLossIndicationOn
46 << ", feedbackModeOn "
47 << codec.codecSpecific.VP8.feedbackModeOn
48 << ", complexity "
49 << codec.codecSpecific.VP8.complexity
50 << ", resilience "
51 << codec.codecSpecific.VP8.resilience
asapersson@webrtc.org1d95c5a2014-04-25 07:02:52 +000052 << ", numberOfTemporalLayers "
53 << static_cast<int>(
54 codec.codecSpecific.VP8.numberOfTemporalLayers)
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000055 << ", keyFrameinterval "
56 << codec.codecSpecific.VP8.keyFrameInterval;
57 for (int idx = 0; idx < codec.numberOfSimulcastStreams; ++idx) {
58 LOG(LS_INFO) << "Stream " << codec.simulcastStream[idx].width
59 << " x " << codec.simulcastStream[idx].height;
60 LOG(LS_INFO) << "Temporal layers "
asapersson@webrtc.org1d95c5a2014-04-25 07:02:52 +000061 << static_cast<int>(
62 codec.simulcastStream[idx].numberOfTemporalLayers)
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000063 << ", min br "
64 << codec.simulcastStream[idx].minBitrate
65 << ", target br "
66 << codec.simulcastStream[idx].targetBitrate
67 << ", max br "
68 << codec.simulcastStream[idx].maxBitrate
69 << ", qp max "
70 << codec.simulcastStream[idx].qpMax;
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000071 }
stefan@webrtc.org2d4a80c2014-07-04 12:42:07 +000072 } else if (codec.codecType == kVideoCodecH264) {
73 LOG(LS_INFO) << "H264 specific settings";
74 LOG(LS_INFO) << "profile: "
75 << codec.codecSpecific.H264.profile
76 << ", framedropping: "
77 << codec.codecSpecific.H264.frameDroppingOn
78 << ", keyFrameInterval: "
79 << codec.codecSpecific.H264.keyFrameInterval
80 << ", spslen: "
81 << codec.codecSpecific.H264.spsLen
82 << ", ppslen: "
83 << codec.codecSpecific.H264.ppsLen;
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000084 }
85}
86
87
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000088ViECodec* ViECodec::GetInterface(VideoEngine* video_engine) {
89#ifdef WEBRTC_VIDEO_ENGINE_CODEC_API
90 if (!video_engine) {
91 return NULL;
92 }
andrew@webrtc.org7ab72682013-05-09 02:12:07 +000093 VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000094 ViECodecImpl* vie_codec_impl = vie_impl;
95 // Increase ref count.
96 (*vie_codec_impl)++;
97 return vie_codec_impl;
98#else
99 return NULL;
100#endif
101}
102
103int ViECodecImpl::Release() {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000104 LOG(LS_INFO) << "ViECodec::Release.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000105 // Decrease ref count.
106 (*this)--;
107
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000108 int32_t ref_count = GetCount();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000109 if (ref_count < 0) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000110 LOG(LS_WARNING) << "ViECodec released too many times.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000111 shared_data_->SetLastError(kViEAPIDoesNotExist);
112 return -1;
113 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000114 return ref_count;
115}
116
117ViECodecImpl::ViECodecImpl(ViESharedData* shared_data)
118 : shared_data_(shared_data) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000119}
120
121ViECodecImpl::~ViECodecImpl() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000122}
123
124int ViECodecImpl::NumberOfCodecs() const {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000125 // +2 because of FEC(RED and ULPFEC)
126 return static_cast<int>((VideoCodingModule::NumberOfCodecs() + 2));
127}
128
129int ViECodecImpl::GetCodec(const unsigned char list_number,
130 VideoCodec& video_codec) const {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000131 if (list_number == VideoCodingModule::NumberOfCodecs()) {
132 memset(&video_codec, 0, sizeof(VideoCodec));
mflodman@webrtc.orgbea854a2013-04-22 12:41:57 +0000133 strcpy(video_codec.plName, "red");
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000134 video_codec.codecType = kVideoCodecRED;
135 video_codec.plType = VCM_RED_PAYLOAD_TYPE;
136 } else if (list_number == VideoCodingModule::NumberOfCodecs() + 1) {
137 memset(&video_codec, 0, sizeof(VideoCodec));
mflodman@webrtc.orgbea854a2013-04-22 12:41:57 +0000138 strcpy(video_codec.plName, "ulpfec");
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000139 video_codec.codecType = kVideoCodecULPFEC;
140 video_codec.plType = VCM_ULPFEC_PAYLOAD_TYPE;
141 } else if (VideoCodingModule::Codec(list_number, &video_codec) != VCM_OK) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000142 shared_data_->SetLastError(kViECodecInvalidArgument);
143 return -1;
144 }
145 return 0;
146}
147
148int ViECodecImpl::SetSendCodec(const int video_channel,
149 const VideoCodec& video_codec) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000150 LOG(LS_INFO) << "SetSendCodec for channel " << video_channel;
151 LogCodec(video_codec);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000152 if (!CodecValid(video_codec)) {
153 // Error logged.
154 shared_data_->SetLastError(kViECodecInvalidCodec);
155 return -1;
156 }
157
158 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
159 ViEChannel* vie_channel = cs.Channel(video_channel);
160 if (!vie_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000161 shared_data_->SetLastError(kViECodecInvalidChannelId);
162 return -1;
163 }
164
165 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
166 assert(vie_encoder);
167 if (vie_encoder->Owner() != video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000168 LOG_F(LS_ERROR) << "Receive only channel.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000169 shared_data_->SetLastError(kViECodecReceiveOnlyChannel);
170 return -1;
171 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000172 // Set a max_bitrate if the user hasn't set one.
173 VideoCodec video_codec_internal;
174 memcpy(&video_codec_internal, &video_codec, sizeof(VideoCodec));
175 if (video_codec_internal.maxBitrate == 0) {
176 // Max is one bit per pixel.
177 video_codec_internal.maxBitrate = (video_codec_internal.width *
178 video_codec_internal.height *
179 video_codec_internal.maxFramerate)
180 / 1000;
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000181 LOG(LS_INFO) << "New max bitrate set " << video_codec_internal.maxBitrate;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000182 }
183
mflodman@webrtc.org54352082014-04-29 12:38:42 +0000184 if (video_codec_internal.startBitrate < video_codec_internal.minBitrate) {
185 video_codec_internal.startBitrate = video_codec_internal.minBitrate;
186 }
mflodman@webrtc.orga9a73272013-12-20 15:07:12 +0000187 if (video_codec_internal.startBitrate > video_codec_internal.maxBitrate) {
188 video_codec_internal.startBitrate = video_codec_internal.maxBitrate;
189 }
190
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000191 VideoCodec encoder;
192 vie_encoder->GetEncoder(&encoder);
193
194 // Make sure to generate a new SSRC if the codec type and/or resolution has
195 // changed. This won't have any effect if the user has set an SSRC.
196 bool new_rtp_stream = false;
197 if (encoder.codecType != video_codec_internal.codecType) {
198 new_rtp_stream = true;
199 }
200
201 ViEInputManagerScoped is(*(shared_data_->input_manager()));
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000202
203 // Stop the media flow while reconfiguring.
204 vie_encoder->Pause();
205
mflodman@webrtc.orga18c6e52013-06-07 13:57:57 +0000206 if (vie_encoder->SetEncoder(video_codec_internal) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000207 shared_data_->SetLastError(kViECodecUnknownError);
208 return -1;
209 }
210
211 // Give the channel(s) the new information.
212 ChannelList channels;
213 cs.ChannelsUsingViEEncoder(video_channel, &channels);
214 for (ChannelList::iterator it = channels.begin(); it != channels.end();
215 ++it) {
216 bool ret = true;
217 if ((*it)->SetSendCodec(video_codec_internal, new_rtp_stream) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000218 ret = false;
219 }
220 if (!ret) {
221 shared_data_->SetLastError(kViECodecUnknownError);
222 return -1;
223 }
224 }
225
mflodman@webrtc.orgb6d9cfc2012-10-25 11:30:29 +0000226 // TODO(mflodman) Break out this part in GetLocalSsrcList().
227 // Update all SSRCs to ViEEncoder.
228 std::list<unsigned int> ssrcs;
229 if (video_codec_internal.numberOfSimulcastStreams == 0) {
230 unsigned int ssrc = 0;
231 if (vie_channel->GetLocalSSRC(0, &ssrc) != 0) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000232 LOG_F(LS_ERROR) << "Could not get ssrc.";
mflodman@webrtc.orgb6d9cfc2012-10-25 11:30:29 +0000233 }
234 ssrcs.push_back(ssrc);
235 } else {
236 for (int idx = 0; idx < video_codec_internal.numberOfSimulcastStreams;
237 ++idx) {
238 unsigned int ssrc = 0;
239 if (vie_channel->GetLocalSSRC(idx, &ssrc) != 0) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000240 LOG_F(LS_ERROR) << "Could not get ssrc for stream " << idx;
mflodman@webrtc.orgb6d9cfc2012-10-25 11:30:29 +0000241 }
242 ssrcs.push_back(ssrc);
243 }
244 }
245 vie_encoder->SetSsrcs(ssrcs);
246 shared_data_->channel_manager()->UpdateSsrcs(video_channel, ssrcs);
247
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000248 // Update the protection mode, we might be switching NACK/FEC.
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000249 vie_encoder->UpdateProtectionMethod(vie_encoder->nack_enabled());
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000250
251 // Get new best format for frame provider.
pbos@webrtc.org87045952013-08-05 09:03:03 +0000252 ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000253 if (frame_provider) {
254 frame_provider->FrameCallbackChanged();
255 }
256 // Restart the media flow
257 if (new_rtp_stream) {
258 // Stream settings changed, make sure we get a key frame.
259 vie_encoder->SendKeyFrame();
260 }
261 vie_encoder->Restart();
262 return 0;
263}
264
265int ViECodecImpl::GetSendCodec(const int video_channel,
266 VideoCodec& video_codec) const {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000267 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
268 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
269 if (!vie_encoder) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000270 shared_data_->SetLastError(kViECodecInvalidChannelId);
271 return -1;
272 }
273 return vie_encoder->GetEncoder(&video_codec);
274}
275
276int ViECodecImpl::SetReceiveCodec(const int video_channel,
277 const VideoCodec& video_codec) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000278 LOG(LS_INFO) << "SetReceiveCodec for channel " << video_channel;
279 LOG(LS_INFO) << "Codec type " << video_codec.codecType
280 << ", payload type " << video_codec.plType;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000281
282 if (CodecValid(video_codec) == false) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000283 shared_data_->SetLastError(kViECodecInvalidCodec);
284 return -1;
285 }
286
287 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
288 ViEChannel* vie_channel = cs.Channel(video_channel);
289 if (!vie_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000290 shared_data_->SetLastError(kViECodecInvalidChannelId);
291 return -1;
292 }
293
294 if (vie_channel->SetReceiveCodec(video_codec) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000295 shared_data_->SetLastError(kViECodecUnknownError);
296 return -1;
297 }
298 return 0;
299}
300
301int ViECodecImpl::GetReceiveCodec(const int video_channel,
302 VideoCodec& video_codec) const {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000303 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(kViECodecInvalidChannelId);
307 return -1;
308 }
309
310 if (vie_channel->GetReceiveCodec(&video_codec) != 0) {
311 shared_data_->SetLastError(kViECodecUnknownError);
312 return -1;
313 }
314 return 0;
315}
316
317int ViECodecImpl::GetCodecConfigParameters(
318 const int video_channel,
319 unsigned char config_parameters[kConfigParameterSize],
320 unsigned char& config_parameters_size) const {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000321 LOG(LS_INFO) << "GetCodecConfigParameters " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000322
323 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
324 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
325 if (!vie_encoder) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000326 shared_data_->SetLastError(kViECodecInvalidChannelId);
327 return -1;
328 }
329
330 if (vie_encoder->GetCodecConfigParameters(config_parameters,
331 config_parameters_size) != 0) {
332 shared_data_->SetLastError(kViECodecUnknownError);
333 return -1;
334 }
335 return 0;
336}
337
338int ViECodecImpl::SetImageScaleStatus(const int video_channel,
339 const bool enable) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000340 LOG(LS_INFO) << "SetImageScaleStates for channel " << video_channel
341 << ", enable: " << enable;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000342
343 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
344 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
345 if (!vie_encoder) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000346 shared_data_->SetLastError(kViECodecInvalidChannelId);
347 return -1;
348 }
349
350 if (vie_encoder->ScaleInputImage(enable) != 0) {
351 shared_data_->SetLastError(kViECodecUnknownError);
352 return -1;
353 }
354 return 0;
355}
356
357int ViECodecImpl::GetSendCodecStastistics(const int video_channel,
358 unsigned int& key_frames,
359 unsigned int& delta_frames) const {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000360 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
361 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
362 if (!vie_encoder) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000363 shared_data_->SetLastError(kViECodecInvalidChannelId);
364 return -1;
365 }
366
367 if (vie_encoder->SendCodecStatistics(&key_frames, &delta_frames) != 0) {
368 shared_data_->SetLastError(kViECodecUnknownError);
369 return -1;
370 }
371 return 0;
372}
373
374int ViECodecImpl::GetReceiveCodecStastistics(const int video_channel,
375 unsigned int& key_frames,
376 unsigned int& delta_frames) const {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000377 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
378 ViEChannel* vie_channel = cs.Channel(video_channel);
379 if (!vie_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000380 shared_data_->SetLastError(kViECodecInvalidChannelId);
381 return -1;
382 }
383 if (vie_channel->ReceiveCodecStatistics(&key_frames, &delta_frames) != 0) {
384 shared_data_->SetLastError(kViECodecUnknownError);
385 return -1;
386 }
387 return 0;
388}
389
mflodman@webrtc.orgf314c802012-12-14 14:02:10 +0000390int ViECodecImpl::GetReceiveSideDelay(const int video_channel,
391 int* delay_ms) const {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000392 assert(delay_ms != NULL);
mflodman@webrtc.orgf314c802012-12-14 14:02:10 +0000393
394 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
395 ViEChannel* vie_channel = cs.Channel(video_channel);
396 if (!vie_channel) {
mflodman@webrtc.orgf314c802012-12-14 14:02:10 +0000397 shared_data_->SetLastError(kViECodecInvalidChannelId);
398 return -1;
399 }
400 *delay_ms = vie_channel->ReceiveDelay();
401 if (*delay_ms < 0) {
402 return -1;
403 }
404 return 0;
405}
406
407
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000408int ViECodecImpl::GetCodecTargetBitrate(const int video_channel,
409 unsigned int* bitrate) const {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000410 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
411 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
412 if (!vie_encoder) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000413 shared_data_->SetLastError(kViECodecInvalidChannelId);
414 return -1;
415 }
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000416 return vie_encoder->CodecTargetBitrate(static_cast<uint32_t*>(bitrate));
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000417}
418
419unsigned int ViECodecImpl::GetDiscardedPackets(const int video_channel) const {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000420 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
421 ViEChannel* vie_channel = cs.Channel(video_channel);
422 if (!vie_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000423 shared_data_->SetLastError(kViECodecInvalidChannelId);
tommi@webrtc.org9fbd3ec2014-07-11 19:09:59 +0000424 return static_cast<unsigned int>(-1);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000425 }
426 return vie_channel->DiscardedPackets();
427}
428
429int ViECodecImpl::SetKeyFrameRequestCallbackStatus(const int video_channel,
430 const bool enable) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000431 LOG(LS_INFO) << "SetKeyFrameRequestCallbackStatus for " << video_channel
432 << ", enacle " << enable;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000433
434 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
435 ViEChannel* vie_channel = cs.Channel(video_channel);
436 if (!vie_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000437 shared_data_->SetLastError(kViECodecInvalidChannelId);
438 return -1;
439 }
440 if (vie_channel->EnableKeyFrameRequestCallback(enable) != 0) {
441 shared_data_->SetLastError(kViECodecUnknownError);
442 return -1;
443 }
444 return 0;
445}
446
447int ViECodecImpl::SetSignalKeyPacketLossStatus(const int video_channel,
448 const bool enable,
449 const bool only_key_frames) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000450 LOG(LS_INFO) << "SetSignalKeyPacketLossStatus for " << video_channel
451 << "enable, " << enable
452 << ", only key frames " << only_key_frames;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000453
454 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
455 ViEChannel* vie_channel = cs.Channel(video_channel);
456 if (!vie_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000457 shared_data_->SetLastError(kViECodecInvalidChannelId);
458 return -1;
459 }
460 if (vie_channel->SetSignalPacketLossStatus(enable, only_key_frames) != 0) {
461 shared_data_->SetLastError(kViECodecUnknownError);
462 return -1;
463 }
464 return 0;
465}
466
467int ViECodecImpl::RegisterEncoderObserver(const int video_channel,
468 ViEEncoderObserver& observer) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000469 LOG(LS_INFO) << "RegisterEncoderObserver for channel " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000470
471 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
472 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
473 if (!vie_encoder) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000474 shared_data_->SetLastError(kViECodecInvalidChannelId);
475 return -1;
476 }
477 if (vie_encoder->RegisterCodecObserver(&observer) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000478 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
479 return -1;
480 }
481 return 0;
482}
483
484int ViECodecImpl::DeregisterEncoderObserver(const int video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000485 LOG(LS_INFO) << "DeregisterEncoderObserver for channel " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000486
487 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
488 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
489 if (!vie_encoder) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000490 shared_data_->SetLastError(kViECodecInvalidChannelId);
491 return -1;
492 }
493 if (vie_encoder->RegisterCodecObserver(NULL) != 0) {
494 shared_data_->SetLastError(kViECodecObserverNotRegistered);
495 return -1;
496 }
497 return 0;
498}
499
500int ViECodecImpl::RegisterDecoderObserver(const int video_channel,
501 ViEDecoderObserver& observer) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000502 LOG(LS_INFO) << "RegisterDecoderObserver for channel " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000503
504 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
505 ViEChannel* vie_channel = cs.Channel(video_channel);
506 if (!vie_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000507 shared_data_->SetLastError(kViECodecInvalidChannelId);
508 return -1;
509 }
510 if (vie_channel->RegisterCodecObserver(&observer) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000511 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
512 return -1;
513 }
514 return 0;
515}
516
517int ViECodecImpl::DeregisterDecoderObserver(const int video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000518 LOG(LS_INFO) << "DeregisterDecodeObserver for channel " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000519
520 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
521 ViEChannel* vie_channel = cs.Channel(video_channel);
522 if (!vie_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000523 shared_data_->SetLastError(kViECodecInvalidChannelId);
524 return -1;
525 }
526 if (vie_channel->RegisterCodecObserver(NULL) != 0) {
527 shared_data_->SetLastError(kViECodecObserverNotRegistered);
528 return -1;
529 }
530 return 0;
531}
532
533int ViECodecImpl::SendKeyFrame(const int video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000534 LOG(LS_INFO) << "SendKeyFrame on channel " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000535
536 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
537 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
538 if (!vie_encoder) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000539 shared_data_->SetLastError(kViECodecInvalidChannelId);
540 return -1;
541 }
542 if (vie_encoder->SendKeyFrame() != 0) {
543 shared_data_->SetLastError(kViECodecUnknownError);
544 return -1;
545 }
546 return 0;
547}
548
549int ViECodecImpl::WaitForFirstKeyFrame(const int video_channel,
550 const bool wait) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000551 LOG(LS_INFO) << "WaitForFirstKeyFrame for channel " << video_channel
552 << ", wait " << wait;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000553
554 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
555 ViEChannel* vie_channel = cs.Channel(video_channel);
556 if (!vie_channel) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000557 shared_data_->SetLastError(kViECodecInvalidChannelId);
558 return -1;
559 }
560 if (vie_channel->WaitForKeyFrame(wait) != 0) {
561 shared_data_->SetLastError(kViECodecUnknownError);
562 return -1;
563 }
564 return 0;
565}
566
mflodman@webrtc.org0291c802013-06-26 09:12:49 +0000567int ViECodecImpl::StartDebugRecording(int video_channel,
568 const char* file_name_utf8) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000569 LOG(LS_INFO) << "StartDebugRecording for channel " << video_channel;
mflodman@webrtc.org0291c802013-06-26 09:12:49 +0000570 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
571 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
572 if (!vie_encoder) {
mflodman@webrtc.org0291c802013-06-26 09:12:49 +0000573 return -1;
574 }
575 return vie_encoder->StartDebugRecording(file_name_utf8);
576}
577
578int ViECodecImpl::StopDebugRecording(int video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000579 LOG(LS_INFO) << "StopDebugRecording for channel " << video_channel;
mflodman@webrtc.org0291c802013-06-26 09:12:49 +0000580 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
581 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
582 if (!vie_encoder) {
mflodman@webrtc.org0291c802013-06-26 09:12:49 +0000583 return -1;
584 }
585 return vie_encoder->StopDebugRecording();
586}
587
henrik.lundin@webrtc.org45901772013-11-18 12:18:43 +0000588void ViECodecImpl::SuspendBelowMinBitrate(int video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000589 LOG(LS_INFO) << "SuspendBelowMinBitrate for channel " << video_channel;
henrik.lundin@webrtc.org39079d12013-10-02 13:34:26 +0000590 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
591 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
592 if (!vie_encoder) {
henrik.lundin@webrtc.org39079d12013-10-02 13:34:26 +0000593 return;
594 }
henrik.lundin@webrtc.orgb9f1eb82013-11-21 14:05:40 +0000595 vie_encoder->SuspendBelowMinBitrate();
596 ViEChannel* vie_channel = cs.Channel(video_channel);
597 if (!vie_channel) {
henrik.lundin@webrtc.orgb9f1eb82013-11-21 14:05:40 +0000598 return;
599 }
600 // Must enable pacing when enabling SuspendBelowMinBitrate. Otherwise, no
601 // padding will be sent when the video is suspended so the video will be
602 // unable to recover.
603 vie_channel->SetTransmissionSmoothingStatus(true);
henrik.lundin@webrtc.org39079d12013-10-02 13:34:26 +0000604}
605
stefan@webrtc.orgee234be2013-12-05 14:05:07 +0000606bool ViECodecImpl::GetSendSideDelay(int video_channel, int* avg_delay_ms,
607 int* max_delay_ms) const {
608 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
609 ViEChannel* vie_channel = cs.Channel(video_channel);
610 if (!vie_channel) {
stefan@webrtc.orgee234be2013-12-05 14:05:07 +0000611 shared_data_->SetLastError(kViECodecInvalidChannelId);
612 return false;
613 }
614 return vie_channel->GetSendSideDelay(avg_delay_ms, max_delay_ms);
615}
616
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000617bool ViECodecImpl::CodecValid(const VideoCodec& video_codec) {
618 // Check pl_name matches codec_type.
619 if (video_codec.codecType == kVideoCodecRED) {
620#if defined(WIN32)
621 if (_strnicmp(video_codec.plName, "red", 3) == 0) {
622#else
623 if (strncasecmp(video_codec.plName, "red", 3) == 0) {
624#endif
625 // We only care about the type and name for red.
626 return true;
627 }
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000628 LOG_F(LS_ERROR) << "Invalid RED configuration.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000629 return false;
630 } else if (video_codec.codecType == kVideoCodecULPFEC) {
631#if defined(WIN32)
632 if (_strnicmp(video_codec.plName, "ULPFEC", 6) == 0) {
633#else
634 if (strncasecmp(video_codec.plName, "ULPFEC", 6) == 0) {
635#endif
636 // We only care about the type and name for ULPFEC.
637 return true;
638 }
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000639 LOG_F(LS_ERROR) << "Invalid ULPFEC configuration.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000640 return false;
641 } else if ((video_codec.codecType == kVideoCodecVP8 &&
pbos@webrtc.orge3339fc2013-03-18 16:39:03 +0000642 strncmp(video_codec.plName, "VP8", 4) == 0) ||
643 (video_codec.codecType == kVideoCodecI420 &&
stefan@webrtc.org2d4a80c2014-07-04 12:42:07 +0000644 strncmp(video_codec.plName, "I420", 4) == 0) ||
645 (video_codec.codecType == kVideoCodecH264 &&
646 strncmp(video_codec.plName, "H264", 4) == 0)) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000647 // OK.
pbos@webrtc.org2ed1cd92013-04-05 13:27:38 +0000648 } else if (video_codec.codecType != kVideoCodecGeneric) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000649 LOG(LS_ERROR) << "Codec type and name mismatch.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000650 return false;
651 }
652
braveyao@webrtc.orge7a9bd42013-01-14 01:52:26 +0000653 if (video_codec.plType == 0 || video_codec.plType > 127) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000654 LOG(LS_ERROR) << "Invalif payload type: " << video_codec.plType;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000655 return false;
656 }
657
658 if (video_codec.width > kViEMaxCodecWidth ||
659 video_codec.height > kViEMaxCodecHeight) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000660 LOG(LS_ERROR) << "Invalid codec resolution " << video_codec.width
661 << " x " << video_codec.height;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000662 return false;
663 }
664
665 if (video_codec.startBitrate < kViEMinCodecBitrate) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000666 LOG(LS_ERROR) << "Invalid start bitrate.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000667 return false;
668 }
669 if (video_codec.minBitrate < kViEMinCodecBitrate) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000670 LOG(LS_ERROR) << "Invalid min bitrate.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000671 return false;
672 }
673 return true;
674}
675
676} // namespace webrtc