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_codec_impl.h"
12
13 #include <list>
14
15 #include "webrtc/engine_configurations.h"
16 #include "webrtc/modules/video_coding/main/interface/video_coding.h"
17 #include "webrtc/system_wrappers/interface/logging.h"
18 #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"
27
28 namespace webrtc {
29
LogCodec(const VideoCodec & codec)30 static void LogCodec(const VideoCodec& codec) {
31 LOG(LS_INFO) << "CodecType " << codec.codecType
32 << ", pl_type " << static_cast<int>(codec.plType)
33 << ", resolution " << codec.width
34 << " x " << codec.height
35 << ", start br " << codec.startBitrate
36 << ", min br " << codec.minBitrate
37 << ", max br " << codec.maxBitrate
38 << ", max fps " << static_cast<int>(codec.maxFramerate)
39 << ", max qp " << codec.qpMax
40 << ", number of streams "
41 << static_cast<int>(codec.numberOfSimulcastStreams);
42 if (codec.codecType == kVideoCodecVP8) {
43 LOG(LS_INFO) << "VP8 specific settings";
44 LOG(LS_INFO) << "pictureLossIndicationOn "
45 << 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
52 << ", numberOfTemporalLayers "
53 << static_cast<int>(
54 codec.codecSpecific.VP8.numberOfTemporalLayers)
55 << ", 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 "
61 << static_cast<int>(
62 codec.simulcastStream[idx].numberOfTemporalLayers)
63 << ", 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;
71 }
72 } else if (codec.codecType == kVideoCodecH264) {
73 LOG(LS_INFO) << "H264 specific settings";
74 LOG(LS_INFO) << "profile: "
75 << codec.codecSpecific.H264.profile
76 << ", constraints: "
77 << codec.codecSpecific.H264.constraints
78 << ", level: "
79 << codec.codecSpecific.H264.level/10.0
80 << ", packetizationMode: "
81 << codec.codecSpecific.H264.packetizationMode
82 << ", framedropping: "
83 << codec.codecSpecific.H264.frameDroppingOn
84 << ", keyFrameInterval: "
85 << codec.codecSpecific.H264.keyFrameInterval
86 << ", spslen: "
87 << codec.codecSpecific.H264.spsLen
88 << ", ppslen: "
89 << codec.codecSpecific.H264.ppsLen;
90 } else if (codec.codecType == kVideoCodecVP9) {
91 LOG(LS_INFO) << "VP9 specific settings";
92 // XXX FIX!! log VP9 specific settings
93 }
94 }
95
96
GetInterface(VideoEngine * video_engine)97 ViECodec* ViECodec::GetInterface(VideoEngine* video_engine) {
98 #ifdef WEBRTC_VIDEO_ENGINE_CODEC_API
99 if (!video_engine) {
100 return NULL;
101 }
102 VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
103 ViECodecImpl* vie_codec_impl = vie_impl;
104 // Increase ref count.
105 (*vie_codec_impl)++;
106 return vie_codec_impl;
107 #else
108 return NULL;
109 #endif
110 }
111
Release()112 int ViECodecImpl::Release() {
113 LOG(LS_INFO) << "ViECodec::Release.";
114 // Decrease ref count.
115 (*this)--;
116
117 int32_t ref_count = GetCount();
118 if (ref_count < 0) {
119 LOG(LS_WARNING) << "ViECodec released too many times.";
120 shared_data_->SetLastError(kViEAPIDoesNotExist);
121 return -1;
122 }
123 return ref_count;
124 }
125
ViECodecImpl(ViESharedData * shared_data)126 ViECodecImpl::ViECodecImpl(ViESharedData* shared_data)
127 : shared_data_(shared_data) {
128 }
129
~ViECodecImpl()130 ViECodecImpl::~ViECodecImpl() {
131 }
132
NumberOfCodecs() const133 int ViECodecImpl::NumberOfCodecs() const {
134 // +2 because of FEC(RED and ULPFEC)
135 return static_cast<int>((VideoCodingModule::NumberOfCodecs() + 2));
136 }
137
GetCodec(const unsigned char list_number,VideoCodec & video_codec) const138 int ViECodecImpl::GetCodec(const unsigned char list_number,
139 VideoCodec& video_codec) const {
140 if (list_number == VideoCodingModule::NumberOfCodecs()) {
141 memset(&video_codec, 0, sizeof(VideoCodec));
142 strcpy(video_codec.plName, "red");
143 video_codec.codecType = kVideoCodecRED;
144 video_codec.plType = VCM_RED_PAYLOAD_TYPE;
145 } else if (list_number == VideoCodingModule::NumberOfCodecs() + 1) {
146 memset(&video_codec, 0, sizeof(VideoCodec));
147 strcpy(video_codec.plName, "ulpfec");
148 video_codec.codecType = kVideoCodecULPFEC;
149 video_codec.plType = VCM_ULPFEC_PAYLOAD_TYPE;
150 } else if (VideoCodingModule::Codec(list_number, &video_codec) != VCM_OK) {
151 shared_data_->SetLastError(kViECodecInvalidArgument);
152 return -1;
153 }
154 return 0;
155 }
156
SetSendCodec(const int video_channel,const VideoCodec & video_codec)157 int ViECodecImpl::SetSendCodec(const int video_channel,
158 const VideoCodec& video_codec) {
159 LOG(LS_INFO) << "SetSendCodec for channel " << video_channel;
160 LogCodec(video_codec);
161 if (!CodecValid(video_codec)) {
162 // Error logged.
163 shared_data_->SetLastError(kViECodecInvalidCodec);
164 return -1;
165 }
166
167 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
168 ViEChannel* vie_channel = cs.Channel(video_channel);
169 if (!vie_channel) {
170 shared_data_->SetLastError(kViECodecInvalidChannelId);
171 return -1;
172 }
173
174 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
175 assert(vie_encoder);
176 if (vie_encoder->Owner() != video_channel) {
177 LOG_F(LS_ERROR) << "Receive only channel.";
178 shared_data_->SetLastError(kViECodecReceiveOnlyChannel);
179 return -1;
180 }
181 // Set a max_bitrate if the user hasn't set one.
182 VideoCodec video_codec_internal;
183 memcpy(&video_codec_internal, &video_codec, sizeof(VideoCodec));
184 if (video_codec_internal.maxBitrate == 0) {
185 // Max is one bit per pixel.
186 video_codec_internal.maxBitrate = (video_codec_internal.width *
187 video_codec_internal.height *
188 video_codec_internal.maxFramerate)
189 / 1000;
190 LOG(LS_INFO) << "New max bitrate set " << video_codec_internal.maxBitrate;
191 }
192
193 if (video_codec_internal.startBitrate > 0) {
194 if (video_codec_internal.startBitrate < video_codec_internal.minBitrate) {
195 video_codec_internal.startBitrate = video_codec_internal.minBitrate;
196 }
197 if (video_codec_internal.startBitrate > video_codec_internal.maxBitrate) {
198 video_codec_internal.startBitrate = video_codec_internal.maxBitrate;
199 }
200 }
201
202 // Make sure to generate a new SSRC if the codec type and/or resolution has
203 // changed. This won't have any effect if the user has set an SSRC.
204 bool new_rtp_stream = true;
205 VideoCodec encoder;
206 if (vie_encoder->GetEncoder(&encoder) == 0)
207 new_rtp_stream = encoder.codecType != video_codec_internal.codecType;
208
209 ViEInputManagerScoped is(*(shared_data_->input_manager()));
210
211 // Stop the media flow while reconfiguring.
212 vie_encoder->Pause();
213
214 if (vie_encoder->SetEncoder(video_codec_internal) != 0) {
215 shared_data_->SetLastError(kViECodecUnknownError);
216 return -1;
217 }
218
219 // Give the channel(s) the new information.
220 ChannelList channels;
221 cs.ChannelsUsingViEEncoder(video_channel, &channels);
222 for (ChannelList::iterator it = channels.begin(); it != channels.end();
223 ++it) {
224 bool ret = true;
225 if ((*it)->SetSendCodec(video_codec_internal, new_rtp_stream) != 0) {
226 ret = false;
227 }
228 if (!ret) {
229 shared_data_->SetLastError(kViECodecUnknownError);
230 return -1;
231 }
232 }
233
234 // TODO(mflodman) Break out this part in GetLocalSsrcList().
235 // Update all SSRCs to ViEEncoder.
236 std::list<unsigned int> ssrcs;
237 if (video_codec_internal.numberOfSimulcastStreams == 0) {
238 unsigned int ssrc = 0;
239 if (vie_channel->GetLocalSSRC(0, &ssrc) != 0) {
240 LOG_F(LS_ERROR) << "Could not get ssrc.";
241 }
242 ssrcs.push_back(ssrc);
243 } else {
244 for (int idx = 0; idx < video_codec_internal.numberOfSimulcastStreams;
245 ++idx) {
246 unsigned int ssrc = 0;
247 if (vie_channel->GetLocalSSRC(idx, &ssrc) != 0) {
248 LOG_F(LS_ERROR) << "Could not get ssrc for stream " << idx;
249 }
250 ssrcs.push_back(ssrc);
251 }
252 }
253 vie_encoder->SetSsrcs(ssrcs);
254 shared_data_->channel_manager()->UpdateSsrcs(video_channel, ssrcs);
255
256 // Update the protection mode, we might be switching NACK/FEC.
257 vie_encoder->UpdateProtectionMethod(vie_encoder->nack_enabled(),
258 vie_channel->IsSendingFecEnabled());
259
260 // Get new best format for frame provider.
261 ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder);
262 if (frame_provider) {
263 frame_provider->FrameCallbackChanged();
264 }
265 // Restart the media flow
266 if (new_rtp_stream) {
267 // Stream settings changed, make sure we get a key frame.
268 vie_encoder->SendKeyFrame();
269 }
270 vie_encoder->Restart();
271 return 0;
272 }
273
GetSendCodec(const int video_channel,VideoCodec & video_codec) const274 int ViECodecImpl::GetSendCodec(const int video_channel,
275 VideoCodec& video_codec) const {
276 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
277 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
278 if (!vie_encoder) {
279 shared_data_->SetLastError(kViECodecInvalidChannelId);
280 return -1;
281 }
282 return vie_encoder->GetEncoder(&video_codec);
283 }
284
SetReceiveCodec(const int video_channel,const VideoCodec & video_codec)285 int ViECodecImpl::SetReceiveCodec(const int video_channel,
286 const VideoCodec& video_codec) {
287 LOG(LS_INFO) << "SetReceiveCodec for channel " << video_channel;
288 LOG(LS_INFO) << "Codec type " << video_codec.codecType
289 << ", payload type " << static_cast<int>(video_codec.plType);
290
291 if (CodecValid(video_codec) == false) {
292 shared_data_->SetLastError(kViECodecInvalidCodec);
293 return -1;
294 }
295
296 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
297 ViEChannel* vie_channel = cs.Channel(video_channel);
298 if (!vie_channel) {
299 shared_data_->SetLastError(kViECodecInvalidChannelId);
300 return -1;
301 }
302
303 if (vie_channel->SetReceiveCodec(video_codec) != 0) {
304 shared_data_->SetLastError(kViECodecUnknownError);
305 return -1;
306 }
307 return 0;
308 }
309
GetReceiveCodec(const int video_channel,VideoCodec & video_codec) const310 int ViECodecImpl::GetReceiveCodec(const int video_channel,
311 VideoCodec& video_codec) const {
312 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
313 ViEChannel* vie_channel = cs.Channel(video_channel);
314 if (!vie_channel) {
315 shared_data_->SetLastError(kViECodecInvalidChannelId);
316 return -1;
317 }
318
319 if (vie_channel->GetReceiveCodec(&video_codec) != 0) {
320 shared_data_->SetLastError(kViECodecUnknownError);
321 return -1;
322 }
323 return 0;
324 }
325
GetCodecConfigParameters(const int video_channel,unsigned char config_parameters[kConfigParameterSize],unsigned char & config_parameters_size) const326 int ViECodecImpl::GetCodecConfigParameters(
327 const int video_channel,
328 unsigned char config_parameters[kConfigParameterSize],
329 unsigned char& config_parameters_size) const {
330 LOG(LS_INFO) << "GetCodecConfigParameters " << video_channel;
331
332 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
333 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
334 if (!vie_encoder) {
335 shared_data_->SetLastError(kViECodecInvalidChannelId);
336 return -1;
337 }
338
339 if (vie_encoder->GetCodecConfigParameters(config_parameters,
340 config_parameters_size) != 0) {
341 shared_data_->SetLastError(kViECodecUnknownError);
342 return -1;
343 }
344 return 0;
345 }
346
SetImageScaleStatus(const int video_channel,const bool enable)347 int ViECodecImpl::SetImageScaleStatus(const int video_channel,
348 const bool enable) {
349 LOG(LS_INFO) << "SetImageScaleStates for channel " << video_channel
350 << ", enable: " << enable;
351
352 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
353 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
354 if (!vie_encoder) {
355 shared_data_->SetLastError(kViECodecInvalidChannelId);
356 return -1;
357 }
358
359 if (vie_encoder->ScaleInputImage(enable) != 0) {
360 shared_data_->SetLastError(kViECodecUnknownError);
361 return -1;
362 }
363 return 0;
364 }
365
GetSendCodecStatistics(const int video_channel,unsigned int & key_frames,unsigned int & delta_frames) const366 int ViECodecImpl::GetSendCodecStatistics(const int video_channel,
367 unsigned int& key_frames,
368 unsigned int& delta_frames) const {
369 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
370 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
371 if (!vie_encoder) {
372 shared_data_->SetLastError(kViECodecInvalidChannelId);
373 return -1;
374 }
375
376 if (vie_encoder->SendCodecStatistics(&key_frames, &delta_frames) != 0) {
377 shared_data_->SetLastError(kViECodecUnknownError);
378 return -1;
379 }
380 return 0;
381 }
382
GetReceiveCodecStatistics(const int video_channel,unsigned int & key_frames,unsigned int & delta_frames) const383 int ViECodecImpl::GetReceiveCodecStatistics(const int video_channel,
384 unsigned int& key_frames,
385 unsigned int& delta_frames) const {
386 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
387 ViEChannel* vie_channel = cs.Channel(video_channel);
388 if (!vie_channel) {
389 shared_data_->SetLastError(kViECodecInvalidChannelId);
390 return -1;
391 }
392 if (vie_channel->ReceiveCodecStatistics(&key_frames, &delta_frames) != 0) {
393 shared_data_->SetLastError(kViECodecUnknownError);
394 return -1;
395 }
396 return 0;
397 }
398
GetReceiveSideDelay(const int video_channel,int * delay_ms) const399 int ViECodecImpl::GetReceiveSideDelay(const int video_channel,
400 int* delay_ms) const {
401 assert(delay_ms != NULL);
402
403 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
404 ViEChannel* vie_channel = cs.Channel(video_channel);
405 if (!vie_channel) {
406 shared_data_->SetLastError(kViECodecInvalidChannelId);
407 return -1;
408 }
409 *delay_ms = vie_channel->ReceiveDelay();
410 if (*delay_ms < 0) {
411 return -1;
412 }
413 return 0;
414 }
415
GetLastObservedBitrateBps(int video_channel) const416 uint32_t ViECodecImpl::GetLastObservedBitrateBps(int video_channel) const {
417 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
418 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
419 assert(vie_encoder != nullptr);
420 return vie_encoder->LastObservedBitrateBps();
421 }
422
GetCodecTargetBitrate(const int video_channel,unsigned int * bitrate) const423 int ViECodecImpl::GetCodecTargetBitrate(const int video_channel,
424 unsigned int* bitrate) const {
425 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
426 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
427 if (!vie_encoder) {
428 shared_data_->SetLastError(kViECodecInvalidChannelId);
429 return -1;
430 }
431 return vie_encoder->CodecTargetBitrate(static_cast<uint32_t*>(bitrate));
432 }
433
GetNumDiscardedPackets(int video_channel) const434 int ViECodecImpl::GetNumDiscardedPackets(int video_channel) const {
435 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
436 ViEChannel* vie_channel = cs.Channel(video_channel);
437 if (!vie_channel) {
438 shared_data_->SetLastError(kViECodecInvalidChannelId);
439 return -1;
440 }
441 return static_cast<int>(vie_channel->DiscardedPackets());
442 }
443
SetKeyFrameRequestCallbackStatus(const int video_channel,const bool enable)444 int ViECodecImpl::SetKeyFrameRequestCallbackStatus(const int video_channel,
445 const bool enable) {
446 LOG(LS_INFO) << "SetKeyFrameRequestCallbackStatus for " << video_channel
447 << ", enable " << enable;
448
449 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
450 ViEChannel* vie_channel = cs.Channel(video_channel);
451 if (!vie_channel) {
452 shared_data_->SetLastError(kViECodecInvalidChannelId);
453 return -1;
454 }
455 if (vie_channel->EnableKeyFrameRequestCallback(enable) != 0) {
456 shared_data_->SetLastError(kViECodecUnknownError);
457 return -1;
458 }
459 return 0;
460 }
461
SetSignalKeyPacketLossStatus(const int video_channel,const bool enable,const bool only_key_frames)462 int ViECodecImpl::SetSignalKeyPacketLossStatus(const int video_channel,
463 const bool enable,
464 const bool only_key_frames) {
465 LOG(LS_INFO) << "SetSignalKeyPacketLossStatus for " << video_channel
466 << "enable, " << enable
467 << ", only key frames " << only_key_frames;
468
469 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
470 ViEChannel* vie_channel = cs.Channel(video_channel);
471 if (!vie_channel) {
472 shared_data_->SetLastError(kViECodecInvalidChannelId);
473 return -1;
474 }
475 if (vie_channel->SetSignalPacketLossStatus(enable, only_key_frames) != 0) {
476 shared_data_->SetLastError(kViECodecUnknownError);
477 return -1;
478 }
479 return 0;
480 }
481
RegisterEncoderObserver(const int video_channel,ViEEncoderObserver & observer)482 int ViECodecImpl::RegisterEncoderObserver(const int video_channel,
483 ViEEncoderObserver& observer) {
484 LOG(LS_INFO) << "RegisterEncoderObserver for channel " << video_channel;
485
486 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
487 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
488 if (!vie_encoder) {
489 shared_data_->SetLastError(kViECodecInvalidChannelId);
490 return -1;
491 }
492 if (vie_encoder->RegisterCodecObserver(&observer) != 0) {
493 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
494 return -1;
495 }
496 return 0;
497 }
498
DeregisterEncoderObserver(const int video_channel)499 int ViECodecImpl::DeregisterEncoderObserver(const int video_channel) {
500 LOG(LS_INFO) << "DeregisterEncoderObserver for channel " << video_channel;
501
502 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
503 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
504 if (!vie_encoder) {
505 shared_data_->SetLastError(kViECodecInvalidChannelId);
506 return -1;
507 }
508 if (vie_encoder->RegisterCodecObserver(NULL) != 0) {
509 shared_data_->SetLastError(kViECodecObserverNotRegistered);
510 return -1;
511 }
512 return 0;
513 }
514
RegisterDecoderObserver(const int video_channel,ViEDecoderObserver & observer)515 int ViECodecImpl::RegisterDecoderObserver(const int video_channel,
516 ViEDecoderObserver& observer) {
517 LOG(LS_INFO) << "RegisterDecoderObserver for channel " << video_channel;
518
519 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
520 ViEChannel* vie_channel = cs.Channel(video_channel);
521 if (!vie_channel) {
522 shared_data_->SetLastError(kViECodecInvalidChannelId);
523 return -1;
524 }
525 if (vie_channel->RegisterCodecObserver(&observer) != 0) {
526 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
527 return -1;
528 }
529 return 0;
530 }
531
DeregisterDecoderObserver(const int video_channel)532 int ViECodecImpl::DeregisterDecoderObserver(const int video_channel) {
533 LOG(LS_INFO) << "DeregisterDecodeObserver for channel " << video_channel;
534
535 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
536 ViEChannel* vie_channel = cs.Channel(video_channel);
537 if (!vie_channel) {
538 shared_data_->SetLastError(kViECodecInvalidChannelId);
539 return -1;
540 }
541 if (vie_channel->RegisterCodecObserver(NULL) != 0) {
542 shared_data_->SetLastError(kViECodecObserverNotRegistered);
543 return -1;
544 }
545 return 0;
546 }
547
SendKeyFrame(const int video_channel)548 int ViECodecImpl::SendKeyFrame(const int video_channel) {
549 LOG(LS_INFO) << "SendKeyFrame on channel " << video_channel;
550
551 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
552 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
553 if (!vie_encoder) {
554 shared_data_->SetLastError(kViECodecInvalidChannelId);
555 return -1;
556 }
557 if (vie_encoder->SendKeyFrame() != 0) {
558 shared_data_->SetLastError(kViECodecUnknownError);
559 return -1;
560 }
561 return 0;
562 }
563
WaitForFirstKeyFrame(const int video_channel,const bool wait)564 int ViECodecImpl::WaitForFirstKeyFrame(const int video_channel,
565 const bool wait) {
566 LOG(LS_INFO) << "WaitForFirstKeyFrame for channel " << video_channel
567 << ", wait " << wait;
568
569 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
570 ViEChannel* vie_channel = cs.Channel(video_channel);
571 if (!vie_channel) {
572 shared_data_->SetLastError(kViECodecInvalidChannelId);
573 return -1;
574 }
575 if (vie_channel->WaitForKeyFrame(wait) != 0) {
576 shared_data_->SetLastError(kViECodecUnknownError);
577 return -1;
578 }
579 return 0;
580 }
581
StartDebugRecording(int video_channel,const char * file_name_utf8)582 int ViECodecImpl::StartDebugRecording(int video_channel,
583 const char* file_name_utf8) {
584 LOG(LS_INFO) << "StartDebugRecording for channel " << video_channel;
585 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
586 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
587 if (!vie_encoder) {
588 return -1;
589 }
590 return vie_encoder->StartDebugRecording(file_name_utf8);
591 }
592
StopDebugRecording(int video_channel)593 int ViECodecImpl::StopDebugRecording(int video_channel) {
594 LOG(LS_INFO) << "StopDebugRecording for channel " << video_channel;
595 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
596 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
597 if (!vie_encoder) {
598 return -1;
599 }
600 return vie_encoder->StopDebugRecording();
601 }
602
SuspendBelowMinBitrate(int video_channel)603 void ViECodecImpl::SuspendBelowMinBitrate(int video_channel) {
604 LOG(LS_INFO) << "SuspendBelowMinBitrate for channel " << video_channel;
605 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
606 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
607 if (!vie_encoder) {
608 return;
609 }
610 vie_encoder->SuspendBelowMinBitrate();
611 ViEChannel* vie_channel = cs.Channel(video_channel);
612 if (!vie_channel) {
613 return;
614 }
615 // Must enable pacing when enabling SuspendBelowMinBitrate. Otherwise, no
616 // padding will be sent when the video is suspended so the video will be
617 // unable to recover.
618 vie_channel->SetTransmissionSmoothingStatus(true);
619 }
620
GetSendSideDelay(int video_channel,int * avg_delay_ms,int * max_delay_ms) const621 bool ViECodecImpl::GetSendSideDelay(int video_channel, int* avg_delay_ms,
622 int* max_delay_ms) const {
623 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
624 ViEChannel* vie_channel = cs.Channel(video_channel);
625 if (!vie_channel) {
626 shared_data_->SetLastError(kViECodecInvalidChannelId);
627 return false;
628 }
629 return vie_channel->GetSendSideDelay(avg_delay_ms, max_delay_ms);
630 }
631
CodecValid(const VideoCodec & video_codec)632 bool ViECodecImpl::CodecValid(const VideoCodec& video_codec) {
633 // Check pl_name matches codec_type.
634 if (video_codec.codecType == kVideoCodecRED) {
635 #if defined(WIN32)
636 if (_strnicmp(video_codec.plName, "red", 3) == 0) {
637 #else
638 if (strncasecmp(video_codec.plName, "red", 3) == 0) {
639 #endif
640 // We only care about the type and name for red.
641 return true;
642 }
643 LOG_F(LS_ERROR) << "Invalid RED configuration.";
644 return false;
645 } else if (video_codec.codecType == kVideoCodecULPFEC) {
646 #if defined(WIN32)
647 if (_strnicmp(video_codec.plName, "ULPFEC", 6) == 0) {
648 #else
649 if (strncasecmp(video_codec.plName, "ULPFEC", 6) == 0) {
650 #endif
651 // We only care about the type and name for ULPFEC.
652 return true;
653 }
654 LOG_F(LS_ERROR) << "Invalid ULPFEC configuration.";
655 return false;
656 } else if ((video_codec.codecType == kVideoCodecVP8 &&
657 strncmp(video_codec.plName, "VP8", 4) == 0) ||
658 (video_codec.codecType == kVideoCodecVP9 &&
659 strncmp(video_codec.plName, "VP9", 4) == 0) ||
660 (video_codec.codecType == kVideoCodecI420 &&
661 strncmp(video_codec.plName, "I420", 4) == 0) ||
662 (video_codec.codecType == kVideoCodecH264 &&
663 strncmp(video_codec.plName, "H264", 4) == 0)) {
664 // OK.
665 } else if (video_codec.codecType != kVideoCodecGeneric) {
666 LOG(LS_ERROR) << "Codec type and name mismatch.";
667 return false;
668 }
669
670 if (video_codec.plType == 0 || video_codec.plType > 127) {
671 LOG(LS_ERROR) << "Invalid payload type: "
672 << static_cast<int>(video_codec.plType);
673 return false;
674 }
675
676 if (video_codec.width > kViEMaxCodecWidth ||
677 video_codec.height > kViEMaxCodecHeight) {
678 LOG(LS_ERROR) << "Invalid codec resolution " << video_codec.width
679 << " x " << video_codec.height;
680 return false;
681 }
682
683 if (video_codec.startBitrate > 0 &&
684 video_codec.startBitrate < kViEMinCodecBitrate) {
685 LOG(LS_ERROR) << "Invalid start bitrate.";
686 return false;
687 }
688 if (video_codec.minBitrate < kViEMinCodecBitrate) {
689 LOG(LS_ERROR) << "Invalid min bitrate.";
690 return false;
691 }
692 return true;
693 }
694
695 } // namespace webrtc
696