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