/*
 *  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 "video_engine/vie_codec_impl.h"

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

namespace webrtc {

ViECodec* ViECodec::GetInterface(VideoEngine* video_engine) {
#ifdef WEBRTC_VIDEO_ENGINE_CODEC_API
  if (!video_engine) {
    return NULL;
  }
  VideoEngineImpl* vie_impl = reinterpret_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() {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, shared_data_->instance_id(),
               "ViECodecImpl::Release()");
  // Decrease ref count.
  (*this)--;

  WebRtc_Word32 ref_count = GetCount();
  if (ref_count < 0) {
    WEBRTC_TRACE(kTraceWarning, kTraceVideo, shared_data_->instance_id(),
                 "ViECodec released too many times");
    shared_data_->SetLastError(kViEAPIDoesNotExist);
    return -1;
  }
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, shared_data_->instance_id(),
               "ViECodec reference count: %d", ref_count);
  return ref_count;
}

ViECodecImpl::ViECodecImpl(ViESharedData* shared_data)
    : shared_data_(shared_data) {
  WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_->instance_id(),
               "ViECodecImpl::ViECodecImpl() Ctor");
}

ViECodecImpl::~ViECodecImpl() {
  WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_->instance_id(),
               "ViECodecImpl::~ViECodecImpl() Dtor");
}

int ViECodecImpl::NumberOfCodecs() const {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
               "%s", __FUNCTION__);
  // +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 {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
               "%s(list_number: %d, codec_type: %d)", __FUNCTION__,
               list_number, video_codec.codecType);
  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) {
    WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
                 "%s: Could not get codec for list_number: %u", __FUNCTION__,
                 list_number);
    shared_data_->SetLastError(kViECodecInvalidArgument);
    return -1;
  }
  return 0;
}

int ViECodecImpl::SetSendCodec(const int video_channel,
                               const VideoCodec& video_codec) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_->instance_id(),video_channel),
               "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
               video_channel, video_codec.codecType);
  WEBRTC_TRACE(kTraceInfo, kTraceVideo,
               ViEId(shared_data_->instance_id(), video_channel),
               "%s: codec: %d, pl_type: %d, width: %d, height: %d, bitrate: %d"
               "maxBr: %d, min_br: %d, frame_rate: %d, qpMax: %u,"
               "numberOfSimulcastStreams: %u )", __FUNCTION__,
               video_codec.codecType, video_codec.plType, video_codec.width,
               video_codec.height, video_codec.startBitrate,
               video_codec.maxBitrate, video_codec.minBitrate,
               video_codec.maxFramerate, video_codec.qpMax,
               video_codec.numberOfSimulcastStreams);
  if (video_codec.codecType == kVideoCodecVP8) {
    WEBRTC_TRACE(kTraceInfo, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "pictureLossIndicationOn: %d, feedbackModeOn: %d, "
                 "complexity: %d, resilience: %d, numberOfTemporalLayers: %u",
                 video_codec.codecSpecific.VP8.pictureLossIndicationOn,
                 video_codec.codecSpecific.VP8.feedbackModeOn,
                 video_codec.codecSpecific.VP8.complexity,
                 video_codec.codecSpecific.VP8.resilience,
                 video_codec.codecSpecific.VP8.numberOfTemporalLayers);
  }
  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) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No channel %d", __FUNCTION__, video_channel);
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    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;
    if (video_codec_internal.startBitrate > video_codec_internal.maxBitrate) {
      // Don't limit the set start bitrate.
      video_codec_internal.maxBitrate = video_codec_internal.startBitrate;
    }
    WEBRTC_TRACE(kTraceInfo, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: New max bitrate set to %d kbps", __FUNCTION__,
                 video_codec_internal.maxBitrate);
  }

  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    assert(false);
    WEBRTC_TRACE(kTraceInfo, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No encoder found for channel %d", __FUNCTION__);
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }

  VideoCodec encoder;
  vie_encoder->GetEncoder(encoder);
  if (encoder.codecType != video_codec_internal.codecType &&
      cs.ChannelUsingViEEncoder(video_channel)) {
      // We don't allow changing codec type when several channels share encoder.
      WEBRTC_TRACE(kTraceInfo, kTraceVideo,
                   ViEId(shared_data_->instance_id(), video_channel),
                   "%s: Settings differs from other channels using encoder",
                   __FUNCTION__);
      shared_data_->SetLastError(kViECodecInUse);
      return -1;
  }
  // 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 = false;
  if (encoder.codecType != video_codec_internal.codecType ||
      encoder.width != video_codec_internal.width ||
      encoder.height != video_codec_internal.height) {
    new_rtp_stream = true;
  }
  if (video_codec_internal.numberOfSimulcastStreams > 1) {
    if (cs.ChannelUsingViEEncoder(video_channel)) {
      // We don't allow simulcast channels to share encoder.
      WEBRTC_TRACE(kTraceInfo, kTraceVideo,
                   ViEId(shared_data_->instance_id(), video_channel),
                   "%s: Can't share simulcast encoder",
                   __FUNCTION__);
      shared_data_->SetLastError(kViECodecInUse);
      return -1;
    }
  }

  ViEInputManagerScoped is(*(shared_data_->input_manager()));
  ViEFrameProviderBase* frame_provider = NULL;

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

  // Check if we have a frame provider that is a camera and can provide this
  // codec for us.
  bool use_capture_device_as_encoder = false;
  frame_provider = is.FrameProvider(vie_encoder);
  if (frame_provider) {
    if (frame_provider->Id() >= kViECaptureIdBase &&
        frame_provider->Id() <= kViECaptureIdMax) {
      ViECapturer* vie_capture = static_cast<ViECapturer*>(frame_provider);
      // Try to get preencoded. Nothing to do if it is not supported.
      if (vie_capture && vie_capture->PreEncodeToViEEncoder(
          video_codec_internal,
          *vie_encoder,
          video_channel) == 0) {
        use_capture_device_as_encoder = true;
      }
    }
  }

  // Update the encoder settings if we are not using a capture device capable
  // of this codec.
  if (!use_capture_device_as_encoder &&
      vie_encoder->SetEncoder(video_codec_internal) != 0) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: Could not change encoder for channel %d", __FUNCTION__,
                 video_channel);
    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) {
      WEBRTC_TRACE(kTraceError, kTraceVideo,
                   ViEId(shared_data_->instance_id(), video_channel),
                   "%s: Could not set send codec for channel %d", __FUNCTION__,
                   video_channel);
      ret = false;
    }
    if (!ret) {
      shared_data_->SetLastError(kViECodecUnknownError);
      return -1;
    }
  }

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

  // Get new best format for frame provider.
  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 {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_->instance_id(), video_channel),
               "%s(video_channel: %d)", __FUNCTION__, video_channel);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  return vie_encoder->GetEncoder(video_codec);
}

int ViECodecImpl::SetReceiveCodec(const int video_channel,
                                  const VideoCodec& video_codec) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_->instance_id(), video_channel),
               "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
               video_channel, video_codec.codecType);
  WEBRTC_TRACE(kTraceInfo, kTraceVideo,
               ViEId(shared_data_->instance_id(), video_channel),
               "%s: codec: %d, pl_type: %d, width: %d, height: %d, bitrate: %d,"
               "maxBr: %d, min_br: %d, frame_rate: %d", __FUNCTION__,
               video_codec.codecType, video_codec.plType, video_codec.width,
               video_codec.height, video_codec.startBitrate,
               video_codec.maxBitrate, video_codec.minBitrate,
               video_codec.maxFramerate);

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

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No channel %d", __FUNCTION__, video_channel);
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }

  if (vie_channel->SetReceiveCodec(video_codec) != 0) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: Could not set receive codec for channel %d",
                 __FUNCTION__, video_channel);
    shared_data_->SetLastError(kViECodecUnknownError);
    return -1;
  }
  return 0;
}

int ViECodecImpl::GetReceiveCodec(const int video_channel,
                                  VideoCodec& video_codec) const {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_->instance_id(), video_channel),
               "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
               video_channel, video_codec.codecType);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No channel %d", __FUNCTION__, video_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 {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_->instance_id(), video_channel),
               "%s(video_channel: %d)", __FUNCTION__, video_channel);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
    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) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_->instance_id(), video_channel),
               "%s(video_channel: %d, enable: %d)", __FUNCTION__, video_channel,
               enable);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No channel %d", __FUNCTION__, video_channel);
    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 {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_->instance_id(), video_channel),
               "%s(video_channel %d)", __FUNCTION__, video_channel);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No send codec for channel %d", __FUNCTION__,
                 video_channel);
    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 {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_->instance_id(), video_channel),
               "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
               video_channel);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No channel %d", __FUNCTION__, video_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::GetCodecTargetBitrate(const int video_channel,
                                        unsigned int* bitrate) const {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_->instance_id(), video_channel),
               "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
               video_channel);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No send codec for channel %d", __FUNCTION__,
                 video_channel);
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  return vie_encoder->CodecTargetBitrate(static_cast<WebRtc_UWord32*>(bitrate));
}

unsigned int ViECodecImpl::GetDiscardedPackets(const int video_channel) const {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_->instance_id(), video_channel),
               "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
               video_channel);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No channel %d", __FUNCTION__, video_channel);
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  return vie_channel->DiscardedPackets();
}

int ViECodecImpl::SetKeyFrameRequestCallbackStatus(const int video_channel,
                                                   const bool enable) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_->instance_id(), video_channel),
               "%s(video_channel: %d)", __FUNCTION__, video_channel);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No channel %d", __FUNCTION__, video_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) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_->instance_id(), video_channel),
               "%s(video_channel: %d, enable: %d, only_key_frames: %d)",
               __FUNCTION__, video_channel, enable);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No channel %d", __FUNCTION__, video_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) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
               "%s", __FUNCTION__);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  if (vie_encoder->RegisterCodecObserver(&observer) != 0) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: Could not register codec observer at channel",
                 __FUNCTION__);
    shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
    return -1;
  }
  return 0;
}

int ViECodecImpl::DeregisterEncoderObserver(const int video_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
               "%s", __FUNCTION__);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
    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) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
               "%s", __FUNCTION__);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No channel %d", __FUNCTION__, video_channel);
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  if (vie_channel->RegisterCodecObserver(&observer) != 0) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: Could not register codec observer at channel",
                 __FUNCTION__);
    shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
    return -1;
  }
  return 0;
}

int ViECodecImpl::DeregisterDecoderObserver(const int video_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_->instance_id()), "%s",
               __FUNCTION__);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No channel %d", __FUNCTION__, video_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) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
               "%s(video_channel: %d)", __FUNCTION__, video_channel);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No channel %d", __FUNCTION__, video_channel);
    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) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_->instance_id()),
               "%s(video_channel: %d, wait: %d)", __FUNCTION__, video_channel,
               wait);

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_->instance_id(), video_channel),
                 "%s: No channel %d", __FUNCTION__, video_channel);
    shared_data_->SetLastError(kViECodecInvalidChannelId);
    return -1;
  }
  if (vie_channel->WaitForKeyFrame(wait) != 0) {
    shared_data_->SetLastError(kViECodecUnknownError);
    return -1;
  }
  return 0;
}

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;
    }
    WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
                 "Codec type doesn't match pl_name", video_codec.plType);
    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;
    }
    WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
                 "Codec type doesn't match pl_name", video_codec.plType);
    return false;
  } else if ((video_codec.codecType == kVideoCodecVP8 &&
                  strncmp(video_codec.plName, "VP8", 4) == 0) ||
              (video_codec.codecType == kVideoCodecI420 &&
                  strncmp(video_codec.plName, "I420", 4) == 0)) {
    // OK.
  } else {
    WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
                 "Codec type doesn't match pl_name", video_codec.plType);
    return false;
  }

  if (video_codec.plType == 0 && video_codec.plType > 127) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
                 "Invalid codec payload type: %d", video_codec.plType);
    return false;
  }

  if (video_codec.width > kViEMaxCodecWidth ||
      video_codec.height > kViEMaxCodecHeight) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Invalid codec size: %u x %u",
                 video_codec.width, video_codec.height);
    return false;
  }

  if (video_codec.startBitrate < kViEMinCodecBitrate) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Invalid start_bitrate: %u",
                 video_codec.startBitrate);
    return false;
  }
  if (video_codec.minBitrate < kViEMinCodecBitrate) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Invalid min_bitrate: %u",
                 video_codec.minBitrate);
    return false;
  }
  if (video_codec.numberOfSimulcastStreams == 1) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
                 "Number of Simulcast streams can not be 1");
    return false;
  }
  return true;
}

}  // namespace webrtc
