/*
 * libjingle
 * Copyright 2004 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_CONFIG_H
#include <config.h>
#endif

#ifdef HAVE_WEBRTC_VOICE

#include "talk/media/webrtc/webrtcvoiceengine.h"

#include <algorithm>
#include <cstdio>
#include <string>
#include <vector>

#include "talk/media/base/audiorenderer.h"
#include "talk/media/base/constants.h"
#include "talk/media/base/streamparams.h"
#include "talk/media/base/voiceprocessor.h"
#include "talk/media/webrtc/webrtcvoe.h"
#include "webrtc/base/base64.h"
#include "webrtc/base/byteorder.h"
#include "webrtc/base/common.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/stringencode.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/common.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/video_engine/include/vie_network.h"

#ifdef WIN32
#include <objbase.h>  // NOLINT
#endif

namespace cricket {

struct CodecPref {
  const char* name;
  int clockrate;
  int channels;
  int payload_type;
  bool is_multi_rate;
};

static const CodecPref kCodecPrefs[] = {
  { "OPUS",   48000,  2, 111, true },
  { "ISAC",   16000,  1, 103, true },
  { "ISAC",   32000,  1, 104, true },
  // G722 should be advertised as 8000 Hz because of the RFC "bug".
  { "G722",   8000,   1, 9,   false },
  { "ILBC",   8000,   1, 102, false },
  { "PCMU",   8000,   1, 0,   false },
  { "PCMA",   8000,   1, 8,   false },
  { "CN",     48000,  1, 107, false },
  { "CN",     32000,  1, 106, false },
  { "CN",     16000,  1, 105, false },
  { "CN",     8000,   1, 13,  false },
  { "red",    8000,   1, 127, false },
  { "telephone-event", 8000, 1, 126, false },
};

// For Linux/Mac, using the default device is done by specifying index 0 for
// VoE 4.0 and not -1 (which was the case for VoE 3.5).
//
// On Windows Vista and newer, Microsoft introduced the concept of "Default
// Communications Device". This means that there are two types of default
// devices (old Wave Audio style default and Default Communications Device).
//
// On Windows systems which only support Wave Audio style default, uses either
// -1 or 0 to select the default device.
//
// On Windows systems which support both "Default Communication Device" and
// old Wave Audio style default, use -1 for Default Communications Device and
// -2 for Wave Audio style default, which is what we want to use for clips.
// It's not clear yet whether the -2 index is handled properly on other OSes.

#ifdef WIN32
static const int kDefaultAudioDeviceId = -1;
static const int kDefaultSoundclipDeviceId = -2;
#else
static const int kDefaultAudioDeviceId = 0;
#endif

static const char kIsacCodecName[] = "ISAC";
static const char kL16CodecName[] = "L16";
static const char kG722CodecName[] = "G722";

// Parameter used for NACK.
// This value is equivalent to 5 seconds of audio data at 20 ms per packet.
static const int kNackMaxPackets = 250;

// Codec parameters for Opus.
// draft-spittka-payload-rtp-opus-03

// Recommended bitrates:
// 8-12 kb/s for NB speech,
// 16-20 kb/s for WB speech,
// 28-40 kb/s for FB speech,
// 48-64 kb/s for FB mono music, and
// 64-128 kb/s for FB stereo music.
// The current implementation applies the following values to mono signals,
// and multiplies them by 2 for stereo.
static const int kOpusBitrateNb = 12000;
static const int kOpusBitrateWb = 20000;
static const int kOpusBitrateFb = 32000;

// Opus bitrate should be in the range between 6000 and 510000.
static const int kOpusMinBitrate = 6000;
static const int kOpusMaxBitrate = 510000;

// Default audio dscp value.
// See http://tools.ietf.org/html/rfc2474 for details.
// See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00
static const rtc::DiffServCodePoint kAudioDscpValue = rtc::DSCP_EF;

// Ensure we open the file in a writeable path on ChromeOS and Android. This
// workaround can be removed when it's possible to specify a filename for audio
// option based AEC dumps.
//
// TODO(grunell): Use a string in the options instead of hardcoding it here
// and let the embedder choose the filename (crbug.com/264223).
//
// NOTE(ajm): Don't use hardcoded paths on platforms not explicitly specified
// below.
#if defined(CHROMEOS)
static const char kAecDumpByAudioOptionFilename[] = "/tmp/audio.aecdump";
#elif defined(ANDROID)
static const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump";
#else
static const char kAecDumpByAudioOptionFilename[] = "audio.aecdump";
#endif

// Dumps an AudioCodec in RFC 2327-ish format.
static std::string ToString(const AudioCodec& codec) {
  std::stringstream ss;
  ss << codec.name << "/" << codec.clockrate << "/" << codec.channels
     << " (" << codec.id << ")";
  return ss.str();
}
static std::string ToString(const webrtc::CodecInst& codec) {
  std::stringstream ss;
  ss << codec.plname << "/" << codec.plfreq << "/" << codec.channels
     << " (" << codec.pltype << ")";
  return ss.str();
}

static void LogMultiline(rtc::LoggingSeverity sev, char* text) {
  const char* delim = "\r\n";
  for (char* tok = strtok(text, delim); tok; tok = strtok(NULL, delim)) {
    LOG_V(sev) << tok;
  }
}

// Severity is an integer because it comes is assumed to be from command line.
static int SeverityToFilter(int severity) {
  int filter = webrtc::kTraceNone;
  switch (severity) {
    case rtc::LS_VERBOSE:
      filter |= webrtc::kTraceAll;
    case rtc::LS_INFO:
      filter |= (webrtc::kTraceStateInfo | webrtc::kTraceInfo);
    case rtc::LS_WARNING:
      filter |= (webrtc::kTraceTerseInfo | webrtc::kTraceWarning);
    case rtc::LS_ERROR:
      filter |= (webrtc::kTraceError | webrtc::kTraceCritical);
  }
  return filter;
}

static bool IsCodecMultiRate(const webrtc::CodecInst& codec) {
  for (size_t i = 0; i < ARRAY_SIZE(kCodecPrefs); ++i) {
    if (_stricmp(kCodecPrefs[i].name, codec.plname) == 0 &&
        kCodecPrefs[i].clockrate == codec.plfreq) {
      return kCodecPrefs[i].is_multi_rate;
    }
  }
  return false;
}

static bool IsTelephoneEventCodec(const std::string& name) {
  return _stricmp(name.c_str(), "telephone-event") == 0;
}

static bool IsCNCodec(const std::string& name) {
  return _stricmp(name.c_str(), "CN") == 0;
}

static bool IsRedCodec(const std::string& name) {
  return _stricmp(name.c_str(), "red") == 0;
}

static bool FindCodec(const std::vector<AudioCodec>& codecs,
                      const AudioCodec& codec,
                      AudioCodec* found_codec) {
  for (std::vector<AudioCodec>::const_iterator it = codecs.begin();
       it != codecs.end(); ++it) {
    if (it->Matches(codec)) {
      if (found_codec != NULL) {
        *found_codec = *it;
      }
      return true;
    }
  }
  return false;
}

static bool IsNackEnabled(const AudioCodec& codec) {
  return codec.HasFeedbackParam(FeedbackParam(kRtcpFbParamNack,
                                              kParamValueEmpty));
}

// Gets the default set of options applied to the engine. Historically, these
// were supplied as a combination of flags from the channel manager (ec, agc,
// ns, and highpass) and the rest hardcoded in InitInternal.
static AudioOptions GetDefaultEngineOptions() {
  AudioOptions options;
  options.echo_cancellation.Set(true);
  options.auto_gain_control.Set(true);
  options.noise_suppression.Set(true);
  options.highpass_filter.Set(true);
  options.stereo_swapping.Set(false);
  options.typing_detection.Set(true);
  options.conference_mode.Set(false);
  options.adjust_agc_delta.Set(0);
  options.experimental_agc.Set(false);
  options.experimental_aec.Set(false);
  options.experimental_ns.Set(false);
  options.aec_dump.Set(false);
  return options;
}

class WebRtcSoundclipMedia : public SoundclipMedia {
 public:
  explicit WebRtcSoundclipMedia(WebRtcVoiceEngine *engine)
      : engine_(engine), webrtc_channel_(-1) {
    engine_->RegisterSoundclip(this);
  }

  virtual ~WebRtcSoundclipMedia() {
    engine_->UnregisterSoundclip(this);
    if (webrtc_channel_ != -1) {
      // We shouldn't have to call Disable() here. DeleteChannel() should call
      // StopPlayout() while deleting the channel.  We should fix the bug
      // inside WebRTC and remove the Disable() call bellow.  This work is
      // tracked by bug http://b/issue?id=5382855.
      PlaySound(NULL, 0, 0);
      Disable();
      if (engine_->voe_sc()->base()->DeleteChannel(webrtc_channel_)
          == -1) {
        LOG_RTCERR1(DeleteChannel, webrtc_channel_);
      }
    }
  }

  bool Init() {
    if (!engine_->voe_sc()) {
      return false;
    }
    webrtc_channel_ = engine_->CreateSoundclipVoiceChannel();
    if (webrtc_channel_ == -1) {
      LOG_RTCERR0(CreateChannel);
      return false;
    }
    return true;
  }

  bool Enable() {
    if (engine_->voe_sc()->base()->StartPlayout(webrtc_channel_) == -1) {
      LOG_RTCERR1(StartPlayout, webrtc_channel_);
      return false;
    }
    return true;
  }

  bool Disable() {
    if (engine_->voe_sc()->base()->StopPlayout(webrtc_channel_) == -1) {
      LOG_RTCERR1(StopPlayout, webrtc_channel_);
      return false;
    }
    return true;
  }

  virtual bool PlaySound(const char *buf, int len, int flags) {
    // The voe file api is not available in chrome.
    if (!engine_->voe_sc()->file()) {
      return false;
    }
    // Must stop playing the current sound (if any), because we are about to
    // modify the stream.
    if (engine_->voe_sc()->file()->StopPlayingFileLocally(webrtc_channel_)
        == -1) {
      LOG_RTCERR1(StopPlayingFileLocally, webrtc_channel_);
      return false;
    }

    if (buf) {
      stream_.reset(new WebRtcSoundclipStream(buf, len));
      stream_->set_loop((flags & SF_LOOP) != 0);
      stream_->Rewind();

      // Play it.
      if (engine_->voe_sc()->file()->StartPlayingFileLocally(
          webrtc_channel_, stream_.get()) == -1) {
        LOG_RTCERR2(StartPlayingFileLocally, webrtc_channel_, stream_.get());
        LOG(LS_ERROR) << "Unable to start soundclip";
        return false;
      }
    } else {
      stream_.reset();
    }
    return true;
  }

  int GetLastEngineError() const { return engine_->voe_sc()->error(); }

 private:
  WebRtcVoiceEngine *engine_;
  int webrtc_channel_;
  rtc::scoped_ptr<WebRtcSoundclipStream> stream_;
};

WebRtcVoiceEngine::WebRtcVoiceEngine()
    : voe_wrapper_(new VoEWrapper()),
      voe_wrapper_sc_(new VoEWrapper()),
      voe_wrapper_sc_initialized_(false),
      tracing_(new VoETraceWrapper()),
      adm_(NULL),
      adm_sc_(NULL),
      log_filter_(SeverityToFilter(kDefaultLogSeverity)),
      is_dumping_aec_(false),
      desired_local_monitor_enable_(false),
      tx_processor_ssrc_(0),
      rx_processor_ssrc_(0) {
  Construct();
}

WebRtcVoiceEngine::WebRtcVoiceEngine(VoEWrapper* voe_wrapper,
                                     VoEWrapper* voe_wrapper_sc,
                                     VoETraceWrapper* tracing)
    : voe_wrapper_(voe_wrapper),
      voe_wrapper_sc_(voe_wrapper_sc),
      voe_wrapper_sc_initialized_(false),
      tracing_(tracing),
      adm_(NULL),
      adm_sc_(NULL),
      log_filter_(SeverityToFilter(kDefaultLogSeverity)),
      is_dumping_aec_(false),
      desired_local_monitor_enable_(false),
      tx_processor_ssrc_(0),
      rx_processor_ssrc_(0) {
  Construct();
}

void WebRtcVoiceEngine::Construct() {
  SetTraceFilter(log_filter_);
  initialized_ = false;
  LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
  SetTraceOptions("");
  if (tracing_->SetTraceCallback(this) == -1) {
    LOG_RTCERR0(SetTraceCallback);
  }
  if (voe_wrapper_->base()->RegisterVoiceEngineObserver(*this) == -1) {
    LOG_RTCERR0(RegisterVoiceEngineObserver);
  }
  // Clear the default agc state.
  memset(&default_agc_config_, 0, sizeof(default_agc_config_));

  // Load our audio codec list.
  ConstructCodecs();

  // Load our RTP Header extensions.
  rtp_header_extensions_.push_back(
      RtpHeaderExtension(kRtpAudioLevelHeaderExtension,
                         kRtpAudioLevelHeaderExtensionDefaultId));
  rtp_header_extensions_.push_back(
      RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
                         kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
  options_ = GetDefaultEngineOptions();
}

static bool IsOpus(const AudioCodec& codec) {
  return (_stricmp(codec.name.c_str(), kOpusCodecName) == 0);
}

static bool IsIsac(const AudioCodec& codec) {
  return (_stricmp(codec.name.c_str(), kIsacCodecName) == 0);
}

// True if params["stereo"] == "1"
static bool IsOpusStereoEnabled(const AudioCodec& codec) {
  int value;
  return codec.GetParam(kCodecParamStereo, &value) && value == 1;
}

// Use params[kCodecParamMaxAverageBitrate] if it is defined, use codec.bitrate
// otherwise. If the value (either from params or codec.bitrate) <=0, use the
// default configuration. If the value is beyond feasible bit rate of Opus,
// clamp it. Returns the Opus bit rate for operation.
static int GetOpusBitrate(const AudioCodec& codec, int max_playback_rate) {
  int bitrate = 0;
  bool use_param = true;
  if (!codec.GetParam(kCodecParamMaxAverageBitrate, &bitrate)) {
    bitrate = codec.bitrate;
    use_param = false;
  }
  if (bitrate <= 0) {
    if (max_playback_rate <= 8000) {
      bitrate = kOpusBitrateNb;
    } else if (max_playback_rate <= 16000) {
      bitrate = kOpusBitrateWb;
    } else {
      bitrate = kOpusBitrateFb;
    }

    if (IsOpusStereoEnabled(codec)) {
      bitrate *= 2;
    }
  } else if (bitrate < kOpusMinBitrate || bitrate > kOpusMaxBitrate) {
    bitrate = (bitrate < kOpusMinBitrate) ? kOpusMinBitrate : kOpusMaxBitrate;
    std::string rate_source =
        use_param ? "Codec parameter \"maxaveragebitrate\"" :
            "Supplied Opus bitrate";
    LOG(LS_WARNING) << rate_source
                    << " is invalid and is replaced by: "
                    << bitrate;
  }
  return bitrate;
}

// Return true if params[kCodecParamUseInbandFec] == "1", false
// otherwise.
static bool IsOpusFecEnabled(const AudioCodec& codec) {
  int value;
  return codec.GetParam(kCodecParamUseInbandFec, &value) && value == 1;
}

// Returns kOpusDefaultPlaybackRate if params[kCodecParamMaxPlaybackRate] is not
// defined. Returns the value of params[kCodecParamMaxPlaybackRate] otherwise.
static int GetOpusMaxPlaybackRate(const AudioCodec& codec) {
  int value;
  if (codec.GetParam(kCodecParamMaxPlaybackRate, &value)) {
    return value;
  }
  return kOpusDefaultMaxPlaybackRate;
}

static void GetOpusConfig(const AudioCodec& codec, webrtc::CodecInst* voe_codec,
                          bool* enable_codec_fec, int* max_playback_rate) {
  *enable_codec_fec = IsOpusFecEnabled(codec);
  *max_playback_rate = GetOpusMaxPlaybackRate(codec);

  // If OPUS, change what we send according to the "stereo" codec
  // parameter, and not the "channels" parameter.  We set
  // voe_codec.channels to 2 if "stereo=1" and 1 otherwise.  If
  // the bitrate is not specified, i.e. is <= zero, we set it to the
  // appropriate default value for mono or stereo Opus.

  voe_codec->channels = IsOpusStereoEnabled(codec) ? 2 : 1;
  voe_codec->rate = GetOpusBitrate(codec, *max_playback_rate);
}

// Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC
// which says that G722 should be advertised as 8 kHz although it is a 16 kHz
// codec.
static void MaybeFixupG722(webrtc::CodecInst* voe_codec, int new_plfreq) {
  if (_stricmp(voe_codec->plname, kG722CodecName) == 0) {
    // If the ASSERT triggers, the codec definition in WebRTC VoiceEngine
    // has changed, and this special case is no longer needed.
    ASSERT(voe_codec->plfreq != new_plfreq);
    voe_codec->plfreq = new_plfreq;
  }
}

void WebRtcVoiceEngine::ConstructCodecs() {
  LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
  int ncodecs = voe_wrapper_->codec()->NumOfCodecs();
  for (int i = 0; i < ncodecs; ++i) {
    webrtc::CodecInst voe_codec;
    if (GetVoeCodec(i, &voe_codec)) {
      // Skip uncompressed formats.
      if (_stricmp(voe_codec.plname, kL16CodecName) == 0) {
        continue;
      }

      const CodecPref* pref = NULL;
      for (size_t j = 0; j < ARRAY_SIZE(kCodecPrefs); ++j) {
        if (_stricmp(kCodecPrefs[j].name, voe_codec.plname) == 0 &&
            kCodecPrefs[j].clockrate == voe_codec.plfreq &&
            kCodecPrefs[j].channels == voe_codec.channels) {
          pref = &kCodecPrefs[j];
          break;
        }
      }

      if (pref) {
        // Use the payload type that we've configured in our pref table;
        // use the offset in our pref table to determine the sort order.
        AudioCodec codec(pref->payload_type, voe_codec.plname, voe_codec.plfreq,
                         voe_codec.rate, voe_codec.channels,
                         ARRAY_SIZE(kCodecPrefs) - (pref - kCodecPrefs));
        LOG(LS_INFO) << ToString(codec);
        if (IsIsac(codec)) {
          // Indicate auto-bitrate in signaling.
          codec.bitrate = 0;
        }
        if (IsOpus(codec)) {
          // Only add fmtp parameters that differ from the spec.
          if (kPreferredMinPTime != kOpusDefaultMinPTime) {
            codec.params[kCodecParamMinPTime] =
                rtc::ToString(kPreferredMinPTime);
          }
          if (kPreferredMaxPTime != kOpusDefaultMaxPTime) {
            codec.params[kCodecParamMaxPTime] =
                rtc::ToString(kPreferredMaxPTime);
          }
          codec.SetParam(kCodecParamUseInbandFec, 1);

          // TODO(hellner): Add ptime, sprop-stereo, and stereo
          // when they can be set to values other than the default.
        }
        codecs_.push_back(codec);
      } else {
        LOG(LS_WARNING) << "Unexpected codec: " << ToString(voe_codec);
      }
    }
  }
  // Make sure they are in local preference order.
  std::sort(codecs_.begin(), codecs_.end(), &AudioCodec::Preferable);
}

bool WebRtcVoiceEngine::GetVoeCodec(int index, webrtc::CodecInst* codec) {
  if (voe_wrapper_->codec()->GetCodec(index, *codec) == -1) {
    return false;
  }
  // Change the sample rate of G722 to 8000 to match SDP.
  MaybeFixupG722(codec, 8000);
  return true;
}

WebRtcVoiceEngine::~WebRtcVoiceEngine() {
  LOG(LS_VERBOSE) << "WebRtcVoiceEngine::~WebRtcVoiceEngine";
  if (voe_wrapper_->base()->DeRegisterVoiceEngineObserver() == -1) {
    LOG_RTCERR0(DeRegisterVoiceEngineObserver);
  }
  if (adm_) {
    voe_wrapper_.reset();
    adm_->Release();
    adm_ = NULL;
  }
  if (adm_sc_) {
    voe_wrapper_sc_.reset();
    adm_sc_->Release();
    adm_sc_ = NULL;
  }

  // Test to see if the media processor was deregistered properly
  ASSERT(SignalRxMediaFrame.is_empty());
  ASSERT(SignalTxMediaFrame.is_empty());

  tracing_->SetTraceCallback(NULL);
}

bool WebRtcVoiceEngine::Init(rtc::Thread* worker_thread) {
  ASSERT(worker_thread == rtc::Thread::Current());
  LOG(LS_INFO) << "WebRtcVoiceEngine::Init";
  bool res = InitInternal();
  if (res) {
    LOG(LS_INFO) << "WebRtcVoiceEngine::Init Done!";
  } else {
    LOG(LS_ERROR) << "WebRtcVoiceEngine::Init failed";
    Terminate();
  }
  return res;
}

bool WebRtcVoiceEngine::InitInternal() {
  // Temporarily turn logging level up for the Init call
  int old_filter = log_filter_;
  int extended_filter = log_filter_ | SeverityToFilter(rtc::LS_INFO);
  SetTraceFilter(extended_filter);
  SetTraceOptions("");

  // Init WebRtc VoiceEngine.
  if (voe_wrapper_->base()->Init(adm_) == -1) {
    LOG_RTCERR0_EX(Init, voe_wrapper_->error());
    SetTraceFilter(old_filter);
    return false;
  }

  SetTraceFilter(old_filter);
  SetTraceOptions(log_options_);

  // Log the VoiceEngine version info
  char buffer[1024] = "";
  voe_wrapper_->base()->GetVersion(buffer);
  LOG(LS_INFO) << "WebRtc VoiceEngine Version:";
  LogMultiline(rtc::LS_INFO, buffer);

  // Save the default AGC configuration settings. This must happen before
  // calling SetOptions or the default will be overwritten.
  if (voe_wrapper_->processing()->GetAgcConfig(default_agc_config_) == -1) {
    LOG_RTCERR0(GetAgcConfig);
    return false;
  }

  // Set defaults for options, so that ApplyOptions applies them explicitly
  // when we clear option (channel) overrides. External clients can still
  // modify the defaults via SetOptions (on the media engine).
  if (!SetOptions(GetDefaultEngineOptions())) {
    return false;
  }

  // Print our codec list again for the call diagnostic log
  LOG(LS_INFO) << "WebRtc VoiceEngine codecs:";
  for (std::vector<AudioCodec>::const_iterator it = codecs_.begin();
      it != codecs_.end(); ++it) {
    LOG(LS_INFO) << ToString(*it);
  }

  // Disable the DTMF playout when a tone is sent.
  // PlayDtmfTone will be used if local playout is needed.
  if (voe_wrapper_->dtmf()->SetDtmfFeedbackStatus(false) == -1) {
    LOG_RTCERR1(SetDtmfFeedbackStatus, false);
  }

  initialized_ = true;
  return true;
}

bool WebRtcVoiceEngine::EnsureSoundclipEngineInit() {
  if (voe_wrapper_sc_initialized_) {
    return true;
  }
  // Note that, if initialization fails, voe_wrapper_sc_initialized_ will still
  // be false, so subsequent calls to EnsureSoundclipEngineInit will
  // probably just fail again. That's acceptable behavior.
#if defined(LINUX) && !defined(HAVE_LIBPULSE)
  voe_wrapper_sc_->hw()->SetAudioDeviceLayer(webrtc::kAudioLinuxAlsa);
#endif

  // Initialize the VoiceEngine instance that we'll use to play out sound clips.
  if (voe_wrapper_sc_->base()->Init(adm_sc_) == -1) {
    LOG_RTCERR0_EX(Init, voe_wrapper_sc_->error());
    return false;
  }

  // On Windows, tell it to use the default sound (not communication) devices.
  // First check whether there is a valid sound device for playback.
  // TODO(juberti): Clean this up when we support setting the soundclip device.
#ifdef WIN32
  // The SetPlayoutDevice may not be implemented in the case of external ADM.
  // TODO(ronghuawu): We should only check the adm_sc_ here, but current
  // PeerConnection interface never set the adm_sc_, so need to check both
  // in order to determine if the external adm is used.
  if (!adm_ && !adm_sc_) {
    int num_of_devices = 0;
    if (voe_wrapper_sc_->hw()->GetNumOfPlayoutDevices(num_of_devices) != -1 &&
        num_of_devices > 0) {
      if (voe_wrapper_sc_->hw()->SetPlayoutDevice(kDefaultSoundclipDeviceId)
          == -1) {
        LOG_RTCERR1_EX(SetPlayoutDevice, kDefaultSoundclipDeviceId,
                       voe_wrapper_sc_->error());
        return false;
      }
    } else {
      LOG(LS_WARNING) << "No valid sound playout device found.";
    }
  }
#endif
  voe_wrapper_sc_initialized_ = true;
  LOG(LS_INFO) << "Initialized WebRtc soundclip engine.";
  return true;
}

void WebRtcVoiceEngine::Terminate() {
  LOG(LS_INFO) << "WebRtcVoiceEngine::Terminate";
  initialized_ = false;

  StopAecDump();

  if (voe_wrapper_sc_) {
    voe_wrapper_sc_initialized_ = false;
    voe_wrapper_sc_->base()->Terminate();
  }
  voe_wrapper_->base()->Terminate();
  desired_local_monitor_enable_ = false;
}

int WebRtcVoiceEngine::GetCapabilities() {
  return AUDIO_SEND | AUDIO_RECV;
}

VoiceMediaChannel *WebRtcVoiceEngine::CreateChannel() {
  WebRtcVoiceMediaChannel* ch = new WebRtcVoiceMediaChannel(this);
  if (!ch->valid()) {
    delete ch;
    ch = NULL;
  }
  return ch;
}

SoundclipMedia *WebRtcVoiceEngine::CreateSoundclip() {
  if (!EnsureSoundclipEngineInit()) {
    LOG(LS_ERROR) << "Unable to create soundclip: soundclip engine failed to "
                  << "initialize.";
    return NULL;
  }
  WebRtcSoundclipMedia *soundclip = new WebRtcSoundclipMedia(this);
  if (!soundclip->Init() || !soundclip->Enable()) {
    delete soundclip;
    return NULL;
  }
  return soundclip;
}

bool WebRtcVoiceEngine::SetOptions(const AudioOptions& options) {
  if (!ApplyOptions(options)) {
    return false;
  }
  options_ = options;
  return true;
}

bool WebRtcVoiceEngine::SetOptionOverrides(const AudioOptions& overrides) {
  LOG(LS_INFO) << "Setting option overrides: " << overrides.ToString();
  if (!ApplyOptions(overrides)) {
    return false;
  }
  option_overrides_ = overrides;
  return true;
}

bool WebRtcVoiceEngine::ClearOptionOverrides() {
  LOG(LS_INFO) << "Clearing option overrides.";
  AudioOptions options = options_;
  // Only call ApplyOptions if |options_overrides_| contains overrided options.
  // ApplyOptions affects NS, AGC other options that is shared between
  // all WebRtcVoiceEngineChannels.
  if (option_overrides_ == AudioOptions()) {
    return true;
  }

  if (!ApplyOptions(options)) {
    return false;
  }
  option_overrides_ = AudioOptions();
  return true;
}

// AudioOptions defaults are set in InitInternal (for options with corresponding
// MediaEngineInterface flags) and in SetOptions(int) for flagless options.
bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
  AudioOptions options = options_in;  // The options are modified below.
  // kEcConference is AEC with high suppression.
  webrtc::EcModes ec_mode = webrtc::kEcConference;
  webrtc::AecmModes aecm_mode = webrtc::kAecmSpeakerphone;
  webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog;
  webrtc::NsModes ns_mode = webrtc::kNsHighSuppression;
  bool aecm_comfort_noise = false;
  if (options.aecm_generate_comfort_noise.Get(&aecm_comfort_noise)) {
    LOG(LS_VERBOSE) << "Comfort noise explicitly set to "
                    << aecm_comfort_noise << " (default is false).";
  }

#if defined(IOS)
  // On iOS, VPIO provides built-in EC and AGC.
  options.echo_cancellation.Set(false);
  options.auto_gain_control.Set(false);
#elif defined(ANDROID)
  ec_mode = webrtc::kEcAecm;
#endif

#if defined(IOS) || defined(ANDROID)
  // Set the AGC mode for iOS as well despite disabling it above, to avoid
  // unsupported configuration errors from webrtc.
  agc_mode = webrtc::kAgcFixedDigital;
  options.typing_detection.Set(false);
  options.experimental_agc.Set(false);
  options.experimental_aec.Set(false);
  options.experimental_ns.Set(false);
#endif

  LOG(LS_INFO) << "Applying audio options: " << options.ToString();

  webrtc::VoEAudioProcessing* voep = voe_wrapper_->processing();

  bool echo_cancellation = false;
  if (options.echo_cancellation.Get(&echo_cancellation)) {
    // Check if platform supports built-in EC. Currently only supported on
    // Android and in combination with Java based audio layer.
    // TODO(henrika): investigate possibility to support built-in EC also
    // in combination with Open SL ES audio.
    const bool built_in_aec = voe_wrapper_->hw()->BuiltInAECIsAvailable();
    if (built_in_aec) {
      // Set mode of built-in EC according to the audio options.
      voe_wrapper_->hw()->EnableBuiltInAEC(echo_cancellation);
      if (echo_cancellation) {
        // Disable internal software EC if device has its own built-in EC,
        // i.e., replace the software EC with the built-in EC.
        options.echo_cancellation.Set(false);
        echo_cancellation = false;
        LOG(LS_INFO) << "Disabling EC since built-in EC will be used instead";
      }
    }
    if (voep->SetEcStatus(echo_cancellation, ec_mode) == -1) {
      LOG_RTCERR2(SetEcStatus, echo_cancellation, ec_mode);
      return false;
    } else {
      LOG(LS_VERBOSE) << "Echo control set to " << echo_cancellation
                      << " with mode " << ec_mode;
    }
#if !defined(ANDROID)
    // TODO(ajm): Remove the error return on Android from webrtc.
    if (voep->SetEcMetricsStatus(echo_cancellation) == -1) {
      LOG_RTCERR1(SetEcMetricsStatus, echo_cancellation);
      return false;
    }
#endif
    if (ec_mode == webrtc::kEcAecm) {
      if (voep->SetAecmMode(aecm_mode, aecm_comfort_noise) != 0) {
        LOG_RTCERR2(SetAecmMode, aecm_mode, aecm_comfort_noise);
        return false;
      }
    }
  }

  bool auto_gain_control;
  if (options.auto_gain_control.Get(&auto_gain_control)) {
    if (voep->SetAgcStatus(auto_gain_control, agc_mode) == -1) {
      LOG_RTCERR2(SetAgcStatus, auto_gain_control, agc_mode);
      return false;
    } else {
      LOG(LS_VERBOSE) << "Auto gain set to " << auto_gain_control
                      << " with mode " << agc_mode;
    }
  }

  if (options.tx_agc_target_dbov.IsSet() ||
      options.tx_agc_digital_compression_gain.IsSet() ||
      options.tx_agc_limiter.IsSet()) {
    // Override default_agc_config_. Generally, an unset option means "leave
    // the VoE bits alone" in this function, so we want whatever is set to be
    // stored as the new "default". If we didn't, then setting e.g.
    // tx_agc_target_dbov would reset digital compression gain and limiter
    // settings.
    // Also, if we don't update default_agc_config_, then adjust_agc_delta
    // would be an offset from the original values, and not whatever was set
    // explicitly.
    default_agc_config_.targetLeveldBOv =
        options.tx_agc_target_dbov.GetWithDefaultIfUnset(
            default_agc_config_.targetLeveldBOv);
    default_agc_config_.digitalCompressionGaindB =
        options.tx_agc_digital_compression_gain.GetWithDefaultIfUnset(
            default_agc_config_.digitalCompressionGaindB);
    default_agc_config_.limiterEnable =
        options.tx_agc_limiter.GetWithDefaultIfUnset(
            default_agc_config_.limiterEnable);
    if (voe_wrapper_->processing()->SetAgcConfig(default_agc_config_) == -1) {
      LOG_RTCERR3(SetAgcConfig,
                  default_agc_config_.targetLeveldBOv,
                  default_agc_config_.digitalCompressionGaindB,
                  default_agc_config_.limiterEnable);
      return false;
    }
  }

  bool noise_suppression;
  if (options.noise_suppression.Get(&noise_suppression)) {
    if (voep->SetNsStatus(noise_suppression, ns_mode) == -1) {
      LOG_RTCERR2(SetNsStatus, noise_suppression, ns_mode);
      return false;
    } else {
      LOG(LS_VERBOSE) << "Noise suppression set to " << noise_suppression
                      << " with mode " << ns_mode;
    }
  }

  bool highpass_filter;
  if (options.highpass_filter.Get(&highpass_filter)) {
    LOG(LS_INFO) << "High pass filter enabled? " << highpass_filter;
    if (voep->EnableHighPassFilter(highpass_filter) == -1) {
      LOG_RTCERR1(SetHighpassFilterStatus, highpass_filter);
      return false;
    }
  }

  bool stereo_swapping;
  if (options.stereo_swapping.Get(&stereo_swapping)) {
    LOG(LS_INFO) << "Stereo swapping enabled? " << stereo_swapping;
    voep->EnableStereoChannelSwapping(stereo_swapping);
    if (voep->IsStereoChannelSwappingEnabled() != stereo_swapping) {
      LOG_RTCERR1(EnableStereoChannelSwapping, stereo_swapping);
      return false;
    }
  }

  bool typing_detection;
  if (options.typing_detection.Get(&typing_detection)) {
    LOG(LS_INFO) << "Typing detection is enabled? " << typing_detection;
    if (voep->SetTypingDetectionStatus(typing_detection) == -1) {
      // In case of error, log the info and continue
      LOG_RTCERR1(SetTypingDetectionStatus, typing_detection);
    }
  }

  int adjust_agc_delta;
  if (options.adjust_agc_delta.Get(&adjust_agc_delta)) {
    LOG(LS_INFO) << "Adjust agc delta is " << adjust_agc_delta;
    if (!AdjustAgcLevel(adjust_agc_delta)) {
      return false;
    }
  }

  bool aec_dump;
  if (options.aec_dump.Get(&aec_dump)) {
    LOG(LS_INFO) << "Aec dump is enabled? " << aec_dump;
    if (aec_dump)
      StartAecDump(kAecDumpByAudioOptionFilename);
    else
      StopAecDump();
  }

  webrtc::Config config;

  experimental_aec_.SetFrom(options.experimental_aec);
  bool experimental_aec;
  if (experimental_aec_.Get(&experimental_aec)) {
    LOG(LS_INFO) << "Experimental aec is enabled? " << experimental_aec;
    config.Set<webrtc::DelayCorrection>(
        new webrtc::DelayCorrection(experimental_aec));
  }

  experimental_ns_.SetFrom(options.experimental_ns);
  bool experimental_ns;
  if (experimental_ns_.Get(&experimental_ns)) {
    LOG(LS_INFO) << "Experimental ns is enabled? " << experimental_ns;
    config.Set<webrtc::ExperimentalNs>(
        new webrtc::ExperimentalNs(experimental_ns));
  }

  // We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine
  // returns NULL on audio_processing().
  webrtc::AudioProcessing* audioproc = voe_wrapper_->base()->audio_processing();
  if (audioproc) {
    audioproc->SetExtraOptions(config);
  }

  uint32 recording_sample_rate;
  if (options.recording_sample_rate.Get(&recording_sample_rate)) {
    LOG(LS_INFO) << "Recording sample rate is " << recording_sample_rate;
    if (voe_wrapper_->hw()->SetRecordingSampleRate(recording_sample_rate)) {
      LOG_RTCERR1(SetRecordingSampleRate, recording_sample_rate);
    }
  }

  uint32 playout_sample_rate;
  if (options.playout_sample_rate.Get(&playout_sample_rate)) {
    LOG(LS_INFO) << "Playout sample rate is " << playout_sample_rate;
    if (voe_wrapper_->hw()->SetPlayoutSampleRate(playout_sample_rate)) {
      LOG_RTCERR1(SetPlayoutSampleRate, playout_sample_rate);
    }
  }

  return true;
}

bool WebRtcVoiceEngine::SetDelayOffset(int offset) {
  voe_wrapper_->processing()->SetDelayOffsetMs(offset);
  if (voe_wrapper_->processing()->DelayOffsetMs() != offset) {
    LOG_RTCERR1(SetDelayOffsetMs, offset);
    return false;
  }

  return true;
}

struct ResumeEntry {
  ResumeEntry(WebRtcVoiceMediaChannel *c, bool p, SendFlags s)
      : channel(c),
        playout(p),
        send(s) {
  }

  WebRtcVoiceMediaChannel *channel;
  bool playout;
  SendFlags send;
};

// TODO(juberti): Refactor this so that the core logic can be used to set the
// soundclip device. At that time, reinstate the soundclip pause/resume code.
bool WebRtcVoiceEngine::SetDevices(const Device* in_device,
                                   const Device* out_device) {
#if !defined(IOS)
  int in_id = in_device ? rtc::FromString<int>(in_device->id) :
      kDefaultAudioDeviceId;
  int out_id = out_device ? rtc::FromString<int>(out_device->id) :
      kDefaultAudioDeviceId;
  // The device manager uses -1 as the default device, which was the case for
  // VoE 3.5. VoE 4.0, however, uses 0 as the default in Linux and Mac.
#ifndef WIN32
  if (-1 == in_id) {
    in_id = kDefaultAudioDeviceId;
  }
  if (-1 == out_id) {
    out_id = kDefaultAudioDeviceId;
  }
#endif

  std::string in_name = (in_id != kDefaultAudioDeviceId) ?
      in_device->name : "Default device";
  std::string out_name = (out_id != kDefaultAudioDeviceId) ?
      out_device->name : "Default device";
  LOG(LS_INFO) << "Setting microphone to (id=" << in_id << ", name=" << in_name
            << ") and speaker to (id=" << out_id << ", name=" << out_name
            << ")";

  // If we're running the local monitor, we need to stop it first.
  bool ret = true;
  if (!PauseLocalMonitor()) {
    LOG(LS_WARNING) << "Failed to pause local monitor";
    ret = false;
  }

  // Must also pause all audio playback and capture.
  for (ChannelList::const_iterator i = channels_.begin();
       i != channels_.end(); ++i) {
    WebRtcVoiceMediaChannel *channel = *i;
    if (!channel->PausePlayout()) {
      LOG(LS_WARNING) << "Failed to pause playout";
      ret = false;
    }
    if (!channel->PauseSend()) {
      LOG(LS_WARNING) << "Failed to pause send";
      ret = false;
    }
  }

  // Find the recording device id in VoiceEngine and set recording device.
  if (!FindWebRtcAudioDeviceId(true, in_name, in_id, &in_id)) {
    ret = false;
  }
  if (ret) {
    if (voe_wrapper_->hw()->SetRecordingDevice(in_id) == -1) {
      LOG_RTCERR2(SetRecordingDevice, in_name, in_id);
      ret = false;
    }
    webrtc::AudioProcessing* ap = voe()->base()->audio_processing();
    if (ap)
      ap->Initialize();
  }

  // Find the playout device id in VoiceEngine and set playout device.
  if (!FindWebRtcAudioDeviceId(false, out_name, out_id, &out_id)) {
    LOG(LS_WARNING) << "Failed to find VoiceEngine device id for " << out_name;
    ret = false;
  }
  if (ret) {
    if (voe_wrapper_->hw()->SetPlayoutDevice(out_id) == -1) {
      LOG_RTCERR2(SetPlayoutDevice, out_name, out_id);
      ret = false;
    }
  }

  // Resume all audio playback and capture.
  for (ChannelList::const_iterator i = channels_.begin();
       i != channels_.end(); ++i) {
    WebRtcVoiceMediaChannel *channel = *i;
    if (!channel->ResumePlayout()) {
      LOG(LS_WARNING) << "Failed to resume playout";
      ret = false;
    }
    if (!channel->ResumeSend()) {
      LOG(LS_WARNING) << "Failed to resume send";
      ret = false;
    }
  }

  // Resume local monitor.
  if (!ResumeLocalMonitor()) {
    LOG(LS_WARNING) << "Failed to resume local monitor";
    ret = false;
  }

  if (ret) {
    LOG(LS_INFO) << "Set microphone to (id=" << in_id <<" name=" << in_name
                 << ") and speaker to (id="<< out_id << " name=" << out_name
                 << ")";
  }

  return ret;
#else
  return true;
#endif  // !IOS
}

bool WebRtcVoiceEngine::FindWebRtcAudioDeviceId(
  bool is_input, const std::string& dev_name, int dev_id, int* rtc_id) {
  // In Linux, VoiceEngine uses the same device dev_id as the device manager.
#if defined(LINUX) || defined(ANDROID)
  *rtc_id = dev_id;
  return true;
#else
  // In Windows and Mac, we need to find the VoiceEngine device id by name
  // unless the input dev_id is the default device id.
  if (kDefaultAudioDeviceId == dev_id) {
    *rtc_id = dev_id;
    return true;
  }

  // Get the number of VoiceEngine audio devices.
  int count = 0;
  if (is_input) {
    if (-1 == voe_wrapper_->hw()->GetNumOfRecordingDevices(count)) {
      LOG_RTCERR0(GetNumOfRecordingDevices);
      return false;
    }
  } else {
    if (-1 == voe_wrapper_->hw()->GetNumOfPlayoutDevices(count)) {
      LOG_RTCERR0(GetNumOfPlayoutDevices);
      return false;
    }
  }

  for (int i = 0; i < count; ++i) {
    char name[128];
    char guid[128];
    if (is_input) {
      voe_wrapper_->hw()->GetRecordingDeviceName(i, name, guid);
      LOG(LS_VERBOSE) << "VoiceEngine microphone " << i << ": " << name;
    } else {
      voe_wrapper_->hw()->GetPlayoutDeviceName(i, name, guid);
      LOG(LS_VERBOSE) << "VoiceEngine speaker " << i << ": " << name;
    }

    std::string webrtc_name(name);
    if (dev_name.compare(0, webrtc_name.size(), webrtc_name) == 0) {
      *rtc_id = i;
      return true;
    }
  }
  LOG(LS_WARNING) << "VoiceEngine cannot find device: " << dev_name;
  return false;
#endif
}

bool WebRtcVoiceEngine::GetOutputVolume(int* level) {
  unsigned int ulevel;
  if (voe_wrapper_->volume()->GetSpeakerVolume(ulevel) == -1) {
    LOG_RTCERR1(GetSpeakerVolume, level);
    return false;
  }
  *level = ulevel;
  return true;
}

bool WebRtcVoiceEngine::SetOutputVolume(int level) {
  ASSERT(level >= 0 && level <= 255);
  if (voe_wrapper_->volume()->SetSpeakerVolume(level) == -1) {
    LOG_RTCERR1(SetSpeakerVolume, level);
    return false;
  }
  return true;
}

int WebRtcVoiceEngine::GetInputLevel() {
  unsigned int ulevel;
  return (voe_wrapper_->volume()->GetSpeechInputLevel(ulevel) != -1) ?
      static_cast<int>(ulevel) : -1;
}

bool WebRtcVoiceEngine::SetLocalMonitor(bool enable) {
  desired_local_monitor_enable_ = enable;
  return ChangeLocalMonitor(desired_local_monitor_enable_);
}

bool WebRtcVoiceEngine::ChangeLocalMonitor(bool enable) {
  // The voe file api is not available in chrome.
  if (!voe_wrapper_->file()) {
    return false;
  }
  if (enable && !monitor_) {
    monitor_.reset(new WebRtcMonitorStream);
    if (voe_wrapper_->file()->StartRecordingMicrophone(monitor_.get()) == -1) {
      LOG_RTCERR1(StartRecordingMicrophone, monitor_.get());
      // Must call Stop() because there are some cases where Start will report
      // failure but still change the state, and if we leave VE in the on state
      // then it could crash later when trying to invoke methods on our monitor.
      voe_wrapper_->file()->StopRecordingMicrophone();
      monitor_.reset();
      return false;
    }
  } else if (!enable && monitor_) {
    voe_wrapper_->file()->StopRecordingMicrophone();
    monitor_.reset();
  }
  return true;
}

bool WebRtcVoiceEngine::PauseLocalMonitor() {
  return ChangeLocalMonitor(false);
}

bool WebRtcVoiceEngine::ResumeLocalMonitor() {
  return ChangeLocalMonitor(desired_local_monitor_enable_);
}

const std::vector<AudioCodec>& WebRtcVoiceEngine::codecs() {
  return codecs_;
}

bool WebRtcVoiceEngine::FindCodec(const AudioCodec& in) {
  return FindWebRtcCodec(in, NULL);
}

// Get the VoiceEngine codec that matches |in|, with the supplied settings.
bool WebRtcVoiceEngine::FindWebRtcCodec(const AudioCodec& in,
                                        webrtc::CodecInst* out) {
  int ncodecs = voe_wrapper_->codec()->NumOfCodecs();
  for (int i = 0; i < ncodecs; ++i) {
    webrtc::CodecInst voe_codec;
    if (GetVoeCodec(i, &voe_codec)) {
      AudioCodec codec(voe_codec.pltype, voe_codec.plname, voe_codec.plfreq,
                       voe_codec.rate, voe_codec.channels, 0);
      bool multi_rate = IsCodecMultiRate(voe_codec);
      // Allow arbitrary rates for ISAC to be specified.
      if (multi_rate) {
        // Set codec.bitrate to 0 so the check for codec.Matches() passes.
        codec.bitrate = 0;
      }
      if (codec.Matches(in)) {
        if (out) {
          // Fixup the payload type.
          voe_codec.pltype = in.id;

          // Set bitrate if specified.
          if (multi_rate && in.bitrate != 0) {
            voe_codec.rate = in.bitrate;
          }

          // Reset G722 sample rate to 16000 to match WebRTC.
          MaybeFixupG722(&voe_codec, 16000);

          // Apply codec-specific settings.
          if (IsIsac(codec)) {
            // If ISAC and an explicit bitrate is not specified,
            // enable auto bitrate adjustment.
            voe_codec.rate = (in.bitrate > 0) ? in.bitrate : -1;
          }
          *out = voe_codec;
        }
        return true;
      }
    }
  }
  return false;
}
const std::vector<RtpHeaderExtension>&
WebRtcVoiceEngine::rtp_header_extensions() const {
  return rtp_header_extensions_;
}

void WebRtcVoiceEngine::SetLogging(int min_sev, const char* filter) {
  // if min_sev == -1, we keep the current log level.
  if (min_sev >= 0) {
    SetTraceFilter(SeverityToFilter(min_sev));
  }
  log_options_ = filter;
  SetTraceOptions(initialized_ ? log_options_ : "");
}

int WebRtcVoiceEngine::GetLastEngineError() {
  return voe_wrapper_->error();
}

void WebRtcVoiceEngine::SetTraceFilter(int filter) {
  log_filter_ = filter;
  tracing_->SetTraceFilter(filter);
}

// We suppport three different logging settings for VoiceEngine:
// 1. Observer callback that goes into talk diagnostic logfile.
//    Use --logfile and --loglevel
//
// 2. Encrypted VoiceEngine log for debugging VoiceEngine.
//    Use --voice_loglevel --voice_logfilter "tracefile file_name"
//
// 3. EC log and dump for debugging QualityEngine.
//    Use --voice_loglevel --voice_logfilter "recordEC file_name"
//
// For more details see: "https://sites.google.com/a/google.com/wavelet/Home/
//    Magic-Flute--RTC-Engine-/Magic-Flute-Command-Line-Parameters"
void WebRtcVoiceEngine::SetTraceOptions(const std::string& options) {
  // Set encrypted trace file.
  std::vector<std::string> opts;
  rtc::tokenize(options, ' ', '"', '"', &opts);
  std::vector<std::string>::iterator tracefile =
      std::find(opts.begin(), opts.end(), "tracefile");
  if (tracefile != opts.end() && ++tracefile != opts.end()) {
    // Write encrypted debug output (at same loglevel) to file
    // EncryptedTraceFile no longer supported.
    if (tracing_->SetTraceFile(tracefile->c_str()) == -1) {
      LOG_RTCERR1(SetTraceFile, *tracefile);
    }
  }

  // Allow trace options to override the trace filter. We default
  // it to log_filter_ (as a translation of libjingle log levels)
  // elsewhere, but this allows clients to explicitly set webrtc
  // log levels.
  std::vector<std::string>::iterator tracefilter =
      std::find(opts.begin(), opts.end(), "tracefilter");
  if (tracefilter != opts.end() && ++tracefilter != opts.end()) {
    if (!tracing_->SetTraceFilter(rtc::FromString<int>(*tracefilter))) {
      LOG_RTCERR1(SetTraceFilter, *tracefilter);
    }
  }

  // Set AEC dump file
  std::vector<std::string>::iterator recordEC =
      std::find(opts.begin(), opts.end(), "recordEC");
  if (recordEC != opts.end()) {
    ++recordEC;
    if (recordEC != opts.end())
      StartAecDump(recordEC->c_str());
    else
      StopAecDump();
  }
}

// Ignore spammy trace messages, mostly from the stats API when we haven't
// gotten RTCP info yet from the remote side.
bool WebRtcVoiceEngine::ShouldIgnoreTrace(const std::string& trace) {
  static const char* kTracesToIgnore[] = {
    "\tfailed to GetReportBlockInformation",
    "GetRecCodec() failed to get received codec",
    "GetReceivedRtcpStatistics: Could not get received RTP statistics",
    "GetRemoteRTCPData() failed to measure statistics due to lack of received RTP and/or RTCP packets",  // NOLINT
    "GetRemoteRTCPData() failed to retrieve sender info for remote side",
    "GetRTPStatistics() failed to measure RTT since no RTP packets have been received yet",  // NOLINT
    "GetRTPStatistics() failed to read RTP statistics from the RTP/RTCP module",
    "GetRTPStatistics() failed to retrieve RTT from the RTP/RTCP module",
    "SenderInfoReceived No received SR",
    "StatisticsRTP() no statistics available",
    "TransmitMixer::TypingDetection() VE_TYPING_NOISE_WARNING message has been posted",  // NOLINT
    "TransmitMixer::TypingDetection() pending noise-saturation warning exists",  // NOLINT
    "GetRecPayloadType() failed to retrieve RX payload type (error=10026)", // NOLINT
    "StopPlayingFileAsMicrophone() isnot playing (error=8088)",
    NULL
  };
  for (const char* const* p = kTracesToIgnore; *p; ++p) {
    if (trace.find(*p) != std::string::npos) {
      return true;
    }
  }
  return false;
}

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

  // 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: " << msg;
    }
  }
}

void WebRtcVoiceEngine::CallbackOnError(int channel_num, int err_code) {
  rtc::CritScope lock(&channels_cs_);
  WebRtcVoiceMediaChannel* channel = NULL;
  uint32 ssrc = 0;
  LOG(LS_WARNING) << "VoiceEngine error " << err_code << " reported on channel "
                  << channel_num << ".";
  if (FindChannelAndSsrc(channel_num, &channel, &ssrc)) {
    ASSERT(channel != NULL);
    channel->OnError(ssrc, err_code);
  } else {
    LOG(LS_ERROR) << "VoiceEngine channel " << channel_num
                  << " could not be found in channel list when error reported.";
  }
}

bool WebRtcVoiceEngine::FindChannelAndSsrc(
    int channel_num, WebRtcVoiceMediaChannel** channel, uint32* ssrc) const {
  ASSERT(channel != NULL && ssrc != NULL);

  *channel = NULL;
  *ssrc = 0;
  // Find corresponding channel and ssrc
  for (ChannelList::const_iterator it = channels_.begin();
      it != channels_.end(); ++it) {
    ASSERT(*it != NULL);
    if ((*it)->FindSsrc(channel_num, ssrc)) {
      *channel = *it;
      return true;
    }
  }

  return false;
}

// This method will search through the WebRtcVoiceMediaChannels and
// obtain the voice engine's channel number.
bool WebRtcVoiceEngine::FindChannelNumFromSsrc(
    uint32 ssrc, MediaProcessorDirection direction, int* channel_num) {
  ASSERT(channel_num != NULL);
  ASSERT(direction == MPD_RX || direction == MPD_TX);

  *channel_num = -1;
  // Find corresponding channel for ssrc.
  for (ChannelList::const_iterator it = channels_.begin();
      it != channels_.end(); ++it) {
    ASSERT(*it != NULL);
    if (direction & MPD_RX) {
      *channel_num = (*it)->GetReceiveChannelNum(ssrc);
    }
    if (*channel_num == -1 && (direction & MPD_TX)) {
      *channel_num = (*it)->GetSendChannelNum(ssrc);
    }
    if (*channel_num != -1) {
      return true;
    }
  }
  LOG(LS_WARNING) << "FindChannelFromSsrc. No Channel Found for Ssrc: " << ssrc;
  return false;
}

void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel *channel) {
  rtc::CritScope lock(&channels_cs_);
  channels_.push_back(channel);
}

void WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel *channel) {
  rtc::CritScope lock(&channels_cs_);
  ChannelList::iterator i = std::find(channels_.begin(),
                                      channels_.end(),
                                      channel);
  if (i != channels_.end()) {
    channels_.erase(i);
  }
}

void WebRtcVoiceEngine::RegisterSoundclip(WebRtcSoundclipMedia *soundclip) {
  soundclips_.push_back(soundclip);
}

void WebRtcVoiceEngine::UnregisterSoundclip(WebRtcSoundclipMedia *soundclip) {
  SoundclipList::iterator i = std::find(soundclips_.begin(),
                                        soundclips_.end(),
                                        soundclip);
  if (i != soundclips_.end()) {
    soundclips_.erase(i);
  }
}

// Adjusts the default AGC target level by the specified delta.
// NB: If we start messing with other config fields, we'll want
// to save the current webrtc::AgcConfig as well.
bool WebRtcVoiceEngine::AdjustAgcLevel(int delta) {
  webrtc::AgcConfig config = default_agc_config_;
  config.targetLeveldBOv -= delta;

  LOG(LS_INFO) << "Adjusting AGC level from default -"
               << default_agc_config_.targetLeveldBOv << "dB to -"
               << config.targetLeveldBOv << "dB";

  if (voe_wrapper_->processing()->SetAgcConfig(config) == -1) {
    LOG_RTCERR1(SetAgcConfig, config.targetLeveldBOv);
    return false;
  }
  return true;
}

bool WebRtcVoiceEngine::SetAudioDeviceModule(webrtc::AudioDeviceModule* adm,
    webrtc::AudioDeviceModule* adm_sc) {
  if (initialized_) {
    LOG(LS_WARNING) << "SetAudioDeviceModule can not be called after Init.";
    return false;
  }
  if (adm_) {
    adm_->Release();
    adm_ = NULL;
  }
  if (adm) {
    adm_ = adm;
    adm_->AddRef();
  }

  if (adm_sc_) {
    adm_sc_->Release();
    adm_sc_ = NULL;
  }
  if (adm_sc) {
    adm_sc_ = adm_sc;
    adm_sc_->AddRef();
  }
  return true;
}

bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file) {
  FILE* aec_dump_file_stream = rtc::FdopenPlatformFileForWriting(file);
  if (!aec_dump_file_stream) {
    LOG(LS_ERROR) << "Could not open AEC dump file stream.";
    if (!rtc::ClosePlatformFile(file))
      LOG(LS_WARNING) << "Could not close file.";
    return false;
  }
  StopAecDump();
  if (voe_wrapper_->processing()->StartDebugRecording(aec_dump_file_stream) !=
      webrtc::AudioProcessing::kNoError) {
    LOG_RTCERR0(StartDebugRecording);
    fclose(aec_dump_file_stream);
    return false;
  }
  is_dumping_aec_ = true;
  return true;
}

bool WebRtcVoiceEngine::RegisterProcessor(
    uint32 ssrc,
    VoiceProcessor* voice_processor,
    MediaProcessorDirection direction) {
  bool register_with_webrtc = false;
  int channel_id = -1;
  bool success = false;
  uint32* processor_ssrc = NULL;
  bool found_channel = FindChannelNumFromSsrc(ssrc, direction, &channel_id);
  if (voice_processor == NULL || !found_channel) {
    LOG(LS_WARNING) << "Media Processing Registration Failed. ssrc: " << ssrc
        << " foundChannel: " << found_channel;
    return false;
  }

  webrtc::ProcessingTypes processing_type;
  {
    rtc::CritScope cs(&signal_media_critical_);
    if (direction == MPD_RX) {
      processing_type = webrtc::kPlaybackAllChannelsMixed;
      if (SignalRxMediaFrame.is_empty()) {
        register_with_webrtc = true;
        processor_ssrc = &rx_processor_ssrc_;
      }
      SignalRxMediaFrame.connect(voice_processor,
                                 &VoiceProcessor::OnFrame);
    } else {
      processing_type = webrtc::kRecordingPerChannel;
      if (SignalTxMediaFrame.is_empty()) {
        register_with_webrtc = true;
        processor_ssrc = &tx_processor_ssrc_;
      }
      SignalTxMediaFrame.connect(voice_processor,
                                 &VoiceProcessor::OnFrame);
    }
  }
  if (register_with_webrtc) {
    // TODO(janahan): when registering consider instantiating a
    // a VoeMediaProcess object and not make the engine extend the interface.
    if (voe()->media() && voe()->media()->
        RegisterExternalMediaProcessing(channel_id,
                                        processing_type,
                                        *this) != -1) {
      LOG(LS_INFO) << "Media Processing Registration Succeeded. channel:"
                   << channel_id;
      *processor_ssrc = ssrc;
      success = true;
    } else {
      LOG_RTCERR2(RegisterExternalMediaProcessing,
                  channel_id,
                  processing_type);
      success = false;
    }
  } else {
    // If we don't have to register with the engine, we just needed to
    // connect a new processor, set success to true;
    success = true;
  }
  return success;
}

bool WebRtcVoiceEngine::UnregisterProcessorChannel(
    MediaProcessorDirection channel_direction,
    uint32 ssrc,
    VoiceProcessor* voice_processor,
    MediaProcessorDirection processor_direction) {
  bool success = true;
  FrameSignal* signal;
  webrtc::ProcessingTypes processing_type;
  uint32* processor_ssrc = NULL;
  if (channel_direction == MPD_RX) {
    signal = &SignalRxMediaFrame;
    processing_type = webrtc::kPlaybackAllChannelsMixed;
    processor_ssrc = &rx_processor_ssrc_;
  } else {
    signal = &SignalTxMediaFrame;
    processing_type = webrtc::kRecordingPerChannel;
    processor_ssrc = &tx_processor_ssrc_;
  }

  int deregister_id = -1;
  {
    rtc::CritScope cs(&signal_media_critical_);
    if ((processor_direction & channel_direction) != 0 && !signal->is_empty()) {
      signal->disconnect(voice_processor);
      int channel_id = -1;
      bool found_channel = FindChannelNumFromSsrc(ssrc,
                                                  channel_direction,
                                                  &channel_id);
      if (signal->is_empty() && found_channel) {
        deregister_id = channel_id;
      }
    }
  }
  if (deregister_id != -1) {
    if (voe()->media() &&
        voe()->media()->DeRegisterExternalMediaProcessing(deregister_id,
        processing_type) != -1) {
      *processor_ssrc = 0;
      LOG(LS_INFO) << "Media Processing DeRegistration Succeeded. channel:"
                   << deregister_id;
    } else {
      LOG_RTCERR2(DeRegisterExternalMediaProcessing,
                  deregister_id,
                  processing_type);
      success = false;
    }
  }
  return success;
}

bool WebRtcVoiceEngine::UnregisterProcessor(
    uint32 ssrc,
    VoiceProcessor* voice_processor,
    MediaProcessorDirection direction) {
  bool success = true;
  if (voice_processor == NULL) {
    LOG(LS_WARNING) << "Media Processing Deregistration Failed. ssrc: "
                    << ssrc;
    return false;
  }
  if (!UnregisterProcessorChannel(MPD_RX, ssrc, voice_processor, direction)) {
    success = false;
  }
  if (!UnregisterProcessorChannel(MPD_TX, ssrc, voice_processor, direction)) {
    success = false;
  }
  return success;
}

// Implementing method from WebRtc VoEMediaProcess interface
// Do not lock mux_channel_cs_ in this callback.
void WebRtcVoiceEngine::Process(int channel,
                                webrtc::ProcessingTypes type,
                                int16_t audio10ms[],
                                int length,
                                int sampling_freq,
                                bool is_stereo) {
    rtc::CritScope cs(&signal_media_critical_);
    AudioFrame frame(audio10ms, length, sampling_freq, is_stereo);
    if (type == webrtc::kPlaybackAllChannelsMixed) {
      SignalRxMediaFrame(rx_processor_ssrc_, MPD_RX, &frame);
    } else if (type == webrtc::kRecordingPerChannel) {
      SignalTxMediaFrame(tx_processor_ssrc_, MPD_TX, &frame);
    } else {
      LOG(LS_WARNING) << "Media Processing invoked unexpectedly."
                      << " channel: " << channel << " type: " << type
                      << " tx_ssrc: " << tx_processor_ssrc_
                      << " rx_ssrc: " << rx_processor_ssrc_;
    }
}

void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
  if (!is_dumping_aec_) {
    // Start dumping AEC when we are not dumping.
    if (voe_wrapper_->processing()->StartDebugRecording(
        filename.c_str()) != webrtc::AudioProcessing::kNoError) {
      LOG_RTCERR1(StartDebugRecording, filename.c_str());
    } else {
      is_dumping_aec_ = true;
    }
  }
}

void WebRtcVoiceEngine::StopAecDump() {
  if (is_dumping_aec_) {
    // Stop dumping AEC when we are dumping.
    if (voe_wrapper_->processing()->StopDebugRecording() !=
        webrtc::AudioProcessing::kNoError) {
      LOG_RTCERR0(StopDebugRecording);
    }
    is_dumping_aec_ = false;
  }
}

int WebRtcVoiceEngine::CreateVoiceChannel(VoEWrapper* voice_engine_wrapper) {
  return voice_engine_wrapper->base()->CreateChannel(voe_config_);
}

int WebRtcVoiceEngine::CreateMediaVoiceChannel() {
  return CreateVoiceChannel(voe_wrapper_.get());
}

int WebRtcVoiceEngine::CreateSoundclipVoiceChannel() {
  return CreateVoiceChannel(voe_wrapper_sc_.get());
}

class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer
    : public AudioRenderer::Sink {
 public:
  WebRtcVoiceChannelRenderer(int ch,
                             webrtc::AudioTransport* voe_audio_transport)
      : channel_(ch),
        voe_audio_transport_(voe_audio_transport),
        renderer_(NULL) {
  }
  virtual ~WebRtcVoiceChannelRenderer() {
    Stop();
  }

  // Starts the rendering by setting a sink to the renderer to get data
  // callback.
  // This method is called on the libjingle worker thread.
  // TODO(xians): Make sure Start() is called only once.
  void Start(AudioRenderer* renderer) {
    rtc::CritScope lock(&lock_);
    ASSERT(renderer != NULL);
    if (renderer_ != NULL) {
      ASSERT(renderer_ == renderer);
      return;
    }

    // TODO(xians): Remove AddChannel() call after Chrome turns on APM
    // in getUserMedia by default.
    renderer->AddChannel(channel_);
    renderer->SetSink(this);
    renderer_ = renderer;
  }

  // Stops rendering by setting the sink of the renderer to NULL. No data
  // callback will be received after this method.
  // This method is called on the libjingle worker thread.
  void Stop() {
    rtc::CritScope lock(&lock_);
    if (renderer_ == NULL)
      return;

    renderer_->RemoveChannel(channel_);
    renderer_->SetSink(NULL);
    renderer_ = NULL;
  }

  // AudioRenderer::Sink implementation.
  // This method is called on the audio thread.
  void OnData(const void* audio_data,
              int bits_per_sample,
              int sample_rate,
              int number_of_channels,
              int number_of_frames) override {
    voe_audio_transport_->OnData(channel_,
                                 audio_data,
                                 bits_per_sample,
                                 sample_rate,
                                 number_of_channels,
                                 number_of_frames);
  }

  // Callback from the |renderer_| when it is going away. In case Start() has
  // never been called, this callback won't be triggered.
  void OnClose() override {
    rtc::CritScope lock(&lock_);
    // Set |renderer_| to NULL to make sure no more callback will get into
    // the renderer.
    renderer_ = NULL;
  }

  // Accessor to the VoE channel ID.
  int channel() const { return channel_; }

 private:
  const int channel_;
  webrtc::AudioTransport* const voe_audio_transport_;

  // Raw pointer to AudioRenderer owned by LocalAudioTrackHandler.
  // PeerConnection will make sure invalidating the pointer before the object
  // goes away.
  AudioRenderer* renderer_;

  // Protects |renderer_| in Start(), Stop() and OnClose().
  rtc::CriticalSection lock_;
};

// WebRtcVoiceMediaChannel
WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine *engine)
    : WebRtcMediaChannel<VoiceMediaChannel, WebRtcVoiceEngine>(
          engine,
          engine->CreateMediaVoiceChannel()),
      send_bitrate_setting_(false),
      send_bitrate_bps_(0),
      options_(),
      dtmf_allowed_(false),
      desired_playout_(false),
      nack_enabled_(false),
      playout_(false),
      typing_noise_detected_(false),
      desired_send_(SEND_NOTHING),
      send_(SEND_NOTHING),
      shared_bwe_vie_(NULL),
      shared_bwe_vie_channel_(-1),
      default_receive_ssrc_(0) {
  engine->RegisterChannel(this);
  LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel "
                  << voe_channel();

  ConfigureSendChannel(voe_channel());
}

WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
  LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel "
                  << voe_channel();
  SetupSharedBandwidthEstimation(NULL, -1);

  // Remove any remaining send streams, the default channel will be deleted
  // later.
  while (!send_channels_.empty())
    RemoveSendStream(send_channels_.begin()->first);

  // Unregister ourselves from the engine.
  engine()->UnregisterChannel(this);
  // Remove any remaining streams.
  while (!receive_channels_.empty()) {
    RemoveRecvStream(receive_channels_.begin()->first);
  }

  // Delete the default channel.
  DeleteChannel(voe_channel());
}

bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
  LOG(LS_INFO) << "Setting voice channel options: "
               << options.ToString();

  // Check if DSCP value is changed from previous.
  bool dscp_option_changed = (options_.dscp != options.dscp);

  // TODO(xians): Add support to set different options for different send
  // streams after we support multiple APMs.

  // We retain all of the existing options, and apply the given ones
  // on top.  This means there is no way to "clear" options such that
  // they go back to the engine default.
  options_.SetAll(options);

  if (send_ != SEND_NOTHING) {
    if (!engine()->SetOptionOverrides(options_)) {
      LOG(LS_WARNING) <<
          "Failed to engine SetOptionOverrides during channel SetOptions.";
      return false;
    }
  } else {
    // Will be interpreted when appropriate.
  }

  // Receiver-side auto gain control happens per channel, so set it here from
  // options. Note that, like conference mode, setting it on the engine won't
  // have the desired effect, since voice channels don't inherit options from
  // the media engine when those options are applied per-channel.
  bool rx_auto_gain_control;
  if (options.rx_auto_gain_control.Get(&rx_auto_gain_control)) {
    if (engine()->voe()->processing()->SetRxAgcStatus(
            voe_channel(), rx_auto_gain_control,
            webrtc::kAgcFixedDigital) == -1) {
      LOG_RTCERR1(SetRxAgcStatus, rx_auto_gain_control);
      return false;
    } else {
      LOG(LS_VERBOSE) << "Rx auto gain set to " << rx_auto_gain_control
                      << " with mode " << webrtc::kAgcFixedDigital;
    }
  }
  if (options.rx_agc_target_dbov.IsSet() ||
      options.rx_agc_digital_compression_gain.IsSet() ||
      options.rx_agc_limiter.IsSet()) {
    webrtc::AgcConfig config;
    // If only some of the options are being overridden, get the current
    // settings for the channel and bail if they aren't available.
    if (!options.rx_agc_target_dbov.IsSet() ||
        !options.rx_agc_digital_compression_gain.IsSet() ||
        !options.rx_agc_limiter.IsSet()) {
      if (engine()->voe()->processing()->GetRxAgcConfig(
              voe_channel(), config) != 0) {
        LOG(LS_ERROR) << "Failed to get default rx agc configuration for "
                      << "channel " << voe_channel() << ". Since not all rx "
                      << "agc options are specified, unable to safely set rx "
                      << "agc options.";
        return false;
      }
    }
    config.targetLeveldBOv =
        options.rx_agc_target_dbov.GetWithDefaultIfUnset(
            config.targetLeveldBOv);
    config.digitalCompressionGaindB =
        options.rx_agc_digital_compression_gain.GetWithDefaultIfUnset(
            config.digitalCompressionGaindB);
    config.limiterEnable = options.rx_agc_limiter.GetWithDefaultIfUnset(
        config.limiterEnable);
    if (engine()->voe()->processing()->SetRxAgcConfig(
            voe_channel(), config) == -1) {
      LOG_RTCERR4(SetRxAgcConfig, voe_channel(), config.targetLeveldBOv,
                  config.digitalCompressionGaindB, config.limiterEnable);
      return false;
    }
  }
  if (dscp_option_changed) {
    rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT;
    if (options_.dscp.GetWithDefaultIfUnset(false))
      dscp = kAudioDscpValue;
    if (MediaChannel::SetDscp(dscp) != 0) {
      LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel";
    }
  }

  // Force update of Video Engine BWE forwarding to reflect experiment setting.
  if (!SetupSharedBandwidthEstimation(shared_bwe_vie_,
                                      shared_bwe_vie_channel_)) {
    return false;
  }

  LOG(LS_INFO) << "Set voice channel options.  Current options: "
               << options_.ToString();
  return true;
}

bool WebRtcVoiceMediaChannel::SetRecvCodecs(
    const std::vector<AudioCodec>& codecs) {
  // Set the payload types to be used for incoming media.
  LOG(LS_INFO) << "Setting receive voice codecs:";

  std::vector<AudioCodec> new_codecs;
  // Find all new codecs. We allow adding new codecs but don't allow changing
  // the payload type of codecs that is already configured since we might
  // already be receiving packets with that payload type.
  for (std::vector<AudioCodec>::const_iterator it = codecs.begin();
       it != codecs.end(); ++it) {
    AudioCodec old_codec;
    if (FindCodec(recv_codecs_, *it, &old_codec)) {
      if (old_codec.id != it->id) {
        LOG(LS_ERROR) << it->name << " payload type changed.";
        return false;
      }
    } else {
      new_codecs.push_back(*it);
    }
  }
  if (new_codecs.empty()) {
    // There are no new codecs to configure. Already configured codecs are
    // never removed.
    return true;
  }

  if (playout_) {
    // Receive codecs can not be changed while playing. So we temporarily
    // pause playout.
    PausePlayout();
  }

  bool ret = true;
  for (std::vector<AudioCodec>::const_iterator it = new_codecs.begin();
       it != new_codecs.end() && ret; ++it) {
    webrtc::CodecInst voe_codec;
    if (engine()->FindWebRtcCodec(*it, &voe_codec)) {
      LOG(LS_INFO) << ToString(*it);
      voe_codec.pltype = it->id;
      if (default_receive_ssrc_ == 0) {
        // Set the receive codecs on the default channel explicitly if the
        // default channel is not used by |receive_channels_|, this happens in
        // conference mode or in non-conference mode when there is no playout
        // channel.
        // TODO(xians): Figure out how we use the default channel in conference
        // mode.
        if (engine()->voe()->codec()->SetRecPayloadType(
            voe_channel(), voe_codec) == -1) {
          LOG_RTCERR2(SetRecPayloadType, voe_channel(), ToString(voe_codec));
          ret = false;
        }
      }

      // Set the receive codecs on all receiving channels.
      for (ChannelMap::iterator it = receive_channels_.begin();
           it != receive_channels_.end() && ret; ++it) {
        if (engine()->voe()->codec()->SetRecPayloadType(
                it->second->channel(), voe_codec) == -1) {
          LOG_RTCERR2(SetRecPayloadType, it->second->channel(),
                      ToString(voe_codec));
          ret = false;
        }
      }
    } else {
      LOG(LS_WARNING) << "Unknown codec " << ToString(*it);
      ret = false;
    }
  }
  if (ret) {
    recv_codecs_ = codecs;
  }

  if (desired_playout_ && !playout_) {
    ResumePlayout();
  }
  return ret;
}

bool WebRtcVoiceMediaChannel::SetSendCodecs(
    int channel, const std::vector<AudioCodec>& codecs) {
  // Disable VAD, FEC, and RED unless we know the other side wants them.
  engine()->voe()->codec()->SetVADStatus(channel, false);
  engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
  engine()->voe()->rtp()->SetREDStatus(channel, false);
  engine()->voe()->codec()->SetFECStatus(channel, false);

  // Scan through the list to figure out the codec to use for sending, along
  // with the proper configuration for VAD and DTMF.
  bool found_send_codec = false;
  webrtc::CodecInst send_codec;
  memset(&send_codec, 0, sizeof(send_codec));

  bool nack_enabled = nack_enabled_;
  bool enable_codec_fec = false;

  int opus_max_playback_rate = 0;

  // Set send codec (the first non-telephone-event/CN codec)
  for (std::vector<AudioCodec>::const_iterator it = codecs.begin();
       it != codecs.end(); ++it) {
    // Ignore codecs we don't know about. The negotiation step should prevent
    // this, but double-check to be sure.
    webrtc::CodecInst voe_codec;
    if (!engine()->FindWebRtcCodec(*it, &voe_codec)) {
      LOG(LS_WARNING) << "Unknown codec " << ToString(*it);
      continue;
    }

    if (IsTelephoneEventCodec(it->name) || IsCNCodec(it->name)) {
      // Skip telephone-event/CN codec, which will be handled later.
      continue;
    }

    // We'll use the first codec in the list to actually send audio data.
    // Be sure to use the payload type requested by the remote side.
    // "red", for RED audio, is a special case where the actual codec to be
    // used is specified in params.
    if (IsRedCodec(it->name)) {
      // Parse out the RED parameters. If we fail, just ignore RED;
      // we don't support all possible params/usage scenarios.
      if (!GetRedSendCodec(*it, codecs, &send_codec)) {
        continue;
      }

      // Enable redundant encoding of the specified codec. Treat any
      // failure as a fatal internal error.
      LOG(LS_INFO) << "Enabling RED on channel " << channel;
      if (engine()->voe()->rtp()->SetREDStatus(channel, true, it->id) == -1) {
        LOG_RTCERR3(SetREDStatus, channel, true, it->id);
        return false;
      }
    } else {
      send_codec = voe_codec;
      nack_enabled = IsNackEnabled(*it);
      // For Opus as the send codec, we are to enable inband FEC if requested
      // and set maximum playback rate.
      if (IsOpus(*it)) {
        GetOpusConfig(*it, &send_codec, &enable_codec_fec,
                      &opus_max_playback_rate);
      }
    }
    found_send_codec = true;
    break;
  }

  if (nack_enabled_ != nack_enabled) {
    SetNack(channel, nack_enabled);
    nack_enabled_ = nack_enabled;
  }

  if (!found_send_codec) {
    LOG(LS_WARNING) << "Received empty list of codecs.";
    return false;
  }

  // Set the codec immediately, since SetVADStatus() depends on whether
  // the current codec is mono or stereo.
  if (!SetSendCodec(channel, send_codec))
    return false;

  // FEC should be enabled after SetSendCodec.
  if (enable_codec_fec) {
    LOG(LS_INFO) << "Attempt to enable codec internal FEC on channel "
                 << channel;
    if (engine()->voe()->codec()->SetFECStatus(channel, true) == -1) {
      // Enable codec internal FEC. Treat any failure as fatal internal error.
      LOG_RTCERR2(SetFECStatus, channel, true);
      return false;
    }
  }

  // maxplaybackrate should be set after SetSendCodec.
  // If opus_max_playback_rate <= 0, the default maximum playback rate of 48 kHz
  // will be used.
  if (opus_max_playback_rate > 0) {
    LOG(LS_INFO) << "Attempt to set maximum playback rate to "
                 << opus_max_playback_rate
                 << " Hz on channel "
                 << channel;
    if (engine()->voe()->codec()->SetOpusMaxPlaybackRate(
        channel, opus_max_playback_rate) == -1) {
      LOG(LS_WARNING) << "Could not set maximum playback rate.";
    }
  }

  // Always update the |send_codec_| to the currently set send codec.
  send_codec_.reset(new webrtc::CodecInst(send_codec));

  if (send_bitrate_setting_) {
    SetSendBitrateInternal(send_bitrate_bps_);
  }

  // Loop through the codecs list again to config the telephone-event/CN codec.
  for (std::vector<AudioCodec>::const_iterator it = codecs.begin();
       it != codecs.end(); ++it) {
    // Ignore codecs we don't know about. The negotiation step should prevent
    // this, but double-check to be sure.
    webrtc::CodecInst voe_codec;
    if (!engine()->FindWebRtcCodec(*it, &voe_codec)) {
      LOG(LS_WARNING) << "Unknown codec " << ToString(*it);
      continue;
    }

    // Find the DTMF telephone event "codec" and tell VoiceEngine channels
    // about it.
    if (IsTelephoneEventCodec(it->name)) {
      if (engine()->voe()->dtmf()->SetSendTelephoneEventPayloadType(
              channel, it->id) == -1) {
        LOG_RTCERR2(SetSendTelephoneEventPayloadType, channel, it->id);
        return false;
      }
    } else if (IsCNCodec(it->name)) {
      // Turn voice activity detection/comfort noise on if supported.
      // Set the wideband CN payload type appropriately.
      // (narrowband always uses the static payload type 13).
      webrtc::PayloadFrequencies cn_freq;
      switch (it->clockrate) {
        case 8000:
          cn_freq = webrtc::kFreq8000Hz;
          break;
        case 16000:
          cn_freq = webrtc::kFreq16000Hz;
          break;
        case 32000:
          cn_freq = webrtc::kFreq32000Hz;
          break;
        default:
          LOG(LS_WARNING) << "CN frequency " << it->clockrate
                          << " not supported.";
          continue;
      }
      // Set the CN payloadtype and the VAD status.
      // The CN payload type for 8000 Hz clockrate is fixed at 13.
      if (cn_freq != webrtc::kFreq8000Hz) {
        if (engine()->voe()->codec()->SetSendCNPayloadType(
                channel, it->id, cn_freq) == -1) {
          LOG_RTCERR3(SetSendCNPayloadType, channel, it->id, cn_freq);
          // TODO(ajm): This failure condition will be removed from VoE.
          // Restore the return here when we update to a new enough webrtc.
          //
          // Not returning false because the SetSendCNPayloadType will fail if
          // the channel is already sending.
          // This can happen if the remote description is applied twice, for
          // example in the case of ROAP on top of JSEP, where both side will
          // send the offer.
        }
      }
      // Only turn on VAD if we have a CN payload type that matches the
      // clockrate for the codec we are going to use.
      if (it->clockrate == send_codec.plfreq) {
        LOG(LS_INFO) << "Enabling VAD";
        if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) {
          LOG_RTCERR2(SetVADStatus, channel, true);
          return false;
        }
      }
    }
  }
  return true;
}

bool WebRtcVoiceMediaChannel::SetSendCodecs(
    const std::vector<AudioCodec>& codecs) {
  dtmf_allowed_ = false;
  for (std::vector<AudioCodec>::const_iterator it = codecs.begin();
       it != codecs.end(); ++it) {
    // Find the DTMF telephone event "codec".
    if (_stricmp(it->name.c_str(), "telephone-event") == 0 ||
        _stricmp(it->name.c_str(), "audio/telephone-event") == 0) {
      dtmf_allowed_ = true;
    }
  }

  // Cache the codecs in order to configure the channel created later.
  send_codecs_ = codecs;
  for (ChannelMap::iterator iter = send_channels_.begin();
       iter != send_channels_.end(); ++iter) {
    if (!SetSendCodecs(iter->second->channel(), codecs)) {
      return false;
    }
  }

  // Set nack status on receive channels and update |nack_enabled_|.
  SetNack(receive_channels_, nack_enabled_);
  return true;
}

void WebRtcVoiceMediaChannel::SetNack(const ChannelMap& channels,
                                      bool nack_enabled) {
  for (ChannelMap::const_iterator it = channels.begin();
       it != channels.end(); ++it) {
    SetNack(it->second->channel(), nack_enabled);
  }
}

void WebRtcVoiceMediaChannel::SetNack(int channel, bool nack_enabled) {
  if (nack_enabled) {
    LOG(LS_INFO) << "Enabling NACK for channel " << channel;
    engine()->voe()->rtp()->SetNACKStatus(channel, true, kNackMaxPackets);
  } else {
    LOG(LS_INFO) << "Disabling NACK for channel " << channel;
    engine()->voe()->rtp()->SetNACKStatus(channel, false, 0);
  }
}

bool WebRtcVoiceMediaChannel::SetSendCodec(
    const webrtc::CodecInst& send_codec) {
  LOG(LS_INFO) << "Selected voice codec " << ToString(send_codec)
               << ", bitrate=" << send_codec.rate;
  for (ChannelMap::iterator iter = send_channels_.begin();
       iter != send_channels_.end(); ++iter) {
    if (!SetSendCodec(iter->second->channel(), send_codec))
      return false;
  }

  return true;
}

bool WebRtcVoiceMediaChannel::SetSendCodec(
    int channel, const webrtc::CodecInst& send_codec) {
  LOG(LS_INFO) << "Send channel " << channel <<  " selected voice codec "
               << ToString(send_codec) << ", bitrate=" << send_codec.rate;

  webrtc::CodecInst current_codec;
  if (engine()->voe()->codec()->GetSendCodec(channel, current_codec) == 0 &&
      (send_codec == current_codec)) {
    // Codec is already configured, we can return without setting it again.
    return true;
  }

  if (engine()->voe()->codec()->SetSendCodec(channel, send_codec) == -1) {
    LOG_RTCERR2(SetSendCodec, channel, ToString(send_codec));
    return false;
  }
  return true;
}

bool WebRtcVoiceMediaChannel::SetRecvRtpHeaderExtensions(
    const std::vector<RtpHeaderExtension>& extensions) {
  if (receive_extensions_ == extensions) {
    return true;
  }

  // The default channel may or may not be in |receive_channels_|. Set the rtp
  // header extensions for default channel regardless.
  if (!SetChannelRecvRtpHeaderExtensions(voe_channel(), extensions)) {
    return false;
  }

  // Loop through all receive channels and enable/disable the extensions.
  for (ChannelMap::const_iterator channel_it = receive_channels_.begin();
       channel_it != receive_channels_.end(); ++channel_it) {
    if (!SetChannelRecvRtpHeaderExtensions(channel_it->second->channel(),
                                           extensions)) {
      return false;
    }
  }

  receive_extensions_ = extensions;
  return true;
}

bool WebRtcVoiceMediaChannel::SetChannelRecvRtpHeaderExtensions(
    int channel_id, const std::vector<RtpHeaderExtension>& extensions) {
  const RtpHeaderExtension* audio_level_extension =
      FindHeaderExtension(extensions, kRtpAudioLevelHeaderExtension);
  if (!SetHeaderExtension(
      &webrtc::VoERTP_RTCP::SetReceiveAudioLevelIndicationStatus, channel_id,
      audio_level_extension)) {
    return false;
  }

  const RtpHeaderExtension* send_time_extension =
      FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
  if (!SetHeaderExtension(
      &webrtc::VoERTP_RTCP::SetReceiveAbsoluteSenderTimeStatus, channel_id,
      send_time_extension)) {
    return false;
  }
  return true;
}

bool WebRtcVoiceMediaChannel::SetSendRtpHeaderExtensions(
    const std::vector<RtpHeaderExtension>& extensions) {
  if (send_extensions_ == extensions) {
    return true;
  }

  // The default channel may or may not be in |send_channels_|. Set the rtp
  // header extensions for default channel regardless.

  if (!SetChannelSendRtpHeaderExtensions(voe_channel(), extensions)) {
    return false;
  }

  // Loop through all send channels and enable/disable the extensions.
  for (ChannelMap::const_iterator channel_it = send_channels_.begin();
       channel_it != send_channels_.end(); ++channel_it) {
    if (!SetChannelSendRtpHeaderExtensions(channel_it->second->channel(),
                                           extensions)) {
      return false;
    }
  }

  send_extensions_ = extensions;
  return true;
}

bool WebRtcVoiceMediaChannel::SetChannelSendRtpHeaderExtensions(
    int channel_id, const std::vector<RtpHeaderExtension>& extensions) {
  const RtpHeaderExtension* audio_level_extension =
      FindHeaderExtension(extensions, kRtpAudioLevelHeaderExtension);

  if (!SetHeaderExtension(
      &webrtc::VoERTP_RTCP::SetSendAudioLevelIndicationStatus, channel_id,
      audio_level_extension)) {
    return false;
  }

  const RtpHeaderExtension* send_time_extension =
      FindHeaderExtension(extensions, kRtpAbsoluteSenderTimeHeaderExtension);
  if (!SetHeaderExtension(
      &webrtc::VoERTP_RTCP::SetSendAbsoluteSenderTimeStatus, channel_id,
      send_time_extension)) {
    return false;
  }

  return true;
}

bool WebRtcVoiceMediaChannel::SetPlayout(bool playout) {
  desired_playout_ = playout;
  return ChangePlayout(desired_playout_);
}

bool WebRtcVoiceMediaChannel::PausePlayout() {
  return ChangePlayout(false);
}

bool WebRtcVoiceMediaChannel::ResumePlayout() {
  return ChangePlayout(desired_playout_);
}

bool WebRtcVoiceMediaChannel::ChangePlayout(bool playout) {
  if (playout_ == playout) {
    return true;
  }

  // Change the playout of all channels to the new state.
  bool result = true;
  if (receive_channels_.empty()) {
    // Only toggle the default channel if we don't have any other channels.
    result = SetPlayout(voe_channel(), playout);
  }
  for (ChannelMap::iterator it = receive_channels_.begin();
       it != receive_channels_.end() && result; ++it) {
    if (!SetPlayout(it->second->channel(), playout)) {
      LOG(LS_ERROR) << "SetPlayout " << playout << " on channel "
                    << it->second->channel() << " failed";
      result = false;
    }
  }

  if (result) {
    playout_ = playout;
  }
  return result;
}

bool WebRtcVoiceMediaChannel::SetSend(SendFlags send) {
  desired_send_ = send;
  if (!send_channels_.empty())
    return ChangeSend(desired_send_);
  return true;
}

bool WebRtcVoiceMediaChannel::PauseSend() {
  return ChangeSend(SEND_NOTHING);
}

bool WebRtcVoiceMediaChannel::ResumeSend() {
  return ChangeSend(desired_send_);
}

bool WebRtcVoiceMediaChannel::ChangeSend(SendFlags send) {
  if (send_ == send) {
    return true;
  }

  // Change the settings on each send channel.
  if (send == SEND_MICROPHONE)
    engine()->SetOptionOverrides(options_);

  // Change the settings on each send channel.
  for (ChannelMap::iterator iter = send_channels_.begin();
       iter != send_channels_.end(); ++iter) {
    if (!ChangeSend(iter->second->channel(), send))
      return false;
  }

  // Clear up the options after stopping sending.
  if (send == SEND_NOTHING)
    engine()->ClearOptionOverrides();

  send_ = send;
  return true;
}

bool WebRtcVoiceMediaChannel::ChangeSend(int channel, SendFlags send) {
  if (send == SEND_MICROPHONE) {
    if (engine()->voe()->base()->StartSend(channel) == -1) {
      LOG_RTCERR1(StartSend, channel);
      return false;
    }
    if (engine()->voe()->file() &&
        engine()->voe()->file()->StopPlayingFileAsMicrophone(channel) == -1) {
      LOG_RTCERR1(StopPlayingFileAsMicrophone, channel);
      return false;
    }
  } else {  // SEND_NOTHING
    ASSERT(send == SEND_NOTHING);
    if (engine()->voe()->base()->StopSend(channel) == -1) {
      LOG_RTCERR1(StopSend, channel);
      return false;
    }
  }

  return true;
}

// TODO(ronghuawu): Change this method to return bool.
void WebRtcVoiceMediaChannel::ConfigureSendChannel(int channel) {
  if (engine()->voe()->network()->RegisterExternalTransport(
          channel, *this) == -1) {
    LOG_RTCERR2(RegisterExternalTransport, channel, this);
  }

  // Enable RTCP (for quality stats and feedback messages)
  EnableRtcp(channel);

  // Reset all recv codecs; they will be enabled via SetRecvCodecs.
  ResetRecvCodecs(channel);

  // Set RTP header extension for the new channel.
  SetChannelSendRtpHeaderExtensions(channel, send_extensions_);
}

bool WebRtcVoiceMediaChannel::DeleteChannel(int channel) {
  if (engine()->voe()->network()->DeRegisterExternalTransport(channel) == -1) {
    LOG_RTCERR1(DeRegisterExternalTransport, channel);
  }

  if (engine()->voe()->base()->DeleteChannel(channel) == -1) {
    LOG_RTCERR1(DeleteChannel, channel);
    return false;
  }

  return true;
}

bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
  // If the default channel is already used for sending create a new channel
  // otherwise use the default channel for sending.
  int channel = GetSendChannelNum(sp.first_ssrc());
  if (channel != -1) {
    LOG(LS_ERROR) << "Stream already exists with ssrc " << sp.first_ssrc();
    return false;
  }

  bool default_channel_is_available = true;
  for (ChannelMap::const_iterator iter = send_channels_.begin();
       iter != send_channels_.end(); ++iter) {
    if (IsDefaultChannel(iter->second->channel())) {
      default_channel_is_available = false;
      break;
    }
  }
  if (default_channel_is_available) {
    channel = voe_channel();
  } else {
    // Create a new channel for sending audio data.
    channel = engine()->CreateMediaVoiceChannel();
    if (channel == -1) {
      LOG_RTCERR0(CreateChannel);
      return false;
    }

    ConfigureSendChannel(channel);
  }

  // Save the channel to send_channels_, so that RemoveSendStream() can still
  // delete the channel in case failure happens below.
  webrtc::AudioTransport* audio_transport =
      engine()->voe()->base()->audio_transport();
  send_channels_.insert(std::make_pair(
      sp.first_ssrc(),
      new WebRtcVoiceChannelRenderer(channel, audio_transport)));

  // Set the send (local) SSRC.
  // If there are multiple send SSRCs, we can only set the first one here, and
  // the rest of the SSRC(s) need to be set after SetSendCodec has been called
  // (with a codec requires multiple SSRC(s)).
  if (engine()->voe()->rtp()->SetLocalSSRC(channel, sp.first_ssrc()) == -1) {
    LOG_RTCERR2(SetSendSSRC, channel, sp.first_ssrc());
    return false;
  }

  // At this point the channel's local SSRC has been updated. If the channel is
  // the default channel make sure that all the receive channels are updated as
  // well. Receive channels have to have the same SSRC as the default channel in
  // order to send receiver reports with this SSRC.
  if (IsDefaultChannel(channel)) {
    for (ChannelMap::const_iterator it = receive_channels_.begin();
         it != receive_channels_.end(); ++it) {
      // Only update the SSRC for non-default channels.
      if (!IsDefaultChannel(it->second->channel())) {
        if (engine()->voe()->rtp()->SetLocalSSRC(it->second->channel(),
                                                 sp.first_ssrc()) != 0) {
          LOG_RTCERR2(SetLocalSSRC, it->second->channel(), sp.first_ssrc());
          return false;
        }
      }
    }
  }

  if (engine()->voe()->rtp()->SetRTCP_CNAME(channel, sp.cname.c_str()) == -1) {
    LOG_RTCERR2(SetRTCP_CNAME, channel, sp.cname);
    return false;
  }

  // Set the current codecs to be used for the new channel.
  if (!send_codecs_.empty() && !SetSendCodecs(channel, send_codecs_))
    return false;

  return ChangeSend(channel, desired_send_);
}

bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32 ssrc) {
  ChannelMap::iterator it = send_channels_.find(ssrc);
  if (it == send_channels_.end()) {
    LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
                    << " which doesn't exist.";
    return false;
  }

  int channel = it->second->channel();
  ChangeSend(channel, SEND_NOTHING);

  // Delete the WebRtcVoiceChannelRenderer object connected to the channel,
  // this will disconnect the audio renderer with the send channel.
  delete it->second;
  send_channels_.erase(it);

  if (IsDefaultChannel(channel)) {
    // Do not delete the default channel since the receive channels depend on
    // the default channel, recycle it instead.
    ChangeSend(channel, SEND_NOTHING);
  } else {
    // Clean up and delete the send channel.
    LOG(LS_INFO) << "Removing audio send stream " << ssrc
                 << " with VoiceEngine channel #" << channel << ".";
    if (!DeleteChannel(channel))
      return false;
  }

  if (send_channels_.empty())
    ChangeSend(SEND_NOTHING);

  return true;
}

bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
  rtc::CritScope lock(&receive_channels_cs_);

  if (!VERIFY(sp.ssrcs.size() == 1))
    return false;
  uint32 ssrc = sp.first_ssrc();

  if (ssrc == 0) {
    LOG(LS_WARNING) << "AddRecvStream with 0 ssrc is not supported.";
    return false;
  }

  if (receive_channels_.find(ssrc) != receive_channels_.end()) {
    LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
    return false;
  }

  // Reuse default channel for recv stream in non-conference mode call
  // when the default channel is not being used.
  webrtc::AudioTransport* audio_transport =
      engine()->voe()->base()->audio_transport();
  if (!InConferenceMode() && default_receive_ssrc_ == 0) {
    LOG(LS_INFO) << "Recv stream " << sp.first_ssrc()
                 << " reuse default channel";
    default_receive_ssrc_ = sp.first_ssrc();
    receive_channels_.insert(std::make_pair(
        default_receive_ssrc_,
        new WebRtcVoiceChannelRenderer(voe_channel(), audio_transport)));
    if (!SetupSharedBweOnChannel(voe_channel())) {
      return false;
    }
    return SetPlayout(voe_channel(), playout_);
  }

  // Create a new channel for receiving audio data.
  int channel = engine()->CreateMediaVoiceChannel();
  if (channel == -1) {
    LOG_RTCERR0(CreateChannel);
    return false;
  }

  if (!ConfigureRecvChannel(channel)) {
    DeleteChannel(channel);
    return false;
  }

  receive_channels_.insert(
      std::make_pair(
          ssrc, new WebRtcVoiceChannelRenderer(channel, audio_transport)));

  LOG(LS_INFO) << "New audio stream " << ssrc
               << " registered to VoiceEngine channel #"
               << channel << ".";
  return true;
}

bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) {
  // Configure to use external transport, like our default channel.
  if (engine()->voe()->network()->RegisterExternalTransport(
          channel, *this) == -1) {
    LOG_RTCERR2(SetExternalTransport, channel, this);
    return false;
  }

  // Use the same SSRC as our default channel (so the RTCP reports are correct).
  unsigned int send_ssrc = 0;
  webrtc::VoERTP_RTCP* rtp = engine()->voe()->rtp();
  if (rtp->GetLocalSSRC(voe_channel(), send_ssrc) == -1) {
    LOG_RTCERR1(GetSendSSRC, channel);
    return false;
  }
  if (rtp->SetLocalSSRC(channel, send_ssrc) == -1) {
    LOG_RTCERR1(SetSendSSRC, channel);
    return false;
  }

  // Use the same recv payload types as our default channel.
  ResetRecvCodecs(channel);
  if (!recv_codecs_.empty()) {
    for (std::vector<AudioCodec>::const_iterator it = recv_codecs_.begin();
        it != recv_codecs_.end(); ++it) {
      webrtc::CodecInst voe_codec;
      if (engine()->FindWebRtcCodec(*it, &voe_codec)) {
        voe_codec.pltype = it->id;
        voe_codec.rate = 0;  // Needed to make GetRecPayloadType work for ISAC
        if (engine()->voe()->codec()->GetRecPayloadType(
            voe_channel(), voe_codec) != -1) {
          if (engine()->voe()->codec()->SetRecPayloadType(
              channel, voe_codec) == -1) {
            LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec));
            return false;
          }
        }
      }
    }
  }

  if (InConferenceMode()) {
    // To be in par with the video, voe_channel() is not used for receiving in
    // a conference call.
    if (receive_channels_.empty() && default_receive_ssrc_ == 0 && playout_) {
      // This is the first stream in a multi user meeting. We can now
      // disable playback of the default stream. This since the default
      // stream will probably have received some initial packets before
      // the new stream was added. This will mean that the CN state from
      // the default channel will be mixed in with the other streams
      // throughout the whole meeting, which might be disturbing.
      LOG(LS_INFO) << "Disabling playback on the default voice channel";
      SetPlayout(voe_channel(), false);
    }
  }
  SetNack(channel, nack_enabled_);

  // Set RTP header extension for the new channel.
  if (!SetChannelRecvRtpHeaderExtensions(channel, receive_extensions_)) {
    return false;
  }

  // Set up channel to be able to forward incoming packets to video engine BWE.
  if (!SetupSharedBweOnChannel(channel)) {
    return false;
  }

  return SetPlayout(channel, playout_);
}

bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32 ssrc) {
  rtc::CritScope lock(&receive_channels_cs_);
  ChannelMap::iterator it = receive_channels_.find(ssrc);
  if (it == receive_channels_.end()) {
    LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
                    << " which doesn't exist.";
    return false;
  }

  // Delete the WebRtcVoiceChannelRenderer object connected to the channel, this
  // will disconnect the audio renderer with the receive channel.
  // Cache the channel before the deletion.
  const int channel = it->second->channel();
  delete it->second;
  receive_channels_.erase(it);

  if (ssrc == default_receive_ssrc_) {
    ASSERT(IsDefaultChannel(channel));
    // Recycle the default channel is for recv stream.
    if (playout_)
      SetPlayout(voe_channel(), false);

    default_receive_ssrc_ = 0;
    return true;
  }

  LOG(LS_INFO) << "Removing audio stream " << ssrc
               << " with VoiceEngine channel #" << channel << ".";
  if (!DeleteChannel(channel))
    return false;

  bool enable_default_channel_playout = false;
  if (receive_channels_.empty()) {
    // The last stream was removed. We can now enable the default
    // channel for new channels to be played out immediately without
    // waiting for AddStream messages.
    // We do this for both conference mode and non-conference mode.
    // TODO(oja): Does the default channel still have it's CN state?
    enable_default_channel_playout = true;
  }
  if (!InConferenceMode() && receive_channels_.size() == 1 &&
      default_receive_ssrc_ != 0) {
    // Only the default channel is active, enable the playout on default
    // channel.
    enable_default_channel_playout = true;
  }
  if (enable_default_channel_playout && playout_) {
    LOG(LS_INFO) << "Enabling playback on the default voice channel";
    SetPlayout(voe_channel(), true);
  }

  return true;
}

bool WebRtcVoiceMediaChannel::SetRemoteRenderer(uint32 ssrc,
                                                AudioRenderer* renderer) {
  ChannelMap::iterator it = receive_channels_.find(ssrc);
  if (it == receive_channels_.end()) {
    if (renderer) {
      // Return an error if trying to set a valid renderer with an invalid ssrc.
      LOG(LS_ERROR) << "SetRemoteRenderer failed with ssrc "<< ssrc;
      return false;
    }

    // The channel likely has gone away, do nothing.
    return true;
  }

  if (renderer)
    it->second->Start(renderer);
  else
    it->second->Stop();

  return true;
}

bool WebRtcVoiceMediaChannel::SetLocalRenderer(uint32 ssrc,
                                               AudioRenderer* renderer) {
  ChannelMap::iterator it = send_channels_.find(ssrc);
  if (it == send_channels_.end()) {
    if (renderer) {
      // Return an error if trying to set a valid renderer with an invalid ssrc.
      LOG(LS_ERROR) << "SetLocalRenderer failed with ssrc "<< ssrc;
      return false;
    }

    // The channel likely has gone away, do nothing.
    return true;
  }

  if (renderer)
    it->second->Start(renderer);
  else
    it->second->Stop();

  return true;
}

bool WebRtcVoiceMediaChannel::GetActiveStreams(
    AudioInfo::StreamList* actives) {
  // In conference mode, the default channel should not be in
  // |receive_channels_|.
  actives->clear();
  for (ChannelMap::iterator it = receive_channels_.begin();
       it != receive_channels_.end(); ++it) {
    int level = GetOutputLevel(it->second->channel());
    if (level > 0) {
      actives->push_back(std::make_pair(it->first, level));
    }
  }
  return true;
}

int WebRtcVoiceMediaChannel::GetOutputLevel() {
  // return the highest output level of all streams
  int highest = GetOutputLevel(voe_channel());
  for (ChannelMap::iterator it = receive_channels_.begin();
       it != receive_channels_.end(); ++it) {
    int level = GetOutputLevel(it->second->channel());
    highest = std::max(level, highest);
  }
  return highest;
}

int WebRtcVoiceMediaChannel::GetTimeSinceLastTyping() {
  int ret;
  if (engine()->voe()->processing()->TimeSinceLastTyping(ret) == -1) {
    // In case of error, log the info and continue
    LOG_RTCERR0(TimeSinceLastTyping);
    ret = -1;
  } else {
    ret *= 1000;  // We return ms, webrtc returns seconds.
  }
  return ret;
}

void WebRtcVoiceMediaChannel::SetTypingDetectionParameters(int time_window,
    int cost_per_typing, int reporting_threshold, int penalty_decay,
    int type_event_delay) {
  if (engine()->voe()->processing()->SetTypingDetectionParameters(
          time_window, cost_per_typing,
          reporting_threshold, penalty_decay, type_event_delay) == -1) {
    // In case of error, log the info and continue
    LOG_RTCERR5(SetTypingDetectionParameters, time_window,
                cost_per_typing, reporting_threshold, penalty_decay,
                type_event_delay);
  }
}

bool WebRtcVoiceMediaChannel::SetOutputScaling(
    uint32 ssrc, double left, double right) {
  rtc::CritScope lock(&receive_channels_cs_);
  // Collect the channels to scale the output volume.
  std::vector<int> channels;
  if (0 == ssrc) {  // Collect all channels, including the default one.
    // Default channel is not in receive_channels_ if it is not being used for
    // playout.
    if (default_receive_ssrc_ == 0)
      channels.push_back(voe_channel());
    for (ChannelMap::const_iterator it = receive_channels_.begin();
         it != receive_channels_.end(); ++it) {
      channels.push_back(it->second->channel());
    }
  } else {  // Collect only the channel of the specified ssrc.
    int channel = GetReceiveChannelNum(ssrc);
    if (-1 == channel) {
      LOG(LS_WARNING) << "Cannot find channel for ssrc:" << ssrc;
      return false;
    }
    channels.push_back(channel);
  }

  // Scale the output volume for the collected channels. We first normalize to
  // scale the volume and then set the left and right pan.
  float scale = static_cast<float>(std::max(left, right));
  if (scale > 0.0001f) {
    left /= scale;
    right /= scale;
  }
  for (std::vector<int>::const_iterator it = channels.begin();
      it != channels.end(); ++it) {
    if (-1 == engine()->voe()->volume()->SetChannelOutputVolumeScaling(
        *it, scale)) {
      LOG_RTCERR2(SetChannelOutputVolumeScaling, *it, scale);
      return false;
    }
    if (-1 == engine()->voe()->volume()->SetOutputVolumePan(
        *it, static_cast<float>(left), static_cast<float>(right))) {
      LOG_RTCERR3(SetOutputVolumePan, *it, left, right);
      // Do not return if fails. SetOutputVolumePan is not available for all
      // pltforms.
    }
    LOG(LS_INFO) << "SetOutputScaling to left=" << left * scale
                 << " right=" << right * scale
                 << " for channel " << *it << " and ssrc " << ssrc;
  }
  return true;
}

bool WebRtcVoiceMediaChannel::GetOutputScaling(
    uint32 ssrc, double* left, double* right) {
  if (!left || !right) return false;

  rtc::CritScope lock(&receive_channels_cs_);
  // Determine which channel based on ssrc.
  int channel = (0 == ssrc) ? voe_channel() : GetReceiveChannelNum(ssrc);
  if (channel == -1) {
    LOG(LS_WARNING) << "Cannot find channel for ssrc:" << ssrc;
    return false;
  }

  float scaling;
  if (-1 == engine()->voe()->volume()->GetChannelOutputVolumeScaling(
      channel, scaling)) {
    LOG_RTCERR2(GetChannelOutputVolumeScaling, channel, scaling);
    return false;
  }

  float left_pan;
  float right_pan;
  if (-1 == engine()->voe()->volume()->GetOutputVolumePan(
      channel, left_pan, right_pan)) {
    LOG_RTCERR3(GetOutputVolumePan, channel, left_pan, right_pan);
    // If GetOutputVolumePan fails, we use the default left and right pan.
    left_pan = 1.0f;
    right_pan = 1.0f;
  }

  *left = scaling * left_pan;
  *right = scaling * right_pan;
  return true;
}

bool WebRtcVoiceMediaChannel::SetRingbackTone(const char *buf, int len) {
  ringback_tone_.reset(new WebRtcSoundclipStream(buf, len));
  return true;
}

bool WebRtcVoiceMediaChannel::PlayRingbackTone(uint32 ssrc,
                                             bool play, bool loop) {
  if (!ringback_tone_) {
    return false;
  }

  // The voe file api is not available in chrome.
  if (!engine()->voe()->file()) {
    return false;
  }

  // Determine which VoiceEngine channel to play on.
  int channel = (ssrc == 0) ? voe_channel() : GetReceiveChannelNum(ssrc);
  if (channel == -1) {
    return false;
  }

  // Make sure the ringtone is cued properly, and play it out.
  if (play) {
    ringback_tone_->set_loop(loop);
    ringback_tone_->Rewind();
    if (engine()->voe()->file()->StartPlayingFileLocally(channel,
        ringback_tone_.get()) == -1) {
      LOG_RTCERR2(StartPlayingFileLocally, channel, ringback_tone_.get());
      LOG(LS_ERROR) << "Unable to start ringback tone";
      return false;
    }
    ringback_channels_.insert(channel);
    LOG(LS_INFO) << "Started ringback on channel " << channel;
  } else {
    if (engine()->voe()->file()->IsPlayingFileLocally(channel) == 1 &&
        engine()->voe()->file()->StopPlayingFileLocally(channel) == -1) {
      LOG_RTCERR1(StopPlayingFileLocally, channel);
      return false;
    }
    LOG(LS_INFO) << "Stopped ringback on channel " << channel;
    ringback_channels_.erase(channel);
  }

  return true;
}

bool WebRtcVoiceMediaChannel::CanInsertDtmf() {
  return dtmf_allowed_;
}

bool WebRtcVoiceMediaChannel::InsertDtmf(uint32 ssrc, int event,
                                         int duration, int flags) {
  if (!dtmf_allowed_) {
    return false;
  }

  // Send the event.
  if (flags & cricket::DF_SEND) {
    int channel = -1;
    if (ssrc == 0) {
      bool default_channel_is_inuse = false;
      for (ChannelMap::const_iterator iter = send_channels_.begin();
           iter != send_channels_.end(); ++iter) {
        if (IsDefaultChannel(iter->second->channel())) {
          default_channel_is_inuse = true;
          break;
        }
      }
      if (default_channel_is_inuse) {
        channel = voe_channel();
      } else if (!send_channels_.empty()) {
        channel = send_channels_.begin()->second->channel();
      }
    } else {
      channel = GetSendChannelNum(ssrc);
    }
    if (channel == -1) {
      LOG(LS_WARNING) << "InsertDtmf - The specified ssrc "
                      << ssrc << " is not in use.";
      return false;
    }
    // Send DTMF using out-of-band DTMF. ("true", as 3rd arg)
    if (engine()->voe()->dtmf()->SendTelephoneEvent(
            channel, event, true, duration) == -1) {
      LOG_RTCERR4(SendTelephoneEvent, channel, event, true, duration);
      return false;
    }
  }

  // Play the event.
  if (flags & cricket::DF_PLAY) {
    // Play DTMF tone locally.
    if (engine()->voe()->dtmf()->PlayDtmfTone(event, duration) == -1) {
      LOG_RTCERR2(PlayDtmfTone, event, duration);
      return false;
    }
  }

  return true;
}

void WebRtcVoiceMediaChannel::OnPacketReceived(
    rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
  // Pick which channel to send this packet to. If this packet doesn't match
  // any multiplexed streams, just send it to the default channel. Otherwise,
  // send it to the specific decoder instance for that stream.
  int which_channel =
      GetReceiveChannelNum(ParseSsrc(packet->data(), packet->size(), false));
  if (which_channel == -1) {
    which_channel = voe_channel();
  }

  // Stop any ringback that might be playing on the channel.
  // It's possible the ringback has already stopped, ih which case we'll just
  // use the opportunity to remove the channel from ringback_channels_.
  if (engine()->voe()->file()) {
    const std::set<int>::iterator it = ringback_channels_.find(which_channel);
    if (it != ringback_channels_.end()) {
      if (engine()->voe()->file()->IsPlayingFileLocally(
          which_channel) == 1) {
        engine()->voe()->file()->StopPlayingFileLocally(which_channel);
        LOG(LS_INFO) << "Stopped ringback on channel " << which_channel
                     << " due to incoming media";
      }
      ringback_channels_.erase(which_channel);
    }
  }

  // Pass it off to the decoder.
  engine()->voe()->network()->ReceivedRTPPacket(
      which_channel, packet->data(), packet->size(),
      webrtc::PacketTime(packet_time.timestamp, packet_time.not_before));
}

void WebRtcVoiceMediaChannel::OnRtcpReceived(
    rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
  // Sending channels need all RTCP packets with feedback information.
  // Even sender reports can contain attached report blocks.
  // Receiving channels need sender reports in order to create
  // correct receiver reports.
  int type = 0;
  if (!GetRtcpType(packet->data(), packet->size(), &type)) {
    LOG(LS_WARNING) << "Failed to parse type from received RTCP packet";
    return;
  }

  // If it is a sender report, find the channel that is listening.
  bool has_sent_to_default_channel = false;
  if (type == kRtcpTypeSR) {
    int which_channel =
        GetReceiveChannelNum(ParseSsrc(packet->data(), packet->size(), true));
    if (which_channel != -1) {
      engine()->voe()->network()->ReceivedRTCPPacket(
          which_channel, packet->data(), packet->size());

      if (IsDefaultChannel(which_channel))
        has_sent_to_default_channel = true;
    }
  }

  // SR may continue RR and any RR entry may correspond to any one of the send
  // channels. So all RTCP packets must be forwarded all send channels. VoE
  // will filter out RR internally.
  for (ChannelMap::iterator iter = send_channels_.begin();
       iter != send_channels_.end(); ++iter) {
    // Make sure not sending the same packet to default channel more than once.
    if (IsDefaultChannel(iter->second->channel()) &&
        has_sent_to_default_channel)
      continue;

    engine()->voe()->network()->ReceivedRTCPPacket(
        iter->second->channel(), packet->data(), packet->size());
  }
}

bool WebRtcVoiceMediaChannel::MuteStream(uint32 ssrc, bool muted) {
  int channel = (ssrc == 0) ? voe_channel() : GetSendChannelNum(ssrc);
  if (channel == -1) {
    LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
    return false;
  }
  if (engine()->voe()->volume()->SetInputMute(channel, muted) == -1) {
    LOG_RTCERR2(SetInputMute, channel, muted);
    return false;
  }
  // We set the AGC to mute state only when all the channels are muted.
  // This implementation is not ideal, instead we should signal the AGC when
  // the mic channel is muted/unmuted. We can't do it today because there
  // is no good way to know which stream is mapping to the mic channel.
  bool all_muted = muted;
  for (ChannelMap::const_iterator iter = send_channels_.begin();
       iter != send_channels_.end() && all_muted; ++iter) {
    if (engine()->voe()->volume()->GetInputMute(iter->second->channel(),
                                                all_muted)) {
      LOG_RTCERR1(GetInputMute, iter->second->channel());
      return false;
    }
  }

  webrtc::AudioProcessing* ap = engine()->voe()->base()->audio_processing();
  if (ap)
    ap->set_output_will_be_muted(all_muted);
  return true;
}

// TODO(minyue): SetMaxSendBandwidth() is subject to be renamed to
// SetMaxSendBitrate() in future.
bool WebRtcVoiceMediaChannel::SetMaxSendBandwidth(int bps) {
  LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBandwidth.";

  return SetSendBitrateInternal(bps);
}

bool WebRtcVoiceMediaChannel::SetSendBitrateInternal(int bps) {
  LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendBitrateInternal.";

  send_bitrate_setting_ = true;
  send_bitrate_bps_ = bps;

  if (!send_codec_) {
    LOG(LS_INFO) << "The send codec has not been set up yet. "
                 << "The send bitrate setting will be applied later.";
    return true;
  }

  // Bitrate is auto by default.
  // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by
  // SetMaxSendBandwith(0), the second call removes the previous limit.
  if (bps <= 0)
    return true;

  webrtc::CodecInst codec = *send_codec_;
  bool is_multi_rate = IsCodecMultiRate(codec);

  if (is_multi_rate) {
    // If codec is multi-rate then just set the bitrate.
    codec.rate = bps;
    if (!SetSendCodec(codec)) {
      LOG(LS_INFO) << "Failed to set codec " << codec.plname
                   << " to bitrate " << bps << " bps.";
      return false;
    }
    return true;
  } else {
    // If codec is not multi-rate and |bps| is less than the fixed bitrate
    // then fail. If codec is not multi-rate and |bps| exceeds or equal the
    // fixed bitrate then ignore.
    if (bps < codec.rate) {
      LOG(LS_INFO) << "Failed to set codec " << codec.plname
                   << " to bitrate " << bps << " bps"
                   << ", requires at least " << codec.rate << " bps.";
      return false;
    }
    return true;
  }
}

bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
  bool echo_metrics_on = false;
  // These can take on valid negative values, so use the lowest possible level
  // as default rather than -1.
  int echo_return_loss = -100;
  int echo_return_loss_enhancement = -100;
  // These can also be negative, but in practice -1 is only used to signal
  // insufficient data, since the resolution is limited to multiples of 4 ms.
  int echo_delay_median_ms = -1;
  int echo_delay_std_ms = -1;
  if (engine()->voe()->processing()->GetEcMetricsStatus(
          echo_metrics_on) != -1 && echo_metrics_on) {
    // TODO(ajm): we may want to use VoECallReport::GetEchoMetricsSummary
    // here, but it appears to be unsuitable currently. Revisit after this is
    // investigated: http://b/issue?id=5666755
    int erl, erle, rerl, anlp;
    if (engine()->voe()->processing()->GetEchoMetrics(
            erl, erle, rerl, anlp) != -1) {
      echo_return_loss = erl;
      echo_return_loss_enhancement = erle;
    }

    int median, std;
    float dummy;
    if (engine()->voe()->processing()->GetEcDelayMetrics(
        median, std, dummy) != -1) {
      echo_delay_median_ms = median;
      echo_delay_std_ms = std;
    }
  }

  webrtc::CallStatistics cs;
  unsigned int ssrc;
  webrtc::CodecInst codec;
  unsigned int level;

  for (ChannelMap::const_iterator channel_iter = send_channels_.begin();
       channel_iter != send_channels_.end(); ++channel_iter) {
    const int channel = channel_iter->second->channel();

    // Fill in the sender info, based on what we know, and what the
    // remote side told us it got from its RTCP report.
    VoiceSenderInfo sinfo;

    if (engine()->voe()->rtp()->GetRTCPStatistics(channel, cs) == -1 ||
        engine()->voe()->rtp()->GetLocalSSRC(channel, ssrc) == -1) {
      continue;
    }

    sinfo.add_ssrc(ssrc);
    sinfo.codec_name = send_codec_.get() ? send_codec_->plname : "";
    sinfo.bytes_sent = cs.bytesSent;
    sinfo.packets_sent = cs.packetsSent;
    // RTT isn't known until a RTCP report is received. Until then, VoiceEngine
    // returns 0 to indicate an error value.
    sinfo.rtt_ms = (cs.rttMs > 0) ? cs.rttMs : -1;

    // Get data from the last remote RTCP report. Use default values if no data
    // available.
    sinfo.fraction_lost = -1.0;
    sinfo.jitter_ms = -1;
    sinfo.packets_lost = -1;
    sinfo.ext_seqnum = -1;
    std::vector<webrtc::ReportBlock> receive_blocks;
    if (engine()->voe()->rtp()->GetRemoteRTCPReportBlocks(
            channel, &receive_blocks) != -1 &&
        engine()->voe()->codec()->GetSendCodec(channel, codec) != -1) {
      std::vector<webrtc::ReportBlock>::iterator iter;
      for (iter = receive_blocks.begin(); iter != receive_blocks.end();
           ++iter) {
        // Lookup report for send ssrc only.
        if (iter->source_SSRC == sinfo.ssrc()) {
          // Convert Q8 to floating point.
          sinfo.fraction_lost = static_cast<float>(iter->fraction_lost) / 256;
          // Convert samples to milliseconds.
          if (codec.plfreq / 1000 > 0) {
            sinfo.jitter_ms = iter->interarrival_jitter / (codec.plfreq / 1000);
          }
          sinfo.packets_lost = iter->cumulative_num_packets_lost;
          sinfo.ext_seqnum = iter->extended_highest_sequence_number;
          break;
        }
      }
    }

    // Local speech level.
    sinfo.audio_level = (engine()->voe()->volume()->
        GetSpeechInputLevelFullRange(level) != -1) ? level : -1;

    // TODO(xians): We are injecting the same APM logging to all the send
    // channels here because there is no good way to know which send channel
    // is using the APM. The correct fix is to allow the send channels to have
    // their own APM so that we can feed the correct APM logging to different
    // send channels. See issue crbug/264611 .
    sinfo.echo_return_loss = echo_return_loss;
    sinfo.echo_return_loss_enhancement = echo_return_loss_enhancement;
    sinfo.echo_delay_median_ms = echo_delay_median_ms;
    sinfo.echo_delay_std_ms = echo_delay_std_ms;
    // TODO(ajm): Re-enable this metric once we have a reliable implementation.
    sinfo.aec_quality_min = -1;
    sinfo.typing_noise_detected = typing_noise_detected_;

    info->senders.push_back(sinfo);
  }

  // Build the list of receivers, one for each receiving channel, or 1 in
  // a 1:1 call.
  std::vector<int> channels;
  for (ChannelMap::const_iterator it = receive_channels_.begin();
       it != receive_channels_.end(); ++it) {
    channels.push_back(it->second->channel());
  }
  if (channels.empty()) {
    channels.push_back(voe_channel());
  }

  // Get the SSRC and stats for each receiver, based on our own calculations.
  for (std::vector<int>::const_iterator it = channels.begin();
       it != channels.end(); ++it) {
    memset(&cs, 0, sizeof(cs));
    if (engine()->voe()->rtp()->GetRemoteSSRC(*it, ssrc) != -1 &&
        engine()->voe()->rtp()->GetRTCPStatistics(*it, cs) != -1 &&
        engine()->voe()->codec()->GetRecCodec(*it, codec) != -1) {
      VoiceReceiverInfo rinfo;
      rinfo.add_ssrc(ssrc);
      rinfo.bytes_rcvd = cs.bytesReceived;
      rinfo.packets_rcvd = cs.packetsReceived;
      // The next four fields are from the most recently sent RTCP report.
      // Convert Q8 to floating point.
      rinfo.fraction_lost = static_cast<float>(cs.fractionLost) / (1 << 8);
      rinfo.packets_lost = cs.cumulativeLost;
      rinfo.ext_seqnum = cs.extendedMax;
      rinfo.capture_start_ntp_time_ms = cs.capture_start_ntp_time_ms_;
      if (codec.pltype != -1) {
        rinfo.codec_name = codec.plname;
      }
      // Convert samples to milliseconds.
      if (codec.plfreq / 1000 > 0) {
        rinfo.jitter_ms = cs.jitterSamples / (codec.plfreq / 1000);
      }

      // Get jitter buffer and total delay (alg + jitter + playout) stats.
      webrtc::NetworkStatistics ns;
      if (engine()->voe()->neteq() &&
          engine()->voe()->neteq()->GetNetworkStatistics(
              *it, ns) != -1) {
        rinfo.jitter_buffer_ms = ns.currentBufferSize;
        rinfo.jitter_buffer_preferred_ms = ns.preferredBufferSize;
        rinfo.expand_rate =
            static_cast<float>(ns.currentExpandRate) / (1 << 14);
        rinfo.speech_expand_rate =
            static_cast<float>(ns.currentSpeechExpandRate) / (1 << 14);
        rinfo.secondary_decoded_rate =
            static_cast<float>(ns.currentSecondaryDecodedRate) / (1 << 14);
      }

      webrtc::AudioDecodingCallStats ds;
      if (engine()->voe()->neteq() &&
          engine()->voe()->neteq()->GetDecodingCallStatistics(
              *it, &ds) != -1) {
        rinfo.decoding_calls_to_silence_generator =
            ds.calls_to_silence_generator;
        rinfo.decoding_calls_to_neteq = ds.calls_to_neteq;
        rinfo.decoding_normal = ds.decoded_normal;
        rinfo.decoding_plc = ds.decoded_plc;
        rinfo.decoding_cng = ds.decoded_cng;
        rinfo.decoding_plc_cng = ds.decoded_plc_cng;
      }

      if (engine()->voe()->sync()) {
        int jitter_buffer_delay_ms = 0;
        int playout_buffer_delay_ms = 0;
        engine()->voe()->sync()->GetDelayEstimate(
            *it, &jitter_buffer_delay_ms, &playout_buffer_delay_ms);
        rinfo.delay_estimate_ms = jitter_buffer_delay_ms +
            playout_buffer_delay_ms;
      }

      // Get speech level.
      rinfo.audio_level = (engine()->voe()->volume()->
          GetSpeechOutputLevelFullRange(*it, level) != -1) ? level : -1;
      info->receivers.push_back(rinfo);
    }
  }

  return true;
}

void WebRtcVoiceMediaChannel::GetLastMediaError(
    uint32* ssrc, VoiceMediaChannel::Error* error) {
  ASSERT(ssrc != NULL);
  ASSERT(error != NULL);
  FindSsrc(voe_channel(), ssrc);
  *error = WebRtcErrorToChannelError(GetLastEngineError());
}

bool WebRtcVoiceMediaChannel::FindSsrc(int channel_num, uint32* ssrc) {
  rtc::CritScope lock(&receive_channels_cs_);
  ASSERT(ssrc != NULL);
  if (channel_num == -1 && send_ != SEND_NOTHING) {
    // Sometimes the VoiceEngine core will throw error with channel_num = -1.
    // This means the error is not limited to a specific channel.  Signal the
    // message using ssrc=0.  If the current channel is sending, use this
    // channel for sending the message.
    *ssrc = 0;
    return true;
  } else {
    // Check whether this is a sending channel.
    for (ChannelMap::const_iterator it = send_channels_.begin();
         it != send_channels_.end(); ++it) {
      if (it->second->channel() == channel_num) {
        // This is a sending channel.
        uint32 local_ssrc = 0;
        if (engine()->voe()->rtp()->GetLocalSSRC(
                channel_num, local_ssrc) != -1) {
          *ssrc = local_ssrc;
        }
        return true;
      }
    }

    // Check whether this is a receiving channel.
    for (ChannelMap::const_iterator it = receive_channels_.begin();
        it != receive_channels_.end(); ++it) {
      if (it->second->channel() == channel_num) {
        *ssrc = it->first;
        return true;
      }
    }
  }
  return false;
}

void WebRtcVoiceMediaChannel::OnError(uint32 ssrc, int error) {
  if (error == VE_TYPING_NOISE_WARNING) {
    typing_noise_detected_ = true;
  } else if (error == VE_TYPING_NOISE_OFF_WARNING) {
    typing_noise_detected_ = false;
  }
  SignalMediaError(ssrc, WebRtcErrorToChannelError(error));
}

int WebRtcVoiceMediaChannel::GetOutputLevel(int channel) {
  unsigned int ulevel;
  int ret =
      engine()->voe()->volume()->GetSpeechOutputLevel(channel, ulevel);
  return (ret == 0) ? static_cast<int>(ulevel) : -1;
}

int WebRtcVoiceMediaChannel::GetReceiveChannelNum(uint32 ssrc) {
  ChannelMap::iterator it = receive_channels_.find(ssrc);
  if (it != receive_channels_.end())
    return it->second->channel();
  return (ssrc == default_receive_ssrc_) ?  voe_channel() : -1;
}

int WebRtcVoiceMediaChannel::GetSendChannelNum(uint32 ssrc) {
  ChannelMap::iterator it = send_channels_.find(ssrc);
  if (it != send_channels_.end())
    return it->second->channel();

  return -1;
}

bool WebRtcVoiceMediaChannel::SetupSharedBandwidthEstimation(
    webrtc::VideoEngine* vie, int vie_channel) {
  shared_bwe_vie_ = vie;
  shared_bwe_vie_channel_ = vie_channel;

  if (!SetupSharedBweOnChannel(voe_channel())) {
    return false;
  }
  for (ChannelMap::iterator it = receive_channels_.begin();
      it != receive_channels_.end(); ++it) {
    if (!SetupSharedBweOnChannel(it->second->channel())) {
      return false;
    }
  }
  return true;
}

bool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec,
    const std::vector<AudioCodec>& all_codecs, webrtc::CodecInst* send_codec) {
  // Get the RED encodings from the parameter with no name. This may
  // change based on what is discussed on the Jingle list.
  // The encoding parameter is of the form "a/b"; we only support where
  // a == b. Verify this and parse out the value into red_pt.
  // If the parameter value is absent (as it will be until we wire up the
  // signaling of this message), use the second codec specified (i.e. the
  // one after "red") as the encoding parameter.
  int red_pt = -1;
  std::string red_params;
  CodecParameterMap::const_iterator it = red_codec.params.find("");
  if (it != red_codec.params.end()) {
    red_params = it->second;
    std::vector<std::string> red_pts;
    if (rtc::split(red_params, '/', &red_pts) != 2 ||
        red_pts[0] != red_pts[1] ||
        !rtc::FromString(red_pts[0], &red_pt)) {
      LOG(LS_WARNING) << "RED params " << red_params << " not supported.";
      return false;
    }
  } else if (red_codec.params.empty()) {
    LOG(LS_WARNING) << "RED params not present, using defaults";
    if (all_codecs.size() > 1) {
      red_pt = all_codecs[1].id;
    }
  }

  // Try to find red_pt in |codecs|.
  std::vector<AudioCodec>::const_iterator codec;
  for (codec = all_codecs.begin(); codec != all_codecs.end(); ++codec) {
    if (codec->id == red_pt)
      break;
  }

  // If we find the right codec, that will be the codec we pass to
  // SetSendCodec, with the desired payload type.
  if (codec != all_codecs.end() &&
    engine()->FindWebRtcCodec(*codec, send_codec)) {
  } else {
    LOG(LS_WARNING) << "RED params " << red_params << " are invalid.";
    return false;
  }

  return true;
}

bool WebRtcVoiceMediaChannel::EnableRtcp(int channel) {
  if (engine()->voe()->rtp()->SetRTCPStatus(channel, true) == -1) {
    LOG_RTCERR2(SetRTCPStatus, channel, 1);
    return false;
  }
  // TODO(juberti): Enable VQMon and RTCP XR reports, once we know what
  // what we want to do with them.
  // engine()->voe().EnableVQMon(voe_channel(), true);
  // engine()->voe().EnableRTCP_XR(voe_channel(), true);
  return true;
}

bool WebRtcVoiceMediaChannel::ResetRecvCodecs(int channel) {
  int ncodecs = engine()->voe()->codec()->NumOfCodecs();
  for (int i = 0; i < ncodecs; ++i) {
    webrtc::CodecInst voe_codec;
    if (engine()->voe()->codec()->GetCodec(i, voe_codec) != -1) {
      voe_codec.pltype = -1;
      if (engine()->voe()->codec()->SetRecPayloadType(
          channel, voe_codec) == -1) {
        LOG_RTCERR2(SetRecPayloadType, channel, ToString(voe_codec));
        return false;
      }
    }
  }
  return true;
}

bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) {
  if (playout) {
    LOG(LS_INFO) << "Starting playout for channel #" << channel;
    if (engine()->voe()->base()->StartPlayout(channel) == -1) {
      LOG_RTCERR1(StartPlayout, channel);
      return false;
    }
  } else {
    LOG(LS_INFO) << "Stopping playout for channel #" << channel;
    engine()->voe()->base()->StopPlayout(channel);
  }
  return true;
}

uint32 WebRtcVoiceMediaChannel::ParseSsrc(const void* data, size_t len,
                                        bool rtcp) {
  size_t ssrc_pos = (!rtcp) ? 8 : 4;
  uint32 ssrc = 0;
  if (len >= (ssrc_pos + sizeof(ssrc))) {
    ssrc = rtc::GetBE32(static_cast<const char*>(data) + ssrc_pos);
  }
  return ssrc;
}

// Convert VoiceEngine error code into VoiceMediaChannel::Error enum.
VoiceMediaChannel::Error
    WebRtcVoiceMediaChannel::WebRtcErrorToChannelError(int err_code) {
  switch (err_code) {
    case 0:
      return ERROR_NONE;
    case VE_CANNOT_START_RECORDING:
    case VE_MIC_VOL_ERROR:
    case VE_GET_MIC_VOL_ERROR:
    case VE_CANNOT_ACCESS_MIC_VOL:
      return ERROR_REC_DEVICE_OPEN_FAILED;
    case VE_SATURATION_WARNING:
      return ERROR_REC_DEVICE_SATURATION;
    case VE_REC_DEVICE_REMOVED:
      return ERROR_REC_DEVICE_REMOVED;
    case VE_RUNTIME_REC_WARNING:
    case VE_RUNTIME_REC_ERROR:
      return ERROR_REC_RUNTIME_ERROR;
    case VE_CANNOT_START_PLAYOUT:
    case VE_SPEAKER_VOL_ERROR:
    case VE_GET_SPEAKER_VOL_ERROR:
    case VE_CANNOT_ACCESS_SPEAKER_VOL:
      return ERROR_PLAY_DEVICE_OPEN_FAILED;
    case VE_RUNTIME_PLAY_WARNING:
    case VE_RUNTIME_PLAY_ERROR:
      return ERROR_PLAY_RUNTIME_ERROR;
    case VE_TYPING_NOISE_WARNING:
      return ERROR_REC_TYPING_NOISE_DETECTED;
    default:
      return VoiceMediaChannel::ERROR_OTHER;
  }
}

bool WebRtcVoiceMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter,
    int channel_id, const RtpHeaderExtension* extension) {
  bool enable = false;
  int id = 0;
  std::string uri;
  if (extension) {
    enable = true;
    id = extension->id;
    uri = extension->uri;
  }
  if ((engine()->voe()->rtp()->*setter)(channel_id, enable, id) != 0) {
    LOG_RTCERR4(*setter, uri, channel_id, enable, id);
    return false;
  }
  return true;
}

bool WebRtcVoiceMediaChannel::SetupSharedBweOnChannel(int voe_channel) {
  webrtc::ViENetwork* vie_network = NULL;
  int vie_channel = -1;
  if (options_.combined_audio_video_bwe.GetWithDefaultIfUnset(false) &&
      shared_bwe_vie_ != NULL && shared_bwe_vie_channel_ != -1) {
    vie_network = webrtc::ViENetwork::GetInterface(shared_bwe_vie_);
    vie_channel = shared_bwe_vie_channel_;
  }
  if (engine()->voe()->rtp()->SetVideoEngineBWETarget(voe_channel, vie_network,
      vie_channel) == -1) {
    LOG_RTCERR3(SetVideoEngineBWETarget, voe_channel, vie_network, vie_channel);
    if (vie_network != NULL) {
      // Don't fail if we're tearing down.
      return false;
    }
  }
  return true;
}

int WebRtcSoundclipStream::Read(void *buf, size_t len) {
  size_t res = 0;
  mem_.Read(buf, len, &res, NULL);
  return static_cast<int>(res);
}

int WebRtcSoundclipStream::Rewind() {
  mem_.Rewind();
  // Return -1 to keep VoiceEngine from looping.
  return (loop_) ? 0 : -1;
}

}  // namespace cricket

#endif  // HAVE_WEBRTC_VOICE
