/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/video_engine/vie_codec_impl.h"

#include <list>

#include "webrtc/engine_configurations.h"
#include "webrtc/modules/video_coding/main/interface/video_coding.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/video_engine/include/vie_errors.h"
#include "webrtc/video_engine/vie_capturer.h"
#include "webrtc/video_engine/vie_channel.h"
#include "webrtc/video_engine/vie_channel_manager.h"
#include "webrtc/video_engine/vie_defines.h"
#include "webrtc/video_engine/vie_encoder.h"
#include "webrtc/video_engine/vie_impl.h"
#include "webrtc/video_engine/vie_input_manager.h"
#include "webrtc/video_engine/vie_shared_data.h"

namespace webrtc {

static void LogCodec(const VideoCodec& codec) {
  LOG(LS_INFO) << "CodecType " << codec.codecType
               << ", pl_type " << static_cast<int>(codec.plType)
               << ", resolution " << codec.width
               << " x " << codec.height
               << ", start br " << codec.startBitrate
               << ", min br " << codec.minBitrate
               << ", max br " << codec.maxBitrate
               << ", max fps " << static_cast<int>(codec.maxFramerate)
               << ", max qp " << codec.qpMax
               << ", number of streams "
               << static_cast<int>(codec.numberOfSimulcastStreams);
  if (codec.codecType == kVideoCodecVP8) {
    LOG(LS_INFO) << "VP8 specific settings";
    LOG(LS_INFO) << "pictureLossIndicationOn "
                 << codec.codecSpecific.VP8.pictureLossIndicationOn
                 << ", feedbackModeOn "
                 << codec.codecSpecific.VP8.feedbackModeOn
                 << ", complexity "
                 << codec.codecSpecific.VP8.complexity
                 << ", resilience "
                 << codec.codecSpecific.VP8.resilience
                 << ", numberOfTemporalLayers "
                 << static_cast<int>(
                     codec.codecSpecific.VP8.numberOfTemporalLayers)
                 << ", keyFrameinterval "
                 << codec.codecSpecific.VP8.keyFrameInterval;
    for (int idx = 0; idx < codec.numberOfSimulcastStreams; ++idx) {
      LOG(LS_INFO) << "Stream " << codec.simulcastStream[idx].width
                   << " x " << codec.simulcastStream[idx].height;
      LOG(LS_INFO) << "Temporal layers "
                   << static_cast<int>(
                       codec.simulcastStream[idx].numberOfTemporalLayers)
                   << ", min br "
                   << codec.simulcastStream[idx].minBitrate
                   << ", target br "
                   << codec.simulcastStream[idx].targetBitrate
                   << ", max br "
                   << codec.simulcastStream[idx].maxBitrate
                   << ", qp max "
                   << codec.simulcastStream[idx].qpMax;
    }
  } else if (codec.codecType == kVideoCodecH264) {
    LOG(LS_INFO) << "H264 specific settings";
    LOG(LS_INFO) << "profile: "
                 <<  codec.codecSpecific.H264.profile
                 << ", framedropping: "
                 << codec.codecSpecific.H264.frameDroppingOn
                 << ", keyFrameInterval: "
                 << codec.codecSpecific.H264.keyFrameInterval
                 << ", spslen: "
                 << codec.codecSpecific.H264.spsLen
                 << ", ppslen: "
                 << codec.codecSpecific.H264.ppsLen;
  }
}


ViECodec* ViECodec::GetInterface(VideoEngine* video_engine) {
#ifdef WEBRTC_VIDEO_ENGINE_CODEC_API
  if (!video_engine) {
    return NULL;
  }
  VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
  ViECodecImpl* vie_codec_impl = vie_impl;
  // Increase ref count.
  (*vie_codec_impl)++;
  return vie_codec_impl;
#else
  return NULL;
#endif
}

int ViECodecImpl::Release() {
  LOG(LS_INFO) << "ViECodec::Release.";
  // Decrease ref count.
  (*this)--;

  int32_t ref_count = GetCount();
  if (ref_count < 0) {
    LOG(LS_WARNING) << "ViECodec released too many times.";
    shared_data_->SetLastError(kViEAPIDoesNotExist);
    return -1;
  }
  return ref_count;
}

ViECodecImpl::ViECodecImpl(ViESharedData* shared_data)
    : shared_data_(shared_data) {
}

ViECodecImpl::~ViECodecImpl() {
}

int ViECodecImpl::NumberOfCodecs() const {
  // +2 because of FEC(RED and ULPFEC)
  return static_cast<int>((VideoCodingModule::NumberOfCodecs() + 2));
}

int ViECodecImpl::GetCodec(const unsigned char list_number,
                           VideoCodec& video_codec) const {
  if (list_number == VideoCodingModule::NumberOfCodecs()) {
    memset(&video_codec, 0, sizeof(VideoCodec));
    strcpy(video_codec.plName, "red");
    video_codec.codecType = kVideoCodecRED;
    video_codec.plType = VCM_RED_PAYLOAD_TYPE;
  } else if (list_number == VideoCodingModule::NumberOfCodecs() + 1) {
    memset(&video_codec, 0, sizeof(VideoCodec));
    strcpy(video_codec.plName, "ulpfec");
    video_codec.codecType = kVideoCodecULPFEC;
    video_codec.plType = VCM_ULPFEC_PAYLOAD_TYPE;
  } else if (VideoCodingModule::Codec(list_number, &video_codec) != VCM_OK) {
    shared_data_->SetLastError(kViECodecInvalidArgument);
    return -1;
  }
  return 0;
}

int ViECodecImpl::SetSendCodec(const int video_channel,
                               const VideoCodec& video_codec) {
  LOG(LS_INFO) << "SetSendCodec for channel " << video_channel;
  LogCodec(video_codec);
  if (!CodecValid(video_codec)) {
    // Error logged.
    shared_data_->SetLastError(kViECodecInvalidCodec);
    return -1;
  }

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }

  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder);
  if (vie_encoder->Owner() != video_channel) {
    LOG_F(LS_ERROR) << "Receive only channel.";
    shared_data_->SetLastError(kViECodecReceiveOnlyChannel);
    return -1;
  }
  // Set a max_bitrate if the user hasn't set one.
  VideoCodec video_codec_internal;
  memcpy(&video_codec_internal, &video_codec, sizeof(VideoCodec));
  if (video_codec_internal.maxBitrate == 0) {
    // Max is one bit per pixel.
    video_codec_internal.maxBitrate = (video_codec_internal.width *
                                       video_codec_internal.height *
                                       video_codec_internal.maxFramerate)
                                       / 1000;
    LOG(LS_INFO) << "New max bitrate set " << video_codec_internal.maxBitrate;
  }

  if (video_codec_internal.startBitrate < video_codec_internal.minBitrate) {
    video_codec_internal.startBitrate = video_codec_internal.minBitrate;
  }
  if (video_codec_internal.startBitrate > video_codec_internal.maxBitrate) {
    video_codec_internal.startBitrate = video_codec_internal.maxBitrate;
  }

  // Make sure to generate a new SSRC if the codec type and/or resolution has
  // changed. This won't have any effect if the user has set an SSRC.
  bool new_rtp_stream = true;
  VideoCodec encoder;
  if (vie_encoder->GetEncoder(&encoder) == 0)
    new_rtp_stream = encoder.codecType != video_codec_internal.codecType;

  ViEInputManagerScoped is(*(shared_data_->input_manager()));

  // Stop the media flow while reconfiguring.
  vie_encoder->Pause();

  if (vie_encoder->SetEncoder(video_codec_internal) != 0) {
    shared_data_->SetLastError(kViECodecUnknownError);
    return -1;
  }

  // Give the channel(s) the new information.
  ChannelList channels;
  cs.ChannelsUsingViEEncoder(video_channel, &channels);
  for (ChannelList::iterator it = channels.begin(); it != channels.end();
       ++it) {
    bool ret = true;
    if ((*it)->SetSendCodec(video_codec_internal, new_rtp_stream) != 0) {
      ret = false;
    }
    if (!ret) {
      shared_data_->SetLastError(kViECodecUnknownError);
      return -1;
    }
  }

  // TODO(mflodman) Break out this part in GetLocalSsrcList().
  // Update all SSRCs to ViEEncoder.
  std::list<unsigned int> ssrcs;
  if (video_codec_internal.numberOfSimulcastStreams == 0) {
    unsigned int ssrc = 0;
    if (vie_channel->GetLocalSSRC(0, &ssrc) != 0) {
      LOG_F(LS_ERROR) << "Could not get ssrc.";
    }
    ssrcs.push_back(ssrc);
  } else {
    for (int idx = 0; idx < video_codec_internal.numberOfSimulcastStreams;
         ++idx) {
      unsigned int ssrc = 0;
      if (vie_channel->GetLocalSSRC(idx, &ssrc) != 0) {
        LOG_F(LS_ERROR) << "Could not get ssrc for stream " << idx;
      }
      ssrcs.push_back(ssrc);
    }
  }
  vie_encoder->SetSsrcs(ssrcs);
  shared_data_->channel_manager()->UpdateSsrcs(video_channel, ssrcs);

  // Update the protection mode, we might be switching NACK/FEC.
  vie_encoder->UpdateProtectionMethod(vie_encoder->nack_enabled(),
                                      vie_channel->IsSendingFecEnabled());

  // Get new best format for frame provider.
  ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder);
  if (frame_provider) {
    frame_provider->FrameCallbackChanged();
  }
  // Restart the media flow
  if (new_rtp_stream) {
    // Stream settings changed, make sure we get a key frame.
    vie_encoder->SendKeyFrame();
  }
  vie_encoder->Restart();
  return 0;
}

int ViECodecImpl::GetSendCodec(const int video_channel,
                               VideoCodec& video_codec) const {
  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  return vie_encoder->GetEncoder(&video_codec);
}

int ViECodecImpl::SetReceiveCodec(const int video_channel,
                                  const VideoCodec& video_codec) {
  LOG(LS_INFO) << "SetReceiveCodec for channel " << video_channel;
  LOG(LS_INFO) << "Codec type " << video_codec.codecType
               << ", payload type " << static_cast<int>(video_codec.plType);

  if (CodecValid(video_codec) == false) {
    shared_data_->SetLastError(kViECodecInvalidCodec);
    return -1;
  }

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }

  if (vie_channel->SetReceiveCodec(video_codec) != 0) {
    shared_data_->SetLastError(kViECodecUnknownError);
    return -1;
  }
  return 0;
}

int ViECodecImpl::GetReceiveCodec(const int video_channel,
                                  VideoCodec& video_codec) const {
  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }

  if (vie_channel->GetReceiveCodec(&video_codec) != 0) {
    shared_data_->SetLastError(kViECodecUnknownError);
    return -1;
  }
  return 0;
}

int ViECodecImpl::GetCodecConfigParameters(
  const int video_channel,
  unsigned char config_parameters[kConfigParameterSize],
  unsigned char& config_parameters_size) const {
  LOG(LS_INFO) << "GetCodecConfigParameters " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }

  if (vie_encoder->GetCodecConfigParameters(config_parameters,
                                            config_parameters_size) != 0) {
    shared_data_->SetLastError(kViECodecUnknownError);
    return -1;
  }
  return 0;
}

int ViECodecImpl::SetImageScaleStatus(const int video_channel,
                                      const bool enable) {
  LOG(LS_INFO) << "SetImageScaleStates for channel " << video_channel
               << ", enable: " << enable;

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }

  if (vie_encoder->ScaleInputImage(enable) != 0) {
    shared_data_->SetLastError(kViECodecUnknownError);
    return -1;
  }
  return 0;
}

int ViECodecImpl::GetSendCodecStastistics(const int video_channel,
                                          unsigned int& key_frames,
                                          unsigned int& delta_frames) const {
  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }

  if (vie_encoder->SendCodecStatistics(&key_frames, &delta_frames) != 0) {
    shared_data_->SetLastError(kViECodecUnknownError);
    return -1;
  }
  return 0;
}

int ViECodecImpl::GetReceiveCodecStastistics(const int video_channel,
                                             unsigned int& key_frames,
                                             unsigned int& delta_frames) const {
  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  if (vie_channel->ReceiveCodecStatistics(&key_frames, &delta_frames) != 0) {
    shared_data_->SetLastError(kViECodecUnknownError);
    return -1;
  }
  return 0;
}

int ViECodecImpl::GetReceiveSideDelay(const int video_channel,
                                      int* delay_ms) const {
  assert(delay_ms != NULL);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  *delay_ms = vie_channel->ReceiveDelay();
  if (*delay_ms < 0) {
    return -1;
  }
  return 0;
}


int ViECodecImpl::GetCodecTargetBitrate(const int video_channel,
                                        unsigned int* bitrate) const {
  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  return vie_encoder->CodecTargetBitrate(static_cast<uint32_t*>(bitrate));
}

int ViECodecImpl::GetNumDiscardedPackets(int video_channel) const {
  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  return static_cast<int>(vie_channel->DiscardedPackets());
}

int ViECodecImpl::SetKeyFrameRequestCallbackStatus(const int video_channel,
                                                   const bool enable) {
  LOG(LS_INFO) << "SetKeyFrameRequestCallbackStatus for " << video_channel
               << ", enable " << enable;

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  if (vie_channel->EnableKeyFrameRequestCallback(enable) != 0) {
    shared_data_->SetLastError(kViECodecUnknownError);
    return -1;
  }
  return 0;
}

int ViECodecImpl::SetSignalKeyPacketLossStatus(const int video_channel,
                                               const bool enable,
                                               const bool only_key_frames) {
  LOG(LS_INFO) << "SetSignalKeyPacketLossStatus for " << video_channel
               << "enable, " << enable
               << ", only key frames " << only_key_frames;

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  if (vie_channel->SetSignalPacketLossStatus(enable, only_key_frames) != 0) {
    shared_data_->SetLastError(kViECodecUnknownError);
    return -1;
  }
  return 0;
}

int ViECodecImpl::RegisterEncoderObserver(const int video_channel,
                                          ViEEncoderObserver& observer) {
  LOG(LS_INFO) << "RegisterEncoderObserver for channel " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  if (vie_encoder->RegisterCodecObserver(&observer) != 0) {
    shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
    return -1;
  }
  return 0;
}

int ViECodecImpl::DeregisterEncoderObserver(const int video_channel) {
  LOG(LS_INFO) << "DeregisterEncoderObserver for channel " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  if (vie_encoder->RegisterCodecObserver(NULL) != 0) {
    shared_data_->SetLastError(kViECodecObserverNotRegistered);
    return -1;
  }
  return 0;
}

int ViECodecImpl::RegisterDecoderObserver(const int video_channel,
                                          ViEDecoderObserver& observer) {
  LOG(LS_INFO) << "RegisterDecoderObserver for channel " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  if (vie_channel->RegisterCodecObserver(&observer) != 0) {
    shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
    return -1;
  }
  return 0;
}

int ViECodecImpl::DeregisterDecoderObserver(const int video_channel) {
  LOG(LS_INFO) << "DeregisterDecodeObserver for channel " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  if (vie_channel->RegisterCodecObserver(NULL) != 0) {
    shared_data_->SetLastError(kViECodecObserverNotRegistered);
    return -1;
  }
  return 0;
}

int ViECodecImpl::SendKeyFrame(const int video_channel) {
  LOG(LS_INFO) << "SendKeyFrame on channel " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  if (vie_encoder->SendKeyFrame() != 0) {
    shared_data_->SetLastError(kViECodecUnknownError);
    return -1;
  }
  return 0;
}

int ViECodecImpl::WaitForFirstKeyFrame(const int video_channel,
                                       const bool wait) {
  LOG(LS_INFO) << "WaitForFirstKeyFrame for channel " << video_channel
               << ", wait " << wait;

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  if (vie_channel->WaitForKeyFrame(wait) != 0) {
    shared_data_->SetLastError(kViECodecUnknownError);
    return -1;
  }
  return 0;
}

int ViECodecImpl::StartDebugRecording(int video_channel,
                                      const char* file_name_utf8) {
  LOG(LS_INFO) << "StartDebugRecording for channel " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    return -1;
  }
  return vie_encoder->StartDebugRecording(file_name_utf8);
}

int ViECodecImpl::StopDebugRecording(int video_channel) {
  LOG(LS_INFO) << "StopDebugRecording for channel " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    return -1;
  }
  return vie_encoder->StopDebugRecording();
}

void ViECodecImpl::SuspendBelowMinBitrate(int video_channel) {
  LOG(LS_INFO) << "SuspendBelowMinBitrate for channel " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    return;
  }
  vie_encoder->SuspendBelowMinBitrate();
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    return;
  }
  // Must enable pacing when enabling SuspendBelowMinBitrate. Otherwise, no
  // padding will be sent when the video is suspended so the video will be
  // unable to recover.
  vie_channel->SetTransmissionSmoothingStatus(true);
}

bool ViECodecImpl::GetSendSideDelay(int video_channel, int* avg_delay_ms,
                                   int* max_delay_ms) const {
  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return false;
  }
  return vie_channel->GetSendSideDelay(avg_delay_ms, max_delay_ms);
}

bool ViECodecImpl::CodecValid(const VideoCodec& video_codec) {
  // Check pl_name matches codec_type.
  if (video_codec.codecType == kVideoCodecRED) {
#if defined(WIN32)
    if (_strnicmp(video_codec.plName, "red", 3) == 0) {
#else
    if (strncasecmp(video_codec.plName, "red", 3) == 0) {
#endif
      // We only care about the type and name for red.
      return true;
    }
    LOG_F(LS_ERROR) << "Invalid RED configuration.";
    return false;
  } else if (video_codec.codecType == kVideoCodecULPFEC) {
#if defined(WIN32)
    if (_strnicmp(video_codec.plName, "ULPFEC", 6) == 0) {
#else
    if (strncasecmp(video_codec.plName, "ULPFEC", 6) == 0) {
#endif
      // We only care about the type and name for ULPFEC.
      return true;
    }
    LOG_F(LS_ERROR) << "Invalid ULPFEC configuration.";
    return false;
  } else if ((video_codec.codecType == kVideoCodecVP8 &&
              strncmp(video_codec.plName, "VP8", 4) == 0) ||
             (video_codec.codecType == kVideoCodecVP9 &&
              strncmp(video_codec.plName, "VP9", 4) == 0) ||
             (video_codec.codecType == kVideoCodecI420 &&
              strncmp(video_codec.plName, "I420", 4) == 0) ||
             (video_codec.codecType == kVideoCodecH264 &&
              strncmp(video_codec.plName, "H264", 4) == 0)) {
    // OK.
  } else if (video_codec.codecType != kVideoCodecGeneric) {
    LOG(LS_ERROR) << "Codec type and name mismatch.";
    return false;
  }

  if (video_codec.plType == 0 || video_codec.plType > 127) {
    LOG(LS_ERROR) << "Invalid payload type: "
                  << static_cast<int>(video_codec.plType);
    return false;
  }

  if (video_codec.width > kViEMaxCodecWidth ||
      video_codec.height > kViEMaxCodecHeight) {
    LOG(LS_ERROR) << "Invalid codec resolution " << video_codec.width
                  << " x " << video_codec.height;
    return false;
  }

  if (video_codec.startBitrate < kViEMinCodecBitrate) {
    LOG(LS_ERROR) << "Invalid start bitrate.";
    return false;
  }
  if (video_codec.minBitrate < kViEMinCodecBitrate) {
    LOG(LS_ERROR) << "Invalid min bitrate.";
    return false;
  }
  return true;
}

}  // namespace webrtc
