Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / video_engine / vie_codec_impl.cc
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
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                  << ", 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;
84   }
85 }
86
87
88 ViECodec* ViECodec::GetInterface(VideoEngine* video_engine) {
89 #ifdef WEBRTC_VIDEO_ENGINE_CODEC_API
90   if (!video_engine) {
91     return NULL;
92   }
93   VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
94   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
103 int ViECodecImpl::Release() {
104   LOG(LS_INFO) << "ViECodec::Release.";
105   // Decrease ref count.
106   (*this)--;
107
108   int32_t ref_count = GetCount();
109   if (ref_count < 0) {
110     LOG(LS_WARNING) << "ViECodec released too many times.";
111     shared_data_->SetLastError(kViEAPIDoesNotExist);
112     return -1;
113   }
114   return ref_count;
115 }
116
117 ViECodecImpl::ViECodecImpl(ViESharedData* shared_data)
118     : shared_data_(shared_data) {
119 }
120
121 ViECodecImpl::~ViECodecImpl() {
122 }
123
124 int ViECodecImpl::NumberOfCodecs() const {
125   // +2 because of FEC(RED and ULPFEC)
126   return static_cast<int>((VideoCodingModule::NumberOfCodecs() + 2));
127 }
128
129 int ViECodecImpl::GetCodec(const unsigned char list_number,
130                            VideoCodec& video_codec) const {
131   if (list_number == VideoCodingModule::NumberOfCodecs()) {
132     memset(&video_codec, 0, sizeof(VideoCodec));
133     strcpy(video_codec.plName, "red");
134     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));
138     strcpy(video_codec.plName, "ulpfec");
139     video_codec.codecType = kVideoCodecULPFEC;
140     video_codec.plType = VCM_ULPFEC_PAYLOAD_TYPE;
141   } else if (VideoCodingModule::Codec(list_number, &video_codec) != VCM_OK) {
142     shared_data_->SetLastError(kViECodecInvalidArgument);
143     return -1;
144   }
145   return 0;
146 }
147
148 int ViECodecImpl::SetSendCodec(const int video_channel,
149                                const VideoCodec& video_codec) {
150   LOG(LS_INFO) << "SetSendCodec for channel " << video_channel;
151   LogCodec(video_codec);
152   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) {
161     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) {
168     LOG_F(LS_ERROR) << "Receive only channel.";
169     shared_data_->SetLastError(kViECodecReceiveOnlyChannel);
170     return -1;
171   }
172   // 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;
181     LOG(LS_INFO) << "New max bitrate set " << video_codec_internal.maxBitrate;
182   }
183
184   if (video_codec_internal.startBitrate < video_codec_internal.minBitrate) {
185     video_codec_internal.startBitrate = video_codec_internal.minBitrate;
186   }
187   if (video_codec_internal.startBitrate > video_codec_internal.maxBitrate) {
188     video_codec_internal.startBitrate = video_codec_internal.maxBitrate;
189   }
190
191   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()));
202
203   // Stop the media flow while reconfiguring.
204   vie_encoder->Pause();
205
206   if (vie_encoder->SetEncoder(video_codec_internal) != 0) {
207     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) {
218       ret = false;
219     }
220     if (!ret) {
221       shared_data_->SetLastError(kViECodecUnknownError);
222       return -1;
223     }
224   }
225
226   // 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) {
232       LOG_F(LS_ERROR) << "Could not get ssrc.";
233     }
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) {
240         LOG_F(LS_ERROR) << "Could not get ssrc for stream " << idx;
241       }
242       ssrcs.push_back(ssrc);
243     }
244   }
245   vie_encoder->SetSsrcs(ssrcs);
246   shared_data_->channel_manager()->UpdateSsrcs(video_channel, ssrcs);
247
248   // Update the protection mode, we might be switching NACK/FEC.
249   vie_encoder->UpdateProtectionMethod(vie_encoder->nack_enabled());
250
251   // Get new best format for frame provider.
252   ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder);
253   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
265 int ViECodecImpl::GetSendCodec(const int video_channel,
266                                VideoCodec& video_codec) const {
267   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
268   ViEEncoder* vie_encoder = cs.Encoder(video_channel);
269   if (!vie_encoder) {
270     shared_data_->SetLastError(kViECodecInvalidChannelId);
271     return -1;
272   }
273   return vie_encoder->GetEncoder(&video_codec);
274 }
275
276 int ViECodecImpl::SetReceiveCodec(const int video_channel,
277                                   const VideoCodec& video_codec) {
278   LOG(LS_INFO) << "SetReceiveCodec for channel " << video_channel;
279   LOG(LS_INFO) << "Codec type " << video_codec.codecType
280                << ", payload type " << video_codec.plType;
281
282   if (CodecValid(video_codec) == false) {
283     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) {
290     shared_data_->SetLastError(kViECodecInvalidChannelId);
291     return -1;
292   }
293
294   if (vie_channel->SetReceiveCodec(video_codec) != 0) {
295     shared_data_->SetLastError(kViECodecUnknownError);
296     return -1;
297   }
298   return 0;
299 }
300
301 int ViECodecImpl::GetReceiveCodec(const int video_channel,
302                                   VideoCodec& video_codec) const {
303   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
304   ViEChannel* vie_channel = cs.Channel(video_channel);
305   if (!vie_channel) {
306     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
317 int ViECodecImpl::GetCodecConfigParameters(
318   const int video_channel,
319   unsigned char config_parameters[kConfigParameterSize],
320   unsigned char& config_parameters_size) const {
321   LOG(LS_INFO) << "GetCodecConfigParameters " << video_channel;
322
323   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
324   ViEEncoder* vie_encoder = cs.Encoder(video_channel);
325   if (!vie_encoder) {
326     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
338 int ViECodecImpl::SetImageScaleStatus(const int video_channel,
339                                       const bool enable) {
340   LOG(LS_INFO) << "SetImageScaleStates for channel " << video_channel
341                << ", enable: " << enable;
342
343   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
344   ViEEncoder* vie_encoder = cs.Encoder(video_channel);
345   if (!vie_encoder) {
346     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
357 int ViECodecImpl::GetSendCodecStastistics(const int video_channel,
358                                           unsigned int& key_frames,
359                                           unsigned int& delta_frames) const {
360   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
361   ViEEncoder* vie_encoder = cs.Encoder(video_channel);
362   if (!vie_encoder) {
363     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
374 int ViECodecImpl::GetReceiveCodecStastistics(const int video_channel,
375                                              unsigned int& key_frames,
376                                              unsigned int& delta_frames) const {
377   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
378   ViEChannel* vie_channel = cs.Channel(video_channel);
379   if (!vie_channel) {
380     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
390 int ViECodecImpl::GetReceiveSideDelay(const int video_channel,
391                                       int* delay_ms) const {
392   assert(delay_ms != NULL);
393
394   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
395   ViEChannel* vie_channel = cs.Channel(video_channel);
396   if (!vie_channel) {
397     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
408 int ViECodecImpl::GetCodecTargetBitrate(const int video_channel,
409                                         unsigned int* bitrate) const {
410   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
411   ViEEncoder* vie_encoder = cs.Encoder(video_channel);
412   if (!vie_encoder) {
413     shared_data_->SetLastError(kViECodecInvalidChannelId);
414     return -1;
415   }
416   return vie_encoder->CodecTargetBitrate(static_cast<uint32_t*>(bitrate));
417 }
418
419 int ViECodecImpl::GetNumDiscardedPackets(int video_channel) const {
420   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
421   ViEChannel* vie_channel = cs.Channel(video_channel);
422   if (!vie_channel) {
423     shared_data_->SetLastError(kViECodecInvalidChannelId);
424     return -1;
425   }
426   return static_cast<int>(vie_channel->DiscardedPackets());
427 }
428
429 int ViECodecImpl::SetKeyFrameRequestCallbackStatus(const int video_channel,
430                                                    const bool enable) {
431   LOG(LS_INFO) << "SetKeyFrameRequestCallbackStatus for " << video_channel
432                << ", enable " << enable;
433
434   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
435   ViEChannel* vie_channel = cs.Channel(video_channel);
436   if (!vie_channel) {
437     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
447 int ViECodecImpl::SetSignalKeyPacketLossStatus(const int video_channel,
448                                                const bool enable,
449                                                const bool only_key_frames) {
450   LOG(LS_INFO) << "SetSignalKeyPacketLossStatus for " << video_channel
451                << "enable, " << enable
452                << ", only key frames " << only_key_frames;
453
454   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
455   ViEChannel* vie_channel = cs.Channel(video_channel);
456   if (!vie_channel) {
457     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
467 int ViECodecImpl::RegisterEncoderObserver(const int video_channel,
468                                           ViEEncoderObserver& observer) {
469   LOG(LS_INFO) << "RegisterEncoderObserver for channel " << video_channel;
470
471   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
472   ViEEncoder* vie_encoder = cs.Encoder(video_channel);
473   if (!vie_encoder) {
474     shared_data_->SetLastError(kViECodecInvalidChannelId);
475     return -1;
476   }
477   if (vie_encoder->RegisterCodecObserver(&observer) != 0) {
478     shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
479     return -1;
480   }
481   return 0;
482 }
483
484 int ViECodecImpl::DeregisterEncoderObserver(const int video_channel) {
485   LOG(LS_INFO) << "DeregisterEncoderObserver for channel " << video_channel;
486
487   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
488   ViEEncoder* vie_encoder = cs.Encoder(video_channel);
489   if (!vie_encoder) {
490     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
500 int ViECodecImpl::RegisterDecoderObserver(const int video_channel,
501                                           ViEDecoderObserver& observer) {
502   LOG(LS_INFO) << "RegisterDecoderObserver for channel " << video_channel;
503
504   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
505   ViEChannel* vie_channel = cs.Channel(video_channel);
506   if (!vie_channel) {
507     shared_data_->SetLastError(kViECodecInvalidChannelId);
508     return -1;
509   }
510   if (vie_channel->RegisterCodecObserver(&observer) != 0) {
511     shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
512     return -1;
513   }
514   return 0;
515 }
516
517 int ViECodecImpl::DeregisterDecoderObserver(const int video_channel) {
518   LOG(LS_INFO) << "DeregisterDecodeObserver for channel " << video_channel;
519
520   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
521   ViEChannel* vie_channel = cs.Channel(video_channel);
522   if (!vie_channel) {
523     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
533 int ViECodecImpl::SendKeyFrame(const int video_channel) {
534   LOG(LS_INFO) << "SendKeyFrame on channel " << video_channel;
535
536   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
537   ViEEncoder* vie_encoder = cs.Encoder(video_channel);
538   if (!vie_encoder) {
539     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
549 int ViECodecImpl::WaitForFirstKeyFrame(const int video_channel,
550                                        const bool wait) {
551   LOG(LS_INFO) << "WaitForFirstKeyFrame for channel " << video_channel
552                << ", wait " << wait;
553
554   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
555   ViEChannel* vie_channel = cs.Channel(video_channel);
556   if (!vie_channel) {
557     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
567 int ViECodecImpl::StartDebugRecording(int video_channel,
568                                       const char* file_name_utf8) {
569   LOG(LS_INFO) << "StartDebugRecording for channel " << video_channel;
570   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
571   ViEEncoder* vie_encoder = cs.Encoder(video_channel);
572   if (!vie_encoder) {
573     return -1;
574   }
575   return vie_encoder->StartDebugRecording(file_name_utf8);
576 }
577
578 int ViECodecImpl::StopDebugRecording(int video_channel) {
579   LOG(LS_INFO) << "StopDebugRecording for channel " << video_channel;
580   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
581   ViEEncoder* vie_encoder = cs.Encoder(video_channel);
582   if (!vie_encoder) {
583     return -1;
584   }
585   return vie_encoder->StopDebugRecording();
586 }
587
588 void ViECodecImpl::SuspendBelowMinBitrate(int video_channel) {
589   LOG(LS_INFO) << "SuspendBelowMinBitrate for channel " << video_channel;
590   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
591   ViEEncoder* vie_encoder = cs.Encoder(video_channel);
592   if (!vie_encoder) {
593     return;
594   }
595   vie_encoder->SuspendBelowMinBitrate();
596   ViEChannel* vie_channel = cs.Channel(video_channel);
597   if (!vie_channel) {
598     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);
604 }
605
606 bool 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) {
611     shared_data_->SetLastError(kViECodecInvalidChannelId);
612     return false;
613   }
614   return vie_channel->GetSendSideDelay(avg_delay_ms, max_delay_ms);
615 }
616
617 bool 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     }
628     LOG_F(LS_ERROR) << "Invalid RED configuration.";
629     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     }
639     LOG_F(LS_ERROR) << "Invalid ULPFEC configuration.";
640     return false;
641   } else if ((video_codec.codecType == kVideoCodecVP8 &&
642               strncmp(video_codec.plName, "VP8", 4) == 0) ||
643              (video_codec.codecType == kVideoCodecVP9 &&
644               strncmp(video_codec.plName, "VP9", 4) == 0) ||
645              (video_codec.codecType == kVideoCodecI420 &&
646               strncmp(video_codec.plName, "I420", 4) == 0) ||
647              (video_codec.codecType == kVideoCodecH264 &&
648               strncmp(video_codec.plName, "H264", 4) == 0)) {
649     // OK.
650   } else if (video_codec.codecType != kVideoCodecGeneric) {
651     LOG(LS_ERROR) << "Codec type and name mismatch.";
652     return false;
653   }
654
655   if (video_codec.plType == 0 || video_codec.plType > 127) {
656     LOG(LS_ERROR) << "Invalif payload type: " << video_codec.plType;
657     return false;
658   }
659
660   if (video_codec.width > kViEMaxCodecWidth ||
661       video_codec.height > kViEMaxCodecHeight) {
662     LOG(LS_ERROR) << "Invalid codec resolution " << video_codec.width
663                   << " x " << video_codec.height;
664     return false;
665   }
666
667   if (video_codec.startBitrate < kViEMinCodecBitrate) {
668     LOG(LS_ERROR) << "Invalid start bitrate.";
669     return false;
670   }
671   if (video_codec.minBitrate < kViEMinCodecBitrate) {
672     LOG(LS_ERROR) << "Invalid min bitrate.";
673     return false;
674   }
675   return true;
676 }
677
678 }  // namespace webrtc