Home | History | Annotate | Download | only in video_engine
      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 == kVideoCodecI420 &&
    644               strncmp(video_codec.plName, "I420", 4) == 0) ||
    645              (video_codec.codecType == kVideoCodecH264 &&
    646               strncmp(video_codec.plName, "H264", 4) == 0)) {
    647     // OK.
    648   } else if (video_codec.codecType != kVideoCodecGeneric) {
    649     LOG(LS_ERROR) << "Codec type and name mismatch.";
    650     return false;
    651   }
    652 
    653   if (video_codec.plType == 0 || video_codec.plType > 127) {
    654     LOG(LS_ERROR) << "Invalif payload type: " << video_codec.plType;
    655     return false;
    656   }
    657 
    658   if (video_codec.width > kViEMaxCodecWidth ||
    659       video_codec.height > kViEMaxCodecHeight) {
    660     LOG(LS_ERROR) << "Invalid codec resolution " << video_codec.width
    661                   << " x " << video_codec.height;
    662     return false;
    663   }
    664 
    665   if (video_codec.startBitrate < kViEMinCodecBitrate) {
    666     LOG(LS_ERROR) << "Invalid start bitrate.";
    667     return false;
    668   }
    669   if (video_codec.minBitrate < kViEMinCodecBitrate) {
    670     LOG(LS_ERROR) << "Invalid min bitrate.";
    671     return false;
    672   }
    673   return true;
    674 }
    675 
    676 }  // namespace webrtc
    677