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