/*
 * libjingle
 * Copyright 2004--2011, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifdef HAVE_WEBRTC_VIDEO

#include "talk/session/phone/webrtcvideoengine.h"

#include "talk/base/common.h"
#include "talk/base/buffer.h"
#include "talk/base/byteorder.h"
#include "talk/base/logging.h"
#include "talk/base/stringutils.h"
#include "talk/session/phone/videorenderer.h"
#include "talk/session/phone/webrtcpassthroughrender.h"
#include "talk/session/phone/webrtcvoiceengine.h"
#include "talk/session/phone/webrtcvideoframe.h"
#include "talk/session/phone/webrtcvie.h"
#include "talk/session/phone/webrtcvoe.h"

namespace cricket {

static const int kDefaultLogSeverity = talk_base::LS_WARNING;
static const int kStartVideoBitrate = 300;
static const int kMaxVideoBitrate = 1000;

class WebRtcRenderAdapter : public webrtc::ExternalRenderer {
 public:
  explicit WebRtcRenderAdapter(VideoRenderer* renderer)
      : renderer_(renderer) {
  }

  virtual int FrameSizeChange(unsigned int width, unsigned int height,
                              unsigned int /*number_of_streams*/) {
    if (renderer_ == NULL)
      return 0;
    width_ = width;
    height_ = height;
    return renderer_->SetSize(width_, height_, 0) ? 0 : -1;
  }

  virtual int DeliverFrame(unsigned char* buffer, int buffer_size) {
    if (renderer_ == NULL)
      return 0;
    WebRtcVideoFrame video_frame;
    // TODO: Currently by the time DeliverFrame got called,
    // ViE expects the frame will be rendered ASAP. However, the libjingle
    // renderer may have its own internal delays. Can you disable the buffering
    // inside ViE and surface the timing information to this callback?
    video_frame.Attach(buffer, buffer_size, width_, height_, 0, 0);
    int ret = renderer_->RenderFrame(&video_frame) ? 0 : -1;
    uint8* buffer_temp;
    size_t buffer_size_temp;
    video_frame.Detach(&buffer_temp, &buffer_size_temp);
    return ret;
  }

  virtual ~WebRtcRenderAdapter() {}

 private:
  VideoRenderer* renderer_;
  unsigned int width_;
  unsigned int height_;
};

const WebRtcVideoEngine::VideoCodecPref
    WebRtcVideoEngine::kVideoCodecPrefs[] = {
    {"VP8", 120, 0},
};

// The formats are sorted by the descending order of width. We use the order to
// find the next format for CPU and bandwidth adaptation.
const VideoFormat WebRtcVideoEngine::kVideoFormats[] = {
  // TODO: Understand why we have problem with 16:9 formats.
  VideoFormat(1280, 800, VideoFormat::FpsToInterval(30), FOURCC_ANY),
//VideoFormat(1280, 720, VideoFormat::FpsToInterval(30), FOURCC_ANY),
  VideoFormat(960, 600, VideoFormat::FpsToInterval(30), FOURCC_ANY),
//VideoFormat(960, 540, VideoFormat::FpsToInterval(30), FOURCC_ANY),
  VideoFormat(640, 400, VideoFormat::FpsToInterval(30), FOURCC_ANY),
//VideoFormat(640, 360, VideoFormat::FpsToInterval(30), FOURCC_ANY),
  VideoFormat(480, 300, VideoFormat::FpsToInterval(30), FOURCC_ANY),
//VideoFormat(480, 270, VideoFormat::FpsToInterval(30), FOURCC_ANY),
  VideoFormat(320, 200, VideoFormat::FpsToInterval(30), FOURCC_ANY),
//VideoFormat(320, 180, VideoFormat::FpsToInterval(30), FOURCC_ANY),
  VideoFormat(240, 150, VideoFormat::FpsToInterval(30), FOURCC_ANY),
//VideoFormat(240, 135, VideoFormat::FpsToInterval(30), FOURCC_ANY),
  VideoFormat(160, 100, VideoFormat::FpsToInterval(30), FOURCC_ANY),
//VideoFormat(160, 90, VideoFormat::FpsToInterval(30), FOURCC_ANY),
};

// TODO: Understand why 640x400 is not working.
const VideoFormat WebRtcVideoEngine::kDefaultVideoFormat =
    VideoFormat(320, 200, VideoFormat::FpsToInterval(30), FOURCC_ANY);

WebRtcVideoEngine::WebRtcVideoEngine()
    : vie_wrapper_(new ViEWrapper()),
      capture_module_(NULL),
      external_capture_(false),
      render_module_(new WebRtcPassthroughRender()),
      voice_engine_(NULL) {
  Construct();
}

WebRtcVideoEngine::WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine,
                                     webrtc::VideoCaptureModule* capture)
    : vie_wrapper_(new ViEWrapper()),
      capture_module_(capture),
      external_capture_(true),
      render_module_(webrtc::VideoRender::CreateVideoRender(0, NULL, false,
          webrtc::kRenderExternal)),
      voice_engine_(voice_engine) {
  Construct();
}

WebRtcVideoEngine::WebRtcVideoEngine(WebRtcVoiceEngine* voice_engine,
                                     ViEWrapper* vie_wrapper)
    : vie_wrapper_(vie_wrapper),
      capture_module_(NULL),
      external_capture_(false),
      render_module_(new WebRtcPassthroughRender()),
      voice_engine_(voice_engine) {
  Construct();
}

void  WebRtcVideoEngine::Construct() {
  capture_id_ = -1;
  log_level_ = kDefaultLogSeverity;
  capture_started_ = false;

  ApplyLogging();
  if (vie_wrapper_->engine()->SetTraceCallback(this) != 0) {
    LOG_RTCERR1(SetTraceCallback, this);
  }

  // Set default quality levels for our supported codecs.  We override them here
  // if we know your cpu performance is low, and they can be updated explicitly
  // by calling SetDefaultCodec.  For example by a flute preference setting, or
  // by the server with a jec in response to our reported system info.
  VideoCodec max_codec(kVideoCodecPrefs[0].payload_type,
                       kVideoCodecPrefs[0].name,
                       kDefaultVideoFormat.width,
                       kDefaultVideoFormat.height,
                       kDefaultVideoFormat.framerate(), 0);
  if (!SetDefaultCodec(max_codec)) {
    LOG(LS_ERROR) << "Failed to initialize list of supported codec types";
  }
}

WebRtcVideoEngine::~WebRtcVideoEngine() {
  LOG(LS_INFO) << " WebRtcVideoEngine::~WebRtcVideoEngine";
  vie_wrapper_->engine()->SetTraceCallback(NULL);
  Terminate();
  vie_wrapper_.reset();
  if (capture_module_) {
    webrtc::VideoCaptureModule::Destroy(capture_module_);
  }
}

bool WebRtcVideoEngine::Init() {
  LOG(LS_INFO) << "WebRtcVideoEngine::Init";
  bool result = InitVideoEngine();
  if (result) {
    LOG(LS_INFO) << "VideoEngine Init done";
  } else {
    LOG(LS_ERROR) << "VideoEngine Init failed, releasing";
    Terminate();
  }
  return result;
}

bool WebRtcVideoEngine::InitVideoEngine() {
  LOG(LS_INFO) << "WebRtcVideoEngine::InitVideoEngine";

  if (vie_wrapper_->base()->Init() != 0) {
    LOG_RTCERR0(Init);
    return false;
  }

  if (!voice_engine_) {
    LOG(LS_WARNING) << "NULL voice engine";
  } else if ((vie_wrapper_->base()->SetVoiceEngine(
      voice_engine_->voe()->engine())) != 0) {
    LOG_RTCERR0(SetVoiceEngine);
    return false;
  }

  if ((vie_wrapper_->base()->RegisterObserver(*this)) != 0) {
    LOG_RTCERR0(RegisterObserver);
    return false;
  }

  if (vie_wrapper_->render()->RegisterVideoRenderModule(
      *render_module_.get()) != 0) {
    LOG_RTCERR0(RegisterVideoRenderModule);
    return false;
  }

  std::sort(video_codecs_.begin(), video_codecs_.end(),
            &VideoCodec::Preferable);
  return true;
}

void WebRtcVideoEngine::PerformanceAlarm(const unsigned int cpu_load) {
  LOG(LS_INFO) << "WebRtcVideoEngine::PerformanceAlarm";
}

// Ignore spammy trace messages, mostly from the stats API when we haven't
// gotten RTCP info yet from the remote side.
static bool ShouldIgnoreTrace(const std::string& trace) {
  static const char* kTracesToIgnore[] = {
    "\tfailed to GetReportBlockInformation",
    NULL
  };
  for (const char* const* p = kTracesToIgnore; *p; ++p) {
    if (trace.find(*p) == 0) {
      return true;
    }
  }
  return false;
}

void WebRtcVideoEngine::Print(const webrtc::TraceLevel level,
                              const char* trace, const int length) {
  talk_base::LoggingSeverity sev = talk_base::LS_VERBOSE;
  if (level == webrtc::kTraceError || level == webrtc::kTraceCritical)
    sev = talk_base::LS_ERROR;
  else if (level == webrtc::kTraceWarning)
    sev = talk_base::LS_WARNING;
  else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo)
    sev = talk_base::LS_INFO;

  if (sev >= log_level_) {
    // Skip past boilerplate prefix text
    if (length < 72) {
      std::string msg(trace, length);
      LOG(LS_ERROR) << "Malformed webrtc log message: ";
      LOG_V(sev) << msg;
    } else {
      std::string msg(trace + 71, length - 72);
      if (!ShouldIgnoreTrace(msg)) {
        LOG_V(sev) << "WebRtc ViE:" << msg;
      }
    }
  }
}

void WebRtcVideoEngine::ApplyLogging() {
  int filter = 0;
  switch (log_level_) {
    case talk_base::LS_VERBOSE: filter |= webrtc::kTraceAll;
    case talk_base::LS_INFO: filter |= webrtc::kTraceStateInfo;
    case talk_base::LS_WARNING: filter |= webrtc::kTraceWarning;
    case talk_base::LS_ERROR: filter |=
        webrtc::kTraceError | webrtc::kTraceCritical;
  }
}

// Rebuilds the codec list to be only those that are less intensive
// than the specified codec.
bool WebRtcVideoEngine::RebuildCodecList(const VideoCodec& in_codec) {
  if (!FindCodec(in_codec))
    return false;

  video_codecs_.clear();

  bool found = false;
  for (size_t i = 0; i < ARRAY_SIZE(kVideoCodecPrefs); ++i) {
    const VideoCodecPref& pref(kVideoCodecPrefs[i]);
    if (!found)
      found = (in_codec.name == pref.name);
    if (found) {
      VideoCodec codec(pref.payload_type, pref.name,
                       in_codec.width, in_codec.height, in_codec.framerate,
                       ARRAY_SIZE(kVideoCodecPrefs) - i);
      video_codecs_.push_back(codec);
    }
  }
  ASSERT(found);
  return true;
}

void WebRtcVideoEngine::Terminate() {
  LOG(LS_INFO) << "WebRtcVideoEngine::Terminate";
  SetCapture(false);
  if (local_renderer_.get()) {
    // If the renderer already set, stop it first
    if (vie_wrapper_->render()->StopRender(capture_id_) != 0)
      LOG_RTCERR1(StopRender, capture_id_);
  }

  if (vie_wrapper_->render()->DeRegisterVideoRenderModule(
      *render_module_.get()) != 0)
    LOG_RTCERR0(DeRegisterVideoRenderModule);

  if ((vie_wrapper_->base()->DeregisterObserver()) != 0)
    LOG_RTCERR0(DeregisterObserver);

  if ((vie_wrapper_->base()->SetVoiceEngine(NULL)) != 0)
    LOG_RTCERR0(SetVoiceEngine);

  if (vie_wrapper_->engine()->SetTraceCallback(NULL) != 0)
    LOG_RTCERR0(SetTraceCallback);
}

int WebRtcVideoEngine::GetCapabilities() {
  return VIDEO_RECV | VIDEO_SEND;
}

bool WebRtcVideoEngine::SetOptions(int options) {
  return true;
}

bool WebRtcVideoEngine::ReleaseCaptureDevice() {
  if (capture_id_ != -1) {
    // Stop capture
    SetCapture(false);
    // DisconnectCaptureDevice
    WebRtcVideoMediaChannel* channel;
    for (VideoChannels::const_iterator it = channels_.begin();
        it != channels_.end(); ++it) {
      ASSERT(*it != NULL);
      channel = *it;
      // Ignore the return value here as the channel may not have connected to
      // the capturer yet.
      vie_wrapper_->capture()->DisconnectCaptureDevice(
          channel->video_channel());
      channel->set_connected(false);
    }
    // ReleaseCaptureDevice
    vie_wrapper_->capture()->ReleaseCaptureDevice(capture_id_);
    capture_id_ = -1;
  }

  return true;
}

bool WebRtcVideoEngine::SetCaptureDevice(const Device* cam) {
  ASSERT(cam != NULL);

  ReleaseCaptureDevice();

  webrtc::ViECapture* vie_capture = vie_wrapper_->capture();

  // There's an external VCM
  if (capture_module_) {
    if (vie_capture->AllocateCaptureDevice(*capture_module_, capture_id_) != 0)
      ASSERT(capture_id_ == -1);
  } else if (!external_capture_) {
    char device_name[256], device_id[256];
    bool found = false;
    for (int i = 0; i < vie_capture->NumberOfCaptureDevices(); ++i) {
      if (vie_capture->GetCaptureDevice(i, device_name, sizeof(device_name),
                                        device_id, sizeof(device_id)) == 0) {
        // TODO: We should only compare the device_id here,
        // however the devicemanager and webrtc use different format for th v4l2
        // device id. So here we also compare the device_name for now.
        // For example "usb-0000:00:1d.7-6" vs "/dev/video0".
        if (cam->name.compare(device_name) == 0 ||
            cam->id.compare(device_id) == 0) {
          LOG(INFO) << "Found video capture device: " << device_name;
          found = true;
          break;
        }
      }
    }
    if (!found) {
      return false;
    }
    if (vie_capture->AllocateCaptureDevice(device_id, strlen(device_id),
                                           capture_id_) != 0) {
      ASSERT(capture_id_ == -1);
    }
  }

  if (capture_id_ != -1) {
    // Connect to all the channels if there is any.
    WebRtcVideoMediaChannel* channel;
    for (VideoChannels::const_iterator it = channels_.begin();
         it != channels_.end(); ++it) {
      ASSERT(*it != NULL);
      channel = *it;

      // No channel should have been connected yet.
      // In case of switching device, all channel connections should have been
      // disconnected in ReleaseCaptureDevice() first.
      ASSERT(!channel->connected());

      if (vie_capture->ConnectCaptureDevice(capture_id_,
                                            channel->video_channel()) == 0) {
        channel->set_connected(true);
      }
    }
    SetCapture(true);
  }

  return (capture_id_ != -1);
}

bool WebRtcVideoEngine::SetCaptureModule(webrtc::VideoCaptureModule* vcm) {
  ReleaseCaptureDevice();
  if (capture_module_) {
    webrtc::VideoCaptureModule::Destroy(capture_module_);
  }
  capture_module_ = vcm;
  external_capture_ = true;
  return true;
}

bool WebRtcVideoEngine::SetLocalRenderer(VideoRenderer* renderer) {
  if (local_renderer_.get()) {
    // If the renderer already set, stop and remove it first
    if (vie_wrapper_->render()->StopRender(capture_id_) != 0) {
      LOG_RTCERR1(StopRender, capture_id_);
    }
    if (vie_wrapper_->render()->RemoveRenderer(capture_id_) != 0) {
      LOG_RTCERR1(RemoveRenderer, capture_id_);
    }
  }
  local_renderer_.reset(new WebRtcRenderAdapter(renderer));

  int ret;
  ret = vie_wrapper_->render()->AddRenderer(capture_id_,
                                            webrtc::kVideoI420,
                                            local_renderer_.get());
  if (ret != 0)
    return false;
  ret = vie_wrapper_->render()->StartRender(capture_id_);
  return (ret == 0);
}

CaptureResult WebRtcVideoEngine::SetCapture(bool capture) {
  if ((capture_started_ != capture) && (capture_id_ != -1)) {
    int ret;
    if (capture)
      ret = vie_wrapper_->capture()->StartCapture(capture_id_);
    else
      ret = vie_wrapper_->capture()->StopCapture(capture_id_);
    if (ret != 0)
      return CR_NO_DEVICE;
    capture_started_ = capture;
  }
  return CR_SUCCESS;
}

const std::vector<VideoCodec>& WebRtcVideoEngine::codecs() const {
  return video_codecs_;
}

void WebRtcVideoEngine::SetLogging(int min_sev, const char* filter) {
  log_level_ = min_sev;
  ApplyLogging();
}

int WebRtcVideoEngine::GetLastEngineError() {
  return vie_wrapper_->error();
}

bool WebRtcVideoEngine::SetDefaultEncoderConfig(
    const VideoEncoderConfig& config) {
  default_encoder_config_ = config;
  return true;
}

WebRtcVideoMediaChannel* WebRtcVideoEngine::CreateChannel(
    VoiceMediaChannel* voice_channel) {
  WebRtcVideoMediaChannel* channel =
      new WebRtcVideoMediaChannel(this, voice_channel);
  if (channel) {
    if (!channel->Init()) {
      delete channel;
      channel = NULL;
    }
  }
  return channel;
}

// Checks to see whether we comprehend and could receive a particular codec
bool WebRtcVideoEngine::FindCodec(const VideoCodec& in) {
  for (int i = 0; i < ARRAY_SIZE(kVideoFormats); ++i) {
    const VideoFormat& fmt = kVideoFormats[i];
    if (fmt.width == in.width && fmt.height == in.height) {
      for (int j = 0; j < ARRAY_SIZE(kVideoCodecPrefs); ++j) {
        VideoCodec codec(kVideoCodecPrefs[j].payload_type,
                         kVideoCodecPrefs[j].name, 0, 0, 0, 0);
        if (codec.Matches(in)) {
          return true;
        }
      }
    }
  }
  return false;
}

// SetDefaultCodec may be called while the capturer is running. For example, a
// test call is started in a page with QVGA default codec, and then a real call
// is started in another page with VGA default codec. This is the corner case
// and happens only when a session is started. We ignore this case currently.
bool WebRtcVideoEngine::SetDefaultCodec(const VideoCodec& codec) {
  if (!RebuildCodecList(codec)) {
    LOG(LS_WARNING) << "Failed to RebuildCodecList";
    return false;
  }
  return true;
}

void WebRtcVideoEngine::ConvertToCricketVideoCodec(
    const webrtc::VideoCodec& in_codec, VideoCodec& out_codec) {
  out_codec.id = in_codec.plType;
  out_codec.name = in_codec.plName;
  out_codec.width = in_codec.width;
  out_codec.height = in_codec.height;
  out_codec.framerate = in_codec.maxFramerate;
}

bool WebRtcVideoEngine::ConvertFromCricketVideoCodec(
    const VideoCodec& in_codec, webrtc::VideoCodec& out_codec) {
  bool found = false;
  int ncodecs = vie_wrapper_->codec()->NumberOfCodecs();
  for (int i = 0; i < ncodecs; ++i) {
    if ((vie_wrapper_->codec()->GetCodec(i, out_codec) == 0) &&
        (strncmp(out_codec.plName,
                 in_codec.name.c_str(),
                 webrtc::kPayloadNameSize - 1) == 0)) {
      found = true;
      break;
    }
  }

  if (!found) {
    LOG(LS_ERROR) << "invalid codec type";
    return false;
  }

  if (in_codec.id != 0)
    out_codec.plType = in_codec.id;

  if (in_codec.width != 0)
    out_codec.width = in_codec.width;

  if (in_codec.height != 0)
    out_codec.height = in_codec.height;

  if (in_codec.framerate != 0)
    out_codec.maxFramerate = in_codec.framerate;

  out_codec.maxBitrate = kMaxVideoBitrate;
  out_codec.startBitrate = kStartVideoBitrate;
  out_codec.minBitrate = kStartVideoBitrate;

  return true;
}

int WebRtcVideoEngine::GetLastVideoEngineError() {
  return vie_wrapper_->base()->LastError();
}

void WebRtcVideoEngine::RegisterChannel(WebRtcVideoMediaChannel *channel) {
  channels_.push_back(channel);
}

void WebRtcVideoEngine::UnregisterChannel(WebRtcVideoMediaChannel *channel) {
  VideoChannels::iterator i = std::find(channels_.begin(),
                                      channels_.end(),
                                      channel);
  if (i != channels_.end()) {
    channels_.erase(i);
  }
}

// WebRtcVideoMediaChannel

WebRtcVideoMediaChannel::WebRtcVideoMediaChannel(
    WebRtcVideoEngine* engine, VoiceMediaChannel* channel)
    : engine_(engine),
      voice_channel_(channel),
      vie_channel_(-1),
      sending_(false),
      connected_(false),
      render_started_(false),
      send_codec_(NULL) {
  engine->RegisterChannel(this);
}

bool WebRtcVideoMediaChannel::Init() {
  bool ret = true;
  if (engine_->video_engine()->base()->CreateChannel(vie_channel_) != 0) {
    LOG_RTCERR1(CreateChannel, vie_channel_);
    return false;
  }

  LOG(LS_INFO) << "WebRtcVideoMediaChannel::Init "
               << "video_channel " << vie_channel_ << " created";

  // connect audio channel
  if (voice_channel_) {
    WebRtcVoiceMediaChannel* channel =
        static_cast<WebRtcVoiceMediaChannel*> (voice_channel_);
    if (engine_->video_engine()->base()->ConnectAudioChannel(
        vie_channel_, channel->voe_channel()) != 0) {
      LOG(LS_WARNING) << "ViE ConnectAudioChannel failed"
                   << "A/V not synchronized";
      // Don't set ret to false;
    }
  }

  // Register external transport
  if (engine_->video_engine()->network()->RegisterSendTransport(
      vie_channel_, *this) != 0) {
    ret = false;
  } else {
    EnableRtcp();
    EnablePLI();
  }
  return ret;
}

WebRtcVideoMediaChannel::~WebRtcVideoMediaChannel() {
  // Stop and remote renderer
  SetRender(false);
  if (engine()->video_engine()->render()->RemoveRenderer(vie_channel_)
      == -1) {
    LOG_RTCERR1(RemoveRenderer, vie_channel_);
  }

  // DeRegister external transport
  if (engine()->video_engine()->network()->DeregisterSendTransport(
      vie_channel_) == -1) {
    LOG_RTCERR1(DeregisterSendTransport, vie_channel_);
  }

  // Unregister RtcChannel with the engine.
  engine()->UnregisterChannel(this);

  // Delete VideoChannel
  if (engine()->video_engine()->base()->DeleteChannel(vie_channel_) == -1) {
    LOG_RTCERR1(DeleteChannel, vie_channel_);
  }
}

bool WebRtcVideoMediaChannel::SetRecvCodecs(
    const std::vector<VideoCodec>& codecs) {
  bool ret = true;
  for (std::vector<VideoCodec>::const_iterator iter = codecs.begin();
      iter != codecs.end(); ++iter) {
    if (engine()->FindCodec(*iter)) {
      webrtc::VideoCodec wcodec;
      if (engine()->ConvertFromCricketVideoCodec(*iter, wcodec)) {
        if (engine()->video_engine()->codec()->SetReceiveCodec(
            vie_channel_,  wcodec) != 0) {
          LOG_RTCERR2(SetReceiveCodec, vie_channel_, wcodec.plName);
          ret = false;
        }
      }
    } else {
      LOG(LS_INFO) << "Unknown codec" << iter->name;
      ret = false;
    }
  }

  // make channel ready to receive packets
  if (ret) {
    if (engine()->video_engine()->base()->StartReceive(vie_channel_) != 0) {
      LOG_RTCERR1(StartReceive, vie_channel_);
      ret = false;
    }
  }
  return ret;
}

bool WebRtcVideoMediaChannel::SetSendCodecs(
    const std::vector<VideoCodec>& codecs) {
  if (sending_) {
    LOG(LS_ERROR) << "channel is alredy sending";
    return false;
  }

  // match with local video codec list
  std::vector<webrtc::VideoCodec> send_codecs;
  for (std::vector<VideoCodec>::const_iterator iter = codecs.begin();
      iter != codecs.end(); ++iter) {
    if (engine()->FindCodec(*iter)) {
      webrtc::VideoCodec wcodec;
      if (engine()->ConvertFromCricketVideoCodec(*iter, wcodec))
        send_codecs.push_back(wcodec);
    }
  }

  // if none matches, return with set
  if (send_codecs.empty()) {
    LOG(LS_ERROR) << "No matching codecs avilable";
    return false;
  }

  // select the first matched codec
  const webrtc::VideoCodec& codec(send_codecs[0]);
  send_codec_.reset(new webrtc::VideoCodec(codec));
  if (engine()->video_engine()->codec()->SetSendCodec(
      vie_channel_, codec) != 0) {
    LOG_RTCERR2(SetSendCodec, vie_channel_, codec.plName);
    return false;
  }
  return true;
}

bool WebRtcVideoMediaChannel::SetRender(bool render) {
  if (render != render_started_) {
    int ret;
    if (render) {
      ret = engine()->video_engine()->render()->StartRender(vie_channel_);
    } else {
      ret = engine()->video_engine()->render()->StopRender(vie_channel_);
    }
    if (ret != 0) {
      return false;
    }
    render_started_ = render;
  }
  return true;
}

bool WebRtcVideoMediaChannel::SetSend(bool send) {
  if (send == sending()) {
    return true;  // no action required
  }

  bool ret = true;
  if (send) {  // enable
    if (engine()->video_engine()->base()->StartSend(vie_channel_) != 0) {
      LOG_RTCERR1(StartSend, vie_channel_);
      ret = false;
    }

    // If the channel has not been connected to the capturer yet,
    // connect it now.
    if (!connected()) {
      if (engine()->video_engine()->capture()->ConnectCaptureDevice(
          engine()->capture_id(), vie_channel_) != 0) {
        LOG_RTCERR2(ConnectCaptureDevice, engine()->capture_id(), vie_channel_);
        ret = false;
      } else {
        set_connected(true);
      }
    }
  } else {  // disable
    if (engine()->video_engine()->base()->StopSend(vie_channel_) != 0) {
      LOG_RTCERR1(StopSend, vie_channel_);
      ret = false;
    }
  }
  if (ret) {
    sending_ = send;
  }

  return ret;
}

bool WebRtcVideoMediaChannel::AddStream(uint32 ssrc, uint32 voice_ssrc) {
  return false;
}

bool WebRtcVideoMediaChannel::RemoveStream(uint32 ssrc) {
  return false;
}

bool WebRtcVideoMediaChannel::SetRenderer(
    uint32 ssrc, VideoRenderer* renderer) {
  ASSERT(vie_channel_ != -1);
  if (ssrc != 0)
    return false;
  if (remote_renderer_.get()) {
    // If the renderer already set, stop and remove it first
    if (engine_->video_engine()->render()->StopRender(vie_channel_) != 0) {
      LOG_RTCERR1(StopRender, vie_channel_);
    }
    if (engine_->video_engine()->render()->RemoveRenderer(vie_channel_) != 0) {
      LOG_RTCERR1(RemoveRenderer, vie_channel_);
    }
  }
  remote_renderer_.reset(new WebRtcRenderAdapter(renderer));

  if (engine_->video_engine()->render()->AddRenderer(vie_channel_,
      webrtc::kVideoI420, remote_renderer_.get()) != 0) {
    LOG_RTCERR3(AddRenderer, vie_channel_, webrtc::kVideoI420,
                remote_renderer_.get());
    remote_renderer_.reset();
    return false;
  }

  if (engine_->video_engine()->render()->StartRender(vie_channel_) != 0) {
    LOG_RTCERR1(StartRender, vie_channel_);
    return false;
  }

  return true;
}

bool WebRtcVideoMediaChannel::GetStats(VideoMediaInfo* info) {
  VideoSenderInfo sinfo;
  memset(&sinfo, 0, sizeof(sinfo));

  unsigned int ssrc;
  if (engine_->video_engine()->rtp()->GetLocalSSRC(vie_channel_,
                                                   ssrc) != 0) {
    LOG_RTCERR2(GetLocalSSRC, vie_channel_, ssrc);
    return false;
  }
  sinfo.ssrc = ssrc;

  unsigned int cumulative_lost, extended_max, jitter;
  int rtt_ms;
  uint16 fraction_lost;

  if (engine_->video_engine()->rtp()->GetReceivedRTCPStatistics(vie_channel_,
          fraction_lost, cumulative_lost, extended_max, jitter, rtt_ms) != 0) {
    LOG_RTCERR6(GetReceivedRTCPStatistics, vie_channel_,
        fraction_lost, cumulative_lost, extended_max, jitter, rtt_ms);
    return false;
  }

  sinfo.fraction_lost = fraction_lost;
  sinfo.packets_lost = cumulative_lost;
  sinfo.rtt_ms = rtt_ms;

  unsigned int bytes_sent, packets_sent, bytes_recv, packets_recv;
  if (engine_->video_engine()->rtp()->GetRTPStatistics(vie_channel_,
          bytes_sent, packets_sent, bytes_recv, packets_recv) != 0) {
    LOG_RTCERR5(GetRTPStatistics, vie_channel_,
        bytes_sent, packets_sent, bytes_recv, packets_recv);
    return false;
  }
  sinfo.packets_sent = packets_sent;
  sinfo.bytes_sent = bytes_sent;
  sinfo.packets_lost = -1;
  sinfo.packets_cached = -1;

  info->senders.push_back(sinfo);

  // build receiver info.
  // reusing the above local variables
  VideoReceiverInfo rinfo;
  memset(&rinfo, 0, sizeof(rinfo));
  if (engine_->video_engine()->rtp()->GetSentRTCPStatistics(vie_channel_,
          fraction_lost, cumulative_lost, extended_max, jitter, rtt_ms) != 0) {
    LOG_RTCERR6(GetSentRTCPStatistics, vie_channel_,
        fraction_lost, cumulative_lost, extended_max, jitter, rtt_ms);
    return false;
  }
  rinfo.bytes_rcvd = bytes_recv;
  rinfo.packets_rcvd = packets_recv;
  rinfo.fraction_lost = fraction_lost;
  rinfo.packets_lost = cumulative_lost;

  if (engine_->video_engine()->rtp()->GetRemoteSSRC(vie_channel_,
                                                    ssrc) != 0) {
    return false;
  }
  rinfo.ssrc = ssrc;

  // Get codec for wxh
  info->receivers.push_back(rinfo);
  return true;
}

bool WebRtcVideoMediaChannel::SendIntraFrame() {
  bool ret = true;
  if (engine()->video_engine()->codec()->SendKeyFrame(vie_channel_) != 0) {
    LOG_RTCERR1(SendKeyFrame, vie_channel_);
    ret = false;
  }

  return ret;
}

bool WebRtcVideoMediaChannel::RequestIntraFrame() {
  // There is no API exposed to application to request a key frame
  // ViE does this internally when there are errors from decoder
  return false;
}

void WebRtcVideoMediaChannel::OnPacketReceived(talk_base::Buffer* packet) {
  engine()->video_engine()->network()->ReceivedRTPPacket(vie_channel_,
                                                         packet->data(),
                                                         packet->length());
}

void WebRtcVideoMediaChannel::OnRtcpReceived(talk_base::Buffer* packet) {
  engine_->video_engine()->network()->ReceivedRTCPPacket(vie_channel_,
                                                         packet->data(),
                                                         packet->length());
}

void WebRtcVideoMediaChannel::SetSendSsrc(uint32 id) {
  if (!sending_) {
    if (engine()->video_engine()->rtp()->SetLocalSSRC(vie_channel_,
                                                      id) != 0) {
      LOG_RTCERR1(SetLocalSSRC, vie_channel_);
    }
  } else {
    LOG(LS_ERROR) << "Channel already in send state";
  }
}

bool WebRtcVideoMediaChannel::SetRtcpCName(const std::string& cname) {
  if (engine()->video_engine()->rtp()->SetRTCPCName(vie_channel_,
                                                    cname.c_str()) != 0) {
    LOG_RTCERR2(SetRTCPCName, vie_channel_, cname.c_str());
    return false;
  }
  return true;
}

bool WebRtcVideoMediaChannel::Mute(bool on) {
  // stop send??
  return false;
}

bool WebRtcVideoMediaChannel::SetSendBandwidth(bool autobw, int bps) {
  LOG(LS_INFO) << "RtcVideoMediaChanne::SetSendBandwidth";

  if (!send_codec_.get()) {
    LOG(LS_INFO) << "The send codec has not been set up yet.";
    return true;
  }

  if (!autobw) {
    send_codec_->startBitrate = bps;
    send_codec_->minBitrate = bps;
  }
  send_codec_->maxBitrate = bps;

  if (engine()->video_engine()->codec()->SetSendCodec(vie_channel_,
      *send_codec_.get()) != 0) {
    LOG_RTCERR2(SetSendCodec, vie_channel_, send_codec_->plName);
    return false;
  }

  return true;
}

bool WebRtcVideoMediaChannel::SetOptions(int options) {
  return true;
}

void WebRtcVideoMediaChannel::EnableRtcp() {
  engine()->video_engine()->rtp()->SetRTCPStatus(
      vie_channel_, webrtc::kRtcpCompound_RFC4585);
}

void WebRtcVideoMediaChannel::EnablePLI() {
  engine_->video_engine()->rtp()->SetKeyFrameRequestMethod(
      vie_channel_, webrtc::kViEKeyFrameRequestPliRtcp);
}

void WebRtcVideoMediaChannel::EnableTMMBR() {
  engine_->video_engine()->rtp()->SetTMMBRStatus(vie_channel_, true);
}

int WebRtcVideoMediaChannel::SendPacket(int channel, const void* data,
                                        int len) {
  if (!network_interface_) {
    return -1;
  }
  talk_base::Buffer packet(data, len, kMaxRtpPacketLen);
  return network_interface_->SendPacket(&packet) ? len : -1;
}

int WebRtcVideoMediaChannel::SendRTCPPacket(int channel,
                                         const void* data,
                                         int len) {
  if (!network_interface_) {
    return -1;
  }
  talk_base::Buffer packet(data, len, kMaxRtpPacketLen);
  return network_interface_->SendRtcp(&packet) ? len : -1;
}

}  // namespace cricket

#endif  // HAVE_WEBRTC_VIDEO

